enhance: Add comprehensive .gitignore for deb-mock project
Some checks failed
Build Deb-Mock Package / build (push) Successful in 54s
Lint Code / Lint All Code (push) Failing after 1s
Test Deb-Mock Build / test (push) Failing after 36s

- Add mock-specific build artifacts (chroot/, mock-*, mockroot/)
- Include package build files (*.deb, *.changes, *.buildinfo)
- Add development tools (.coverage, .pytest_cache, .tox)
- Include system files (.DS_Store, Thumbs.db, ._*)
- Add temporary and backup files (*.tmp, *.bak, *.backup)
- Include local configuration overrides (config.local.yaml, .env.local)
- Add test artifacts and documentation builds
- Comprehensive coverage for Python build system project

This ensures build artifacts, chroot environments, and development
tools are properly ignored in version control.
This commit is contained in:
robojerk 2025-08-18 23:37:49 -07:00
parent 1a559245ea
commit 4c0dcb2522
329 changed files with 27394 additions and 965 deletions

333
behave/steps/other.py Normal file
View file

@ -0,0 +1,333 @@
""" Generic testing steps """
import glob
import importlib
import json
import os
import shutil
import tarfile
import tempfile
from pathlib import Path
from hamcrest import (
assert_that,
contains_string,
ends_with,
equal_to,
has_item,
has_entries,
has_length,
not_,
)
import jsonschema
from behave import given, when, then # pylint: disable=no-name-in-module
from testlib.commands import run, no_output
# flake8: noqa
# pylint: disable=missing-function-docstring,function-redefined
# mypy: disable-error-code="no-redef"
def _first_int(string, max_lines=20):
for line in string.split("\n")[:max_lines]:
if not line:
continue
first_word = line.split()[0]
if first_word.isdigit():
return first_word
raise RuntimeError("unexpected dnf history output")
def add_cleanup_last_transaction(context):
# DNF5 support https://github.com/rpm-software-management/dnf5/issues/140
dnf = ["sudo", "/usr/bin/dnf", "history"]
_, out, _ = run(dnf + ["list"])
transaction_id = _first_int(out)
def _revert_transaction(_context):
cmd = dnf + ["undo", transaction_id, "-y"]
with no_output():
assert_that(run(cmd)[0], equal_to(0))
context.add_cleanup(_revert_transaction, context)
@given('an unique mock namespace')
def step_impl(context):
print(f"using uniqueext {context.uniqueext}")
context.uniqueext_used = True
@given('the {package} package {state} installed on host')
def step_impl(context, package, state):
"""
Install the package, and uninstall in post- action. If state is "not", then
just check it is not installed.
"""
is_installed, _, _ = run(["rpm", "-q", package])
# exit_status 0 => installed
is_installed = bool(not is_installed)
if "not" in state:
if not is_installed:
return # nothing to do
# Remove the package and schedule its removal
cmd = ["sudo", "dnf", "-y", "remove", package]
assert_that(run(cmd)[0], equal_to(0))
# schedule removal
add_cleanup_last_transaction(context)
return
if is_installed:
return
# install the package, and schedule removal
def _uninstall_pkg(_context):
cmd = ["sudo", "dnf", "-y", "remove", package]
with no_output():
assert_that(run(cmd)[0], equal_to(0))
cmd = ["sudo", "dnf", "-y", "install", package]
assert_that(run(cmd)[0], equal_to(0))
context.add_cleanup(_uninstall_pkg, context)
@given('pre-intitialized chroot')
def step_impl(context):
context.mock.init()
@given('a custom third-party repository is used for builds')
def step_impl(context):
context.add_repos.append(
"https://raw.githubusercontent.com/rpm-software-management/"
"mock-test-data/main/repo/"
)
@given("a created local repository")
def step_impl(context):
context.local_repo = tempfile.mkdtemp(prefix="mock-tests-local-repo-")
run(["createrepo_c", context.local_repo])
@given('the local repo contains a "{rpm}" RPM')
def step_impl(context, rpm):
rpm = context.download_rpm(rpm)
shutil.move(rpm, context.local_repo)
run(["createrepo_c", context.local_repo])
@given("the local repo is used for builds")
def step_impl(context):
context.add_repos.append(context.local_repo)
@when('a build is depending on third-party repo requested')
@when('a build which requires the "always-installable" RPM is requested')
def step_impl(context):
local_file = context.download_rpm("buildrequires-always-installable")
context.mock.rebuild([local_file])
@then('the build succeeds')
def step_impl(context):
assert os.path.exists(context.mock.resultdir)
rpms = glob.glob(os.path.join(context.mock.resultdir, "*.rpm"))
print("Found RPMs: " + ", ".join(rpms))
assert_that(rpms, has_item(ends_with(".src.rpm")))
assert_that(rpms, has_item(not_(ends_with(".src.rpm"))))
@when('mock is run with "{options}" options')
def step_impl(context, options):
options = options.split()
context.last_cmd = run(['mock'] + options)
@given('mock is always executed with "{options}"')
def step_impl(context, options):
options = options.split()
context.mock.common_opts += options
@then('the exit code is {code}')
def step_impl(context, code):
code = int(code)
assert_that(context.last_cmd[0], equal_to(code))
@then('the one-liner error contains "{expected_message}"')
def step_impl(context, expected_message):
err = context.last_cmd[2].splitlines()
assert_that(err, has_length(1))
assert_that(err[0], contains_string(expected_message))
def _rebuild_online(context, chroot=None, package=None):
package = package or "mock-test-bump-version-1-0.src.rpm"
url = context.test_storage + package
if chroot:
context.mock.chroot = chroot
context.mock.chroot_opt = chroot
context.mock.rebuild([url])
@when('an online source RPM is rebuilt')
def step_impl(context):
_rebuild_online(context)
@when('an online source RPM is rebuilt against {chroot}')
def step_impl(context, chroot):
_rebuild_online(context, chroot)
@when('an online SRPM {package} is rebuilt against {chroot}')
def step_impl(context, package, chroot):
_rebuild_online(context, chroot, package)
@then('{output} contains "{text}"')
def step_impl(context, output, text):
index = 1 if output == "stdout" else 2
real_output = context.last_cmd[index]
assert_that(real_output, contains_string(text))
@when('{call} method from {module} is called with {args} args')
def step_impl(context, call, module, args):
imp = importlib.import_module(module)
method = getattr(imp, call)
args = args.split()
context.last_method_call_retval = method(*args)
@then('the return value contains a field "{field}={value}"')
def step_impl(context, field, value):
assert_that(context.last_method_call_retval[field],
equal_to(value))
@when('deps for {srpm} are calculated against {chroot}')
def step_impl(context, srpm, chroot):
url = context.test_storage + srpm
context.mock.calculate_deps(url, chroot)
@when('a local repository is created from lockfile')
def step_impl(context):
mock_run = context.mock_runs["calculate-build-deps"][-1]
lockfile = mock_run["lockfile"]
context.local_repo = tempfile.mkdtemp(prefix="mock-tests-local-repo-")
cmd = ["mock-hermetic-repo", "--lockfile", lockfile, "--output-repo",
context.local_repo]
assert_that(run(cmd)[0], equal_to(0))
@when('a hermetic build is retriggered with the lockfile and repository')
def step_impl(context):
context.mock.hermetic_build()
@then('the produced lockfile is validated properly')
def step_impl(context):
mock_run = context.mock_runs["calculate-build-deps"][-1]
lockfile = mock_run["lockfile"]
with open(lockfile, "r", encoding="utf-8") as fd:
lockfile_data = json.load(fd)
assert_that(lockfile_data["buildroot"]["rpms"],
has_item(has_entries({"name": "filesystem"})))
schemafile = os.path.join(os.path.dirname(__file__), '..', '..',
"mock", "docs",
"buildroot-lock-schema-1.1.0.json")
with open(schemafile, "r", encoding="utf-8") as fd:
schema = json.load(fd)
jsonschema.validate(lockfile_data, schema)
@given('next mock call uses {option} option')
def step_impl(context, option):
context.next_mock_options.append(option)
@then("the directory {directory} is empty")
def step_impl(_, directory):
assert_that(os.path.exists(directory), equal_to(True))
assert_that(not os.listdir(directory), equal_to(True))
@given('chroot_scan is enabled for {regex}')
def step_impl(context, regex):
context.custom_config += f"""\
config_opts['plugin_conf']['chroot_scan_enable'] = True
config_opts['plugin_conf']['chroot_scan_opts']['regexes'] = ["{regex}"]
config_opts['plugin_conf']['chroot_scan_opts']['only_failed'] = False
"""
@then('{file} file is in chroot_scan result dir')
def step_impl(context, file):
resultdir = os.path.join(context.mock.resultdir, 'chroot_scan')
# Find the expected file
found = False
print("resultdir: ", resultdir)
for _, _, files in os.walk(resultdir):
for f in files:
print(f)
if f == file:
found = True
break
if found:
break
assert_that(found, equal_to(True))
@given('chroot_scan is configured to produce tarball')
def step_impl(context):
context.custom_config += """\
config_opts['plugin_conf']['chroot_scan_opts']['write_tar'] = True
"""
@then('ownership of all chroot_scan files is correct')
def step_impl(context):
resultdir = os.path.join(context.mock.resultdir, 'chroot_scan')
for root, dirs, files in os.walk(resultdir):
for f in files + dirs:
path = Path(root) / f
assert_that(path.group(), equal_to("mock"))
assert_that(path.owner(), equal_to(context.current_user))
@then('chroot_scan tarball has correct perms and provides dnf5.log')
def step_impl(context):
tarball = Path(context.mock.resultdir, 'chroot_scan.tar.gz')
with tarfile.open(tarball, 'r:gz') as tarf:
for file in tarf.getnames():
if file.endswith("dnf5.log"):
break
assert_that(tarball.group(), equal_to("mock"))
assert_that(tarball.owner(), equal_to(context.current_user))
@when('OCI tarball from {chroot} backed up and will be used')
def step_impl(context, chroot):
resultdir = f"/var/lib/mock/{chroot}-{context.uniqueext}/result"
tarball_base = "buildroot-oci.tar"
tarball = os.path.join(resultdir, tarball_base)
assert os.path.exists(tarball)
shutil.copy(tarball, context.workdir)
context.mock.buildroot_image = os.path.join(context.workdir, tarball_base)
@when('the {chroot} chroot is scrubbed')
def step_impl(context, chroot):
context.mock.scrub(chroot)