diff --git a/packit/api.py b/packit/api.py index e36477a62..a946bf19c 100644 --- a/packit/api.py +++ b/packit/api.py @@ -1018,6 +1018,20 @@ def sync_release( "Using the downstream specfile instead of the upstream one.", ) self.up.set_specfile(self.dg.specfile) + try: + downstream_spec_ver = self.dg.get_specfile_version() + if compare_versions(version, downstream_spec_ver) < 0: + msg = ( + f"Downstream specfile version {downstream_spec_ver} is lower " + f"than the version to propose ({version}). Skipping the update." + ) + logger.debug(msg) + raise ReleaseSkippedPackitException(msg) + self.dg.refresh_specfile() + + except FileNotFoundError: + # no downstream spec file + pass self.up.run_action( actions=ActionName.post_upstream_clone, diff --git a/packit/base_git.py b/packit/base_git.py index cfdd71c0b..f3a551fa1 100644 --- a/packit/base_git.py +++ b/packit/base_git.py @@ -11,6 +11,7 @@ import git import requests +import rpm from git import GitCommandError, PushInfo from ogr.abstract import AccessLevel, GitProject, PullRequest from specfile import Specfile @@ -138,6 +139,15 @@ def absolute_source_dir(self) -> Path: """ return self.absolute_specfile_dir + def get_specfile_version(self) -> str: + """provide version from specfile""" + # we need to get the version from rpm spec header + # (as the version tag might not be present directly in the specfile, + # but e.g. imported) + version = self.specfile.rpm_spec.sourceHeader[rpm.RPMTAG_VERSION] + logger.info(f"Version in spec file is {version!r}.") + return version + def create_branch( self, branch_name: str, diff --git a/packit/upstream.py b/packit/upstream.py index 2a3587891..c534fb5b1 100644 --- a/packit/upstream.py +++ b/packit/upstream.py @@ -13,7 +13,6 @@ from typing import Optional, Union import git -import rpm from packit.actions import ActionName from packit.base_git import PackitRepositoryBase @@ -256,15 +255,6 @@ def get_latest_released_version(self) -> Optional[str]: logger.info(f"Version in upstream registries is {version!r}.") return version - def get_specfile_version(self) -> str: - """provide version from specfile""" - # we need to get the version from rpm spec header - # (as the version tag might not be present directly in the specfile, - # but e.g. imported) - version = self.specfile.rpm_spec.sourceHeader[rpm.RPMTAG_VERSION] - logger.info(f"Version in spec file is {version!r}.") - return version - def get_version_from_action(self) -> str: """provide version from action""" action_output = self.get_output_from_action( diff --git a/tests/unit/test_api.py b/tests/unit/test_api.py index f6e88172c..cbfb2fb12 100644 --- a/tests/unit/test_api.py +++ b/tests/unit/test_api.py @@ -16,7 +16,7 @@ from packit.config.config import Config from packit.copr_helper import CoprHelper from packit.distgit import DistGit -from packit.exceptions import PackitException +from packit.exceptions import PackitException, ReleaseSkippedPackitException from packit.local_project import LocalProjectBuilder from packit.patches import PatchGenerator from packit.sync import SyncFilesItem @@ -340,6 +340,22 @@ def test_sync_release_check_pr_instructions(api_mock): api_mock.sync_release(version="1.1", dist_git_branch="_", add_pr_instructions=True) +def test_sync_release_downgrade(api_mock): + flexmock(PatchGenerator).should_receive("undo_identical") + api_mock.up.should_receive("get_specfile_version").and_return("0") + api_mock.up.should_receive("specfile").and_return( + flexmock().should_receive("reload").mock(), + ) + api_mock.up.package_config.should_receive("get_package_names_as_env").and_return({}) + api_mock.dg.should_receive("get_specfile_version").and_return("1.1") + with pytest.raises(ReleaseSkippedPackitException): + api_mock.sync_release( + version="1.0", + dist_git_branch="_", + add_pr_instructions=True, + ) + + @pytest.mark.parametrize( "resolved_bugs, result", [