#59 Do the heavy lifting of the builder plugin callback in the build root
Merged 4 years ago by asaleh. Opened 4 years ago by nphilipp.
fedora-infra/ nphilipp/rpmautospec master--process-in-buildroot  into  master

file added
+12
@@ -0,0 +1,12 @@ 

+ [run]

+ branch = True

+ source = rpmautospec koji_plugins

+ omit =

+ 

+ [report]

+ precision = 2

+ #fail_under = 99

+ exclude_lines =

+     pragma: no cover

+     def __repr__

+ show_missing = True

file modified
+13 -3
@@ -1,6 +1,16 @@ 

+ # setuptools related

+ /build/

+ /dist/

+ /rpmautospec.egg-info/

+ 

+ # Visual Studio Code configuration

+ /.vscode

+ 

+ # Coverage related

+ /htmlcov/

+ /.coverage

+ /coverage.xml

+ 

  # Byte-compiled / optimized / DLL files

  __pycache__/

  *.py[cod]

- .vscode

- dist/

- *.egg-info/

file modified
+2 -2
@@ -2,10 +2,10 @@ 

     tasks:

      - name: List project directory on the test system

        command: ls -al {{ansible_user_dir}}/{{zuul.project.src_dir}}

-     - name: install deps

+     - name: install dependencies

        become: yes

        package:

-         name: ['python3-pytest', 'python3-rpm', 'python3-koji', 'python3-pygit2']

+         name: ['python3-koji', 'python3-pytest', 'python3-pytest-cov', 'python3-rpm']

          state: present

      - name: run pytest

        command: chdir={{ansible_user_dir}}/{{zuul.project.src_dir}} python -m pytest

file modified
+7 -1
@@ -5,7 +5,13 @@ 

      - name: install deps

        become: yes

        package:

-         name: ['rpm-build', 'python3-devel', 'koji', 'python3-koji', 'pytest']

+         name:

+           - 'koji'

+           - 'python3-devel'

+           - 'python3-koji'

+           - 'python3-pytest'

+           - 'python3-pytest-cov'

+           - 'rpm-build'

          state: present

      - name: build source tarball

        command: chdir={{ansible_user_dir}}/{{zuul.project.src_dir}} python setup.py sdist

@@ -1,6 +1,32 @@ 

+ import inspect

+ 

  from koji.plugin import callback

  

- from rpmautospec.process_distgit import process_distgit

+ from rpmautospec import process_distgit

+ 

+ 

+ def _steal_buildroot_object_from_frame_stack():

+     buildroot = frame_info = frame = stack = None

+     try:

+         # Skip 2 frames, this fn and its caller

+         stack = inspect.stack()[2:]

+         for frame_info in stack:

+             if (

+                 type(frame.f_locals.get("self")).__name__ == "BuildSRPMFromSCMTask"

+                 and frame_info.function == "handler"

+             ):

+                 # The handler() method calls this broot internally

+                 buildroot = frame.f_locals.get("broot")

+                 break

+     finally:

+         # Explicitly delete references to frame objects to avoid memory leaks, see:

+         # https://docs.python.org/3/library/inspect.html#the-interpreter-stack

+         del frame, frame_info, stack

+ 

+     if not buildroot:

+         raise RuntimeError("Can't steal `broot` from BuildSRPMFromSCMTask.")

+ 

+     return buildroot

  

  

  @callback("postSCMCheckout")
@@ -10,5 +36,16 @@ 

          # i.e. maven and image builds don't have spec-files

          return

  

-     dist = build_tag["name"]

-     process_distgit(srcdir, dist, session)

+     if not process_distgit.needs_processing(srcdir):

+         return

+ 

+     buildroot = kwargs.get("buildroot")

+     if not buildroot:

+         buildroot = _steal_buildroot_object_from_frame_stack()

+ 

+     br_packages = buildroot.getPackageList()

+     if not any(p["name"] == "python3-rpmautospec" for p in br_packages):

+         buildroot.mock("--install", "python3-rpmautospec")

+ 

+     srcdir_within = buildroot.path_without_to_within(srcdir)

+     buildroot.mock("--shell", "rpmautospec", "process-distgit", "--process-specfile", srcdir_within)

file modified
+1
@@ -32,6 +32,7 @@ 

  BuildRequires:  koji

  BuildRequires:  python3-koji

  BuildRequires:  python%{python3_pkgversion}-pytest

+ BuildRequires:  python%{python3_pkgversion}-pytest-cov

  BuildRequires:  git

  %endif

  

file modified
+1 -1
@@ -42,4 +42,4 @@ 

  

      if args.subcommand:

          subcmd_module = subcmd_modules_by_name[args.subcommand]

-         subcmd_module.main(args)

+         sys.exit(subcmd_module.main(args))

file modified
+77 -26
@@ -7,7 +7,7 @@ 

  

  

  from rpmautospec.changelog import produce_changelog

- from rpmautospec.misc import koji_init

+ from rpmautospec.misc import koji_init, run_command

  from rpmautospec.release import holistic_heuristic_algo

  

  _log = logging.getLogger(__name__)
@@ -35,7 +35,23 @@ 

      )

  

      process_distgit_parser.add_argument("worktree_path", help="Path to the dist-git worktree")

-     process_distgit_parser.add_argument("dist", help="The dist tag")

+     process_distgit_parser.add_argument("dist", requires=False, help="The dist tag")

+ 

+     process_distgit_parser.add_argument(

+         "--check",

+         dest="actions",

+         action="append_const",

+         const="check",

+         help="Check if the spec file uses %autorel or %autochangelog macros at all.",

+     )

+ 

+     process_distgit_parser.add_argument(

+         "--process-specfile",

+         dest="action",

+         action="append_const",

+         const="process-specfile",

+         help="Generate next release and changelog values and write into the spec file.",

and write them into the spec file?

đź‘Ť

+     )

  

      return subcmd_name

  
@@ -51,20 +67,22 @@ 

      return release

  

  

- def process_distgit(srcdir, dist, session):

-     name = os.path.basename(srcdir)

-     new_rel = get_autorel(name, dist, session)

+ def get_specfile_name(srcdir):

      specfile_names = glob(f"{srcdir}/*.spec")

      if len(specfile_names) != 1:

-         # callback should be run only in if there is a single spec-file

+         # this code should be run only if there is a single spec-file

          return

  

-     specfile_name = specfile_names[0]

+     return specfile_names[0]

+ 

  

+ def check_distgit(srcdir):

      has_autorel = False

      changelog_lineno = None

      has_autochangelog = None

  

+     specfile_name = get_specfile_name(srcdir)

Hm, shouldn't we check if a specfile_name` was returned asget_specfile_namecan returnNone``.

You're right. AIUI, koji checks that beforehand, but we the code should be able to deal with this on its own.

+ 

      # Detect if %autorel, %autochangelog are in use

      with open(specfile_name, "r") as specfile:

          # Process line by line to cope with large files
@@ -84,29 +102,62 @@ 

                      # Anything else than %autochangelog after %changelog -> hands off

                      has_autochangelog = False

  

-     if has_autorel or has_autochangelog:

-         with open(specfile_name, "r") as specfile, tempfile.NamedTemporaryFile("w") as tmp_specfile:

-             # Process the spec file into a temporary file...

-             if has_autorel:

-                 # Write %autorel macro header

-                 with open(autorel_macro_path, "r") as autorel_macro_file:

-                     print(autorel_template.format(autorel_normal=new_rel), file=tmp_specfile)

-                     for line in autorel_macro_file:

-                         print(line, file=tmp_specfile, end="")

+     return has_autorel, has_autochangelog, changelog_lineno

+ 

+ 

+ def needs_processing(srcdir):

+     has_autorel, has_autochangelog, changelog_lineno = check_distgit(srcdir)

+     return has_autorel or has_autochangelog

+ 

+ 

+ def process_specfile(srcdir, dist, session, has_autorel, has_autochangelog, changelog_lineno):

+     name = os.path.basename(srcdir)

+     specfile_name = get_specfile_name(srcdir)

Same as above get_specfile_name can return None, should we handle it?

+ 

+     if not dist:

+         dist = run_command(["rpm", "--eval", "%dist"])

+ 

+     new_rel = get_autorel(name, dist, session)

+     with open(specfile_name, "r") as specfile, tempfile.NamedTemporaryFile("w") as tmp_specfile:

+         # Process the spec file into a temporary file...

+         if has_autorel:

+             # Write %autorel macro header

+             with open(autorel_macro_path, "r") as autorel_macro_file:

+                 print(autorel_template.format(autorel_normal=new_rel), file=tmp_specfile)

+                 for line in autorel_macro_file:

+                     print(line, file=tmp_specfile, end="")

+ 

+         for lineno, line in enumerate(specfile, start=1):

+             if has_autochangelog and lineno > changelog_lineno:

+                 break

+ 

+             print(line, file=tmp_specfile, end="")

+ 

+         if has_autochangelog:

+             print("\n".join(produce_changelog(srcdir, latest_rel=new_rel)), file=tmp_specfile)

+ 

+         tmp_specfile.flush()

+ 

+         # ...and copy it back (potentially across device boundaries)

+         shutil.copy2(tmp_specfile.name, specfile_name)

+ 

  

-             for lineno, line in enumerate(specfile, start=1):

-                 if has_autochangelog and lineno > changelog_lineno:

-                     break

+ def process_distgit(srcdir, dist, session, actions=None):

+     if not actions:

+         actions = ["check", "process-specfile"]

  

-                 print(line, file=tmp_specfile, end="")

+     retval = True

  

-             if has_autochangelog:

-                 print("\n".join(produce_changelog(srcdir, latest_rel=new_rel)), file=tmp_specfile)

+     if "check" in actions or "process-specfile" in actions:

+         has_autorel, has_autochangelog, changelog_lineno = check_distgit(srcdir)

+         processing_necessary = has_autorel or has_autochangelog

+         if "process-specfile" not in actions:

+             retval = processing_necessary

  

-             tmp_specfile.flush()

+     if "process-specfile" in actions and processing_necessary:

processing_necessary may not be defined here if --check wasn't specified.

if "process-specfile" is in actions, it is defined (the check is required before actually doing things).

Oh, I see it now, okido :)

+         process_specfile(srcdir, dist, session, has_autorel, has_autochangelog, changelog_lineno)

  

-             # ...and copy it back (potentially across device boundaries)

-             shutil.copy2(tmp_specfile.name, specfile_name)

+     return retval

  

  

  def main(args):
@@ -116,4 +167,4 @@ 

      dist = args.dist

      kojiclient = koji_init(args.koji_url)

  

-     process_distgit(repopath, dist, kojiclient)

+     return 0 if process_distgit(repopath, dist, kojiclient, args.actions) else 1

file modified
+3
@@ -7,3 +7,6 @@ 

  # Configure flake8-import-order

  application-import-names = rpmautospec,koji_plugins

  import-order-style = google

+ 

+ [tool:pytest]

+ addopts = --cov-config .coveragerc --cov=rpmautospec --cov=koji_plugins --cov-report term --cov-report xml --cov-report html

file modified
+1
@@ -1,1 +1,2 @@ 

  pytest

+ pytest-cov

@@ -1,163 +1,125 @@ 

- import os

- import shutil

- from subprocess import check_output

- import tarfile

- import tempfile

- from unittest.mock import MagicMock

+ from unittest import mock

  

  import pytest

  

  from koji_plugins.rpmautospec_builder import process_distgit_cb

  

  

- __here__ = os.path.dirname(__file__)

+ class TestRpmautospecBuilder:

+     """Test the rpmautospec builder plugin for Koji."""

  

- commit = "5ab06967a36e72f66add9b6cfe08bd98f8900693"

- url = f"git+https://src.fedoraproject.org/rpms/dummy-test-package-gloster.git#{commit}"

+     commit = "5ab06967a36e72f66add9b6cfe08bd98f8900693"

+     url = f"git+https://src.fedoraproject.org/rpms/dummy-test-package-gloster.git#{commit}"

+ 

+     data_scm_info = {

+         "host": "src.fedoraproject.org",

+         "module": "",

+         "repository": "/rpms/dummy-test-package-gloster.git",

+         "revision": commit,

+         "scheme": "git+https://",

+         "scmtype": "GIT",

+         "url": url,

+         "user": None,

+     }

+ 

+     data_build_tag = {

+         "id": 11522,

+         "name": "f32-build",

+         "arches": "armv7hl i686 x86_64 aarch64 ppc64le s390x",

+         "extra": {},

+         "locked": False,

+         "maven_include_all": False,

+         "maven_support": False,

+         "perm": "admin",

+         "perm_id": 1,

+     }

+ 

+     @pytest.mark.parametrize(

+         "testcase",

+         (

+             "normal",

+             "no buildroot supplied",

+             "rpmautospec installed",

+             "other taskinfo method",

+             "skip processing",

+         ),

+     )

+     @mock.patch("rpmautospec.process_distgit.needs_processing")

