enhance: Add comprehensive .gitignore for deb-mock project
- 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:
parent
1a559245ea
commit
4c0dcb2522
329 changed files with 27394 additions and 965 deletions
333
behave/steps/other.py
Normal file
333
behave/steps/other.py
Normal 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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue