diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c6a5e..42bf16c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [0.7.1] - 2025-12-09 + +* Fix floating 'latest' tag logic: dereference annotated target (vX.Y.Z^{}), add tag message to avoid Git errors, ensure best-effort update without blocking releases, and update unit tests (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff). + + ## [0.7.0] - 2025-12-09 * Add Git helpers for branch sync and floating 'latest' tag in the release workflow, ensure main/master are updated from origin before tagging, and extend unit/e2e tests including 'pkgmgr release --help' coverage (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff) diff --git a/PKGBUILD b/PKGBUILD index b1d0842..8132fce 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: Kevin Veen-Birkenbach pkgname=package-manager -pkgver=0.7.0 +pkgver=0.7.1 pkgrel=1 pkgdesc="Local-flake wrapper for Kevin's package-manager (Nix-based)." arch=('any') diff --git a/debian/changelog b/debian/changelog index 858e893..fc26fe5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +package-manager (0.7.1-1) unstable; urgency=medium + + * Fix floating 'latest' tag logic: dereference annotated target (vX.Y.Z^{}), add tag message to avoid Git errors, ensure best-effort update without blocking releases, and update unit tests (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff). + + -- Kevin Veen-Birkenbach Tue, 09 Dec 2025 15:26:54 +0100 + package-manager (0.7.0-1) unstable; urgency=medium * Add Git helpers for branch sync and floating 'latest' tag in the release workflow, ensure main/master are updated from origin before tagging, and extend unit/e2e tests including 'pkgmgr release --help' coverage (see ChatGPT conversation: https://chatgpt.com/share/69383024-efa4-800f-a875-129b81fa40ff) diff --git a/flake.nix b/flake.nix index 930bd63..db6daff 100644 --- a/flake.nix +++ b/flake.nix @@ -31,7 +31,7 @@ rec { pkgmgr = pyPkgs.buildPythonApplication { pname = "package-manager"; - version = "0.7.0"; + version = "0.7.1"; # Use the git repo as source src = ./.; diff --git a/package-manager.spec b/package-manager.spec index 57cdd17..980b69b 100644 --- a/package-manager.spec +++ b/package-manager.spec @@ -1,5 +1,5 @@ Name: package-manager -Version: 0.7.0 +Version: 0.7.1 Release: 1%{?dist} Summary: Wrapper that runs Kevin's package-manager via Nix flake diff --git a/pkgmgr/actions/release/__init__.py b/pkgmgr/actions/release/__init__.py index 328d797..34ff0ae 100644 --- a/pkgmgr/actions/release/__init__.py +++ b/pkgmgr/actions/release/__init__.py @@ -171,8 +171,15 @@ def _release_impl( run_git_command("git push origin --tags") # Move 'latest' to the new release tag so the newest SemVer is always - # marked as latest. - update_latest_tag(new_tag, preview=False) + # marked as latest. This is best-effort and must not break the release. + try: + update_latest_tag(new_tag, preview=False) + except GitError as exc: # pragma: no cover + print( + f"[WARN] Failed to update floating 'latest' tag for {new_tag}: {exc}\n" + "[WARN] The release itself completed successfully; only the " + "'latest' tag was not updated." + ) print(f"Release {new_ver_str} completed.") diff --git a/pkgmgr/actions/release/git_ops.py b/pkgmgr/actions/release/git_ops.py index 040ef00..3d72b1a 100644 --- a/pkgmgr/actions/release/git_ops.py +++ b/pkgmgr/actions/release/git_ops.py @@ -71,12 +71,25 @@ def sync_branch_with_remote(branch: str, preview: bool = False) -> None: def update_latest_tag(new_tag: str, preview: bool = False) -> None: """ Move the floating 'latest' tag to the newly created release tag. + + Implementation details: + - We explicitly dereference the tag object via `^{}` so that + 'latest' always points at the underlying commit, not at another tag. + - We create/update 'latest' as an annotated tag with a short message so + Git configurations that enforce annotated/signed tags do not fail + with "no tag message". """ - print(f"[INFO] Updating 'latest' tag to point at {new_tag}...") + target_ref = f"{new_tag}^{{}}" + print(f"[INFO] Updating 'latest' tag to point at {new_tag} (commit {target_ref})...") + if preview: - print(f"[PREVIEW] Would run: git tag -f latest {new_tag}") + print(f"[PREVIEW] Would run: git tag -f -a latest {target_ref} " + f'-m "Floating latest tag for {new_tag}"') print("[PREVIEW] Would run: git push origin latest --force") return - run_git_command(f"git tag -f latest {new_tag}") + run_git_command( + f'git tag -f -a latest {target_ref} ' + f'-m "Floating latest tag for {new_tag}"' + ) run_git_command("git push origin latest --force") diff --git a/pyproject.toml b/pyproject.toml index f08904b..71c8abe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" [project] name = "package-manager" -version = "0.7.0" +version = "0.7.1" description = "Kevin's package-manager tool (pkgmgr)" readme = "README.md" requires-python = ">=3.11" diff --git a/tests/unit/pkgmgr/actions/release/test_git_ops.py b/tests/unit/pkgmgr/actions/release/test_git_ops.py index 9220b8d..1b53867 100644 --- a/tests/unit/pkgmgr/actions/release/test_git_ops.py +++ b/tests/unit/pkgmgr/actions/release/test_git_ops.py @@ -75,16 +75,19 @@ class TestUpdateLatestTag(unittest.TestCase): mock_run_git_command.assert_not_called() @patch("pkgmgr.actions.release.git_ops.run_git_command") - def test_update_latest_tag_real_calls_git( + def test_update_latest_tag_real_calls_git_with_dereference_and_message( self, mock_run_git_command, ) -> None: update_latest_tag("v1.2.3", preview=False) calls = [c.args[0] for c in mock_run_git_command.call_args_list] - self.assertIn("git tag -f latest v1.2.3", calls) + # Must dereference the tag object and create an annotated tag with message + self.assertIn( + 'git tag -f -a latest v1.2.3^{} -m "Floating latest tag for v1.2.3"', + calls, + ) self.assertIn("git push origin latest --force", calls) - if __name__ == "__main__": unittest.main()