+     @mock.patch("koji_plugins.rpmautospec_builder._steal_buildroot_object_from_frame_stack")

+     def test_process_distgit_cb(self, steal_buildroot_fn, needs_processing_fn, testcase):

+         """Test the process_distgit_cb() function"""

+         buildroot_supplied = testcase != "no buildroot supplied"

+         rpmautospec_installed = testcase == "rpmautospec installed"

+         taskinfo_method_responsible = testcase != "other taskinfo method"

+         skip_processing = testcase != "skip processing"

+ 

+         # prepare test environment

+         srcdir_within = "/builddir/build/BUILD/something"

+         unpacked_repo_dir = f"/var/lib/mock/some-root/{srcdir_within}"

+         args = ["postSCMCheckout"]

+         kwargs = {

+             "scminfo": self.data_scm_info,

+             "build_tag": self.data_build_tag,

+             "scratch": mock.MagicMock(),

+             "srcdir": unpacked_repo_dir,

+             "taskinfo": {"method": "buildSRPMFromSCM"},

+             "session": mock.MagicMock(),

+         }

+ 

+         if not taskinfo_method_responsible:

+             kwargs["taskinfo"]["method"] = "not the method you're looking for"

+ 

+         if skip_processing:

+             needs_processing_fn.return_value = False

+ 

+         buildroot = mock.MagicMock()

+         installed_packages = [

+             {"name": "foo", "version": "1.0", "release": "3"},

+             {"name": "bar", "version": "1.1", "release": "1"},

+             {"name": "baz", "version": "2.0", "release": "2"},

+         ]

+ 

+         if rpmautospec_installed:

+             installed_packages.append(

+                 {"name": "python3-rpmautospec", "version": "0.1", "release": "1"}

+             )

  

- data_scm_info = {

-     "host": "src.fedoraproject.org",

-     "module": "",

-     "repository": "/rpms/dummy-test-package-gloster.git",

-     "revision": "5ab06967a36e72f66add9b6cfe08bd98f8900693",

-     "scheme": "git+https://",

-     "scmtype": "GIT",

-     "url": url,

-     "user": None,

- }

+         buildroot.getPackageList.return_value = installed_packages

  

- data_build_tag = {"id": "dsttag", "tag_id": "fc32", "tag_name": "fc32"}

+         if buildroot_supplied:

+             kwargs["buildroot"] = buildroot

+         else:

+             steal_buildroot_fn.return_value = buildroot

  

+         buildroot.path_without_to_within.return_value = srcdir_within

  

- class TestRpmautospecBuilder:

-     """Test the rpmautospec builder plugin for Koji."""

+         # test the callback

+         process_distgit_cb(*args, **kwargs)

  

-     autorel_autochangelog_cases = [

-         (autorel_case, autochangelog_case)

-         for autorel_case in ("unchanged", "with braces")

-         for autochangelog_case in (

-             "unchanged",

-             "changelog case insensitive",

-             "changelog trailing garbage",

-             "line in between",

-             "trailing line",

-             "with braces",

-         )

-     ]

- 

-     @staticmethod

-     def fuzz_spec_file(spec_file_path, autorel_case, autochangelog_case):

-         """Fuzz a spec file in ways which shouldn't change the outcome"""

- 

-         with open(spec_file_path, "r") as orig, open(spec_file_path + ".new", "w") as new:

-             for line in orig:

-                 if line.startswith("Release:") and autorel_case != "unchanged":

-                     if autorel_case == "with braces":

-                         print("Release:        %{autorel}", file=new)

-                     else:

-                         raise ValueError(f"Unknown autorel_case: {autorel_case}")

-                 elif line.strip() == "%changelog" and autochangelog_case != "unchanged":

-                     if autochangelog_case == "changelog case insensitive":

-                         print("%ChAnGeLoG", file=new)

-                     elif autochangelog_case == "changelog trailing garbage":

-                         print("%changelog with trailing garbage yes this works", file=new)

-                     elif autochangelog_case == "line in between":

-                         print("%changelog\n\n%autochangelog", file=new)

-                         break

-                     elif autochangelog_case == "trailing line":

-                         print("%changelog\n%autochangelog\n", file=new)

-                         break

-                     elif autochangelog_case == "with braces":

-                         print("%changelog\n%{autochangelog}", file=new)

-                         break

-                     else:

-                         raise ValueError(f"Unknown autochangelog_case: {autochangelog_case}")

-                 else:

-                     print(line, file=new, end="")

- 

-         os.rename(spec_file_path + ".new", spec_file_path)

- 

-     @pytest.mark.parametrize("autorel_case,autochangelog_case", autorel_autochangelog_cases)

-     def test_autospec_cb(self, autorel_case, autochangelog_case):

-         """Test the autospec_cb() function"""

-         with tempfile.TemporaryDirectory() as workdir:

-             with tarfile.open(

-                 os.path.join(

-                     __here__,

-                     os.path.pardir,

-                     "test-data",

-                     "repodata",

-                     "dummy-test-package-gloster-git.tar.gz",

-                 )

-             ) as tar:

-                 tar.extractall(path=workdir)

- 

-             unpacked_repo_dir = os.path.join(workdir, "dummy-test-package-gloster")

-             unprocessed_spec_file_path = os.path.join(

-                 unpacked_repo_dir, "dummy-test-package-gloster.spec",

-             )

+         # verify what the callback did

+         if not taskinfo_method_responsible:

+             needs_processing_fn.assert_not_called()

+             return

  

-             if autorel_case != "unchanged" or autochangelog_case != "unchanged":

-                 self.fuzz_spec_file(unprocessed_spec_file_path, autorel_case, autochangelog_case)

- 

-             koji_session = MagicMock()

-             koji_session.getPackageID.return_value = 30489

-             name = "dummy-test-package-gloster"

-             builds = [

-                 {

-                     "epoch": None,

-                     "nvr": f"{name}-0-{x}.f32",

-                     "name": name,

-                     "release": f"{x}.fc32",

-                     "version": "0",

-                 }

-                 for x in range(2, 7)

-             ]

-             koji_session.listBuilds.return_value = builds

-             args = ["postSCMCheckout"]

-             kwargs = {

-                 "scminfo": data_scm_info,

-                 "build_tag": data_build_tag,

-                 "scratch": MagicMock(),

-                 "srcdir": unpacked_repo_dir,

-                 "taskinfo": {"method": "buildSRPMFromSCM"},

-                 "session": koji_session,

-             }

- 

-             process_distgit_cb(*args, **kwargs)

- 

-             expected_spec_file_path = os.path.join(

-                 __here__,

-                 os.path.pardir,

-                 "test-data",

-                 "repodata",

-                 "dummy-test-package-gloster.spec.expected",

-             )

+         needs_processing_fn.assert_called_once_with(unpacked_repo_dir)

+ 

+         if skip_processing:

+             buildroot.getPackageList.assert_not_called()

+             return

+ 

+         buildroot.getPackageList.assert_called_once()

+         buildroot.path_without_to_within.assert_called_once()

  

-             with tempfile.NamedTemporaryFile() as tmpspec:

-                 if autorel_case != "unchanged" or autochangelog_case != "unchanged":

-                     if autochangelog_case not in (

-                         "changelog case insensitive",

-                         "changelog trailing garbage",

-                     ):

-                         # "%changelog", "%ChAnGeLoG", ... stay verbatim, trick fuzz_spec_file() to

-                         # leave the rest of the cases as is, the %autorel macro is expanded.

-                         autochangelog_case = "unchanged"

-                     shutil.copy2(expected_spec_file_path, tmpspec.name)

-                     expected_spec_file_path = tmpspec.name

-                     self.fuzz_spec_file(expected_spec_file_path, autorel_case, autochangelog_case)

- 

-                 rpm_cmd = ["rpm", "--define", "dist .fc32", "--specfile"]

- 

-                 unprocessed_cmd = rpm_cmd + [unprocessed_spec_file_path]

-                 expected_cmd = rpm_cmd + [expected_spec_file_path]

- 

-                 q_release = ["--qf", "%{release}\n"]

-                 assert check_output(unprocessed_cmd + q_release) == check_output(

-                     expected_cmd + q_release

-                 )

- 

-                 q_changelog = ["--changelog"]

-                 assert check_output(unprocessed_cmd + q_changelog) == check_output(

-                     expected_cmd + q_changelog

-                 )

+         if buildroot_supplied:

+             steal_buildroot_fn.assert_not_called()

+         else:

+             steal_buildroot_fn.assert_called_once_with()

+ 

+         if rpmautospec_installed:

+             assert not any("--install" in call[0] for call in buildroot.mock.call_args_list)

+         else:

+             buildroot.mock.assert_any_call("--install", "python3-rpmautospec")

+ 

+         buildroot.mock.assert_called_with(

+             "--shell", "rpmautospec", "process-distgit", "--process-specfile", srcdir_within,

+         )

@@ -1,15 +1,148 @@ 

- from rpmautospec.process_distgit import is_autorel

+ import os

+ import shutil

+ from subprocess import check_output

+ import tarfile

+ import tempfile

+ from unittest import mock

+ 

+ import pytest

+ 

+ from rpmautospec import process_distgit

+ 

+ 

+ __here__ = os.path.dirname(__file__)

  

  

  class TestProcessDistgit:

      """Test the rpmautospec.process_distgit module"""

  

+     autorel_autochangelog_cases = [

+         (autorel_case, autochangelog_case)

+         for autorel_case in ("unchanged", "with braces")

+         for autochangelog_case in (

+             "unchanged",

+             "changelog case insensitive",

+             "changelog trailing garbage",

+             "line in between",

+             "trailing line",

+             "with braces",

+         )

+     ]

+ 

+     @staticmethod

+     def fuzz_spec_file(spec_file_path, autorel_case, autochangelog_case):

+         """Fuzz a spec file in ways which shouldn't change the outcome"""

+ 

+         with open(spec_file_path, "r") as orig, open(spec_file_path + ".new", "w") as new:

+             for line in orig:

+                 if line.startswith("Release:") and autorel_case != "unchanged":

+                     if autorel_case == "with braces":

+                         print("Release:        %{autorel}", file=new)

+                     else:

+                         raise ValueError(f"Unknown autorel_case: {autorel_case}")

+                 elif line.strip() == "%changelog" and autochangelog_case != "unchanged":

+                     if autochangelog_case == "changelog case insensitive":

+                         print("%ChAnGeLoG", file=new)

+                     elif autochangelog_case == "changelog trailing garbage":

+                         print("%changelog with trailing garbage yes this works", file=new)

+                     elif autochangelog_case == "line in between":

+                         print("%changelog\n\n%autochangelog", file=new)

+                         break

+                     elif autochangelog_case == "trailing line":

+                         print("%changelog\n%autochangelog\n", file=new)

+                         break

+                     elif autochangelog_case == "with braces":

+                         print("%changelog\n%{autochangelog}", file=new)

+                         break

+                     else:

+                         raise ValueError(f"Unknown autochangelog_case: {autochangelog_case}")

+                 else:

+                     print(line, file=new, end="")

+ 

+         os.rename(spec_file_path + ".new", spec_file_path)

+ 

      def test_is_autorel(self):

-         assert is_autorel("Release: %{autorel}")

-         assert is_autorel("Release: %autorel")

-         assert is_autorel("release: %{autorel}")

-         assert is_autorel(" release :  %{autorel}")

-         assert is_autorel("Release: %{autorel_special}")

- 

-         assert not is_autorel("NotRelease: %{autorel}")

-         assert not is_autorel("release: 1%{?dist}")

+         assert process_distgit.is_autorel("Release: %{autorel}")

+         assert process_distgit.is_autorel("Release: %autorel")

+         assert process_distgit.is_autorel("release: %{autorel}")

+         assert process_distgit.is_autorel(" release :  %{autorel}")

+         assert process_distgit.is_autorel("Release: %{autorel_special}")

+ 

+         assert not process_distgit.is_autorel("NotRelease: %{autorel}")

+         assert not process_distgit.is_autorel("release: 1%{?dist}")

+ 

+     @pytest.mark.parametrize("autorel_case,autochangelog_case", autorel_autochangelog_cases)

+     def test_process_distgit(self, autorel_case, autochangelog_case):

+         """Test the process_distgit() function"""

+         with tempfile.TemporaryDirectory() as workdir:

+             with tarfile.open(

+                 os.path.join(

+                     __here__,

+                     os.path.pardir,

+                     "test-data",

+                     "repodata",

+                     "dummy-test-package-gloster-git.tar.gz",

+                 )

+             ) as tar:

+                 tar.extractall(path=workdir)

+ 

+             unpacked_repo_dir = os.path.join(workdir, "dummy-test-package-gloster")

+             unprocessed_spec_file_path = os.path.join(

+                 unpacked_repo_dir, "dummy-test-package-gloster.spec",

+             )

+ 

+             if autorel_case != "unchanged" or autochangelog_case != "unchanged":

+                 self.fuzz_spec_file(unprocessed_spec_file_path, autorel_case, autochangelog_case)

+ 

+             koji_session = mock.MagicMock()

+             koji_session.getPackageID.return_value = 30489

+             name = "dummy-test-package-gloster"

+             builds = [

+                 {

+                     "epoch": None,

+                     "nvr": f"{name}-0-{x}.f32",

+                     "name": name,

+                     "release": f"{x}.fc32",

+                     "version": "0",

+                 }

+                 for x in range(2, 7)

+             ]

+             koji_session.listBuilds.return_value = builds

+ 

+             process_distgit.process_distgit(unpacked_repo_dir, "fc32", koji_session)

+ 

+             expected_spec_file_path = os.path.join(

+                 __here__,

+                 os.path.pardir,

+                 "test-data",

+                 "repodata",

+                 "dummy-test-package-gloster.spec.expected",

+             )

+ 

+             with tempfile.NamedTemporaryFile() as tmpspec:

+                 if autorel_case != "unchanged" or autochangelog_case != "unchanged":

+                     if autochangelog_case not in (

+                         "changelog case insensitive",

+                         "changelog trailing garbage",

+                     ):

+                         # "%changelog", "%ChAnGeLoG", ... stay verbatim, trick fuzz_spec_file() to

+                         # leave the rest of the cases as is, the %autorel macro is expanded.

+                         autochangelog_case = "unchanged"

+                     shutil.copy2(expected_spec_file_path, tmpspec.name)

+                     expected_spec_file_path = tmpspec.name

+                     self.fuzz_spec_file(expected_spec_file_path, autorel_case, autochangelog_case)

+ 

+                 rpm_cmd = ["rpm", "--define", "dist .fc32", "--specfile"]

+ 

+                 unprocessed_cmd = rpm_cmd + [unprocessed_spec_file_path]

+                 expected_cmd = rpm_cmd + [expected_spec_file_path]

+ 

+                 q_release = ["--qf", "%{release}\n"]

+                 assert check_output(unprocessed_cmd + q_release) == check_output(

+                     expected_cmd + q_release

+                 )

+ 

+                 q_changelog = ["--changelog"]

+                 assert check_output(unprocessed_cmd + q_changelog) == check_output(

+                     expected_cmd + q_changelog

+                 )

This should fix #58 (and #55, #56) when applied.

Build failed.

3 new commits added

  • Make .gitignore prettier
  • Determine coverage when running tests
  • Don't install python3-pygit2 for CI tests
4 years ago

Build failed.

rebased onto 6cdb2a3

4 years ago

7 new commits added

  • Run process-distgit in the build root if necessary
  • Make `dist` optional
  • Set exit code when run from CLI
  • Split stages of processing a dist-git repository
  • Make .gitignore prettier
  • Determine coverage when running tests
  • Don't install python3-pygit2 for CI tests
4 years ago

Build failed.

7 new commits added

  • Run process-distgit in the build root if necessary
  • Make `dist` optional
  • Set exit code when run from CLI
  • Split stages of processing a dist-git repository
  • Make .gitignore prettier
  • Determine coverage when running tests
  • Don't install python3-pygit2 for CI tests
4 years ago

Build succeeded.

Don't really like flags, and we don't initialize it dynamically. Probably should be two different functions? check_distgit_simple ? Or we could return return None if there is no autochangelog and no autorel, you could then use the truthiness of the value (instead of being it a tuple) (but I don't really like none as a return value anyway :D )

I had it like this at first, in two functions—check_distgit_simple() wrapping check_distgit() without the flag. I'll revert to that.

7 new commits added

  • Run process-distgit in the build root if necessary
  • Make `dist` optional
  • Set exit code when run from CLI
  • Split stages of processing a dist-git repository
  • Make .gitignore prettier
  • Determine coverage when running tests
  • Don't install python3-pygit2 for CI tests
4 years ago

As discussed, changing the name of the wrapping function from check_distgit_simple() to needs_processing().

Build succeeded.

Pull-Request has been merged by asaleh

4 years ago

Hm, shouldn't we check if a specfile_name` was returned asget_specfile_namecan returnNone``.

and write them into the spec file?

Same as above get_specfile_name can return None, should we handle it?

You're right. AIUI, koji checks that beforehand, but we the code should be able to deal with this on its own.

processing_necessary may not be defined here if --check wasn't specified.

if "process-specfile" is in actions, it is defined (the check is required before actually doing things).