From 20132f6d12739454e17d7d99ad65514f23b00115 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 03:10:33 +0000 Subject: [PATCH 1/6] fix(release): use remote tags to determine next RC tag This fixes a bug where local out-of-sync tags could lead to computing the wrong next RC version. We now query remote tags directly using git ls-remote. Also added type annotations and docstring to get_remote_tags. --- tests/tools/private/release/release_test.py | 38 ++++++++++++++------- tools/private/release/create_rc.py | 2 +- tools/private/release/git.py | 27 +++++++++++++++ tools/private/release/release.py | 6 ++-- tools/private/release/utils.py | 7 ++-- 5 files changed, 62 insertions(+), 18 deletions(-) diff --git a/tests/tools/private/release/release_test.py b/tests/tools/private/release/release_test.py index 636c9b2589..ce04ba9c0e 100644 --- a/tests/tools/private/release/release_test.py +++ b/tests/tools/private/release/release_test.py @@ -34,6 +34,7 @@ def _mock_git_and_gh(test_case): # Apply safe defaults mock_git.get_current_branch.return_value = None mock_git.get_tags.return_value = [] + mock_git.get_remote_tags.return_value = [] mock_git.get_tags_at_head.return_value = [] mock_git.status.return_value = "" mock_git.branch_exists.return_value = False @@ -588,6 +589,17 @@ def test_get_latest_rc_tag_ignores_v_prefix(self, mock_get_tags): mock_get_tags.return_value = ["v2.0.0-rc0", "2.0.0-rc1"] self.assertEqual(utils.get_latest_rc_tag("2.0.0"), "2.0.0-rc1") + @patch("tools.private.release.git.get_remote_tags") + def test_get_latest_rc_tag_remote_success(self, mock_get_remote_tags): + mock_get_remote_tags.return_value = [ + "2.0.0-rc0", + "2.0.0-rc2", + "2.0.0-rc1", + "2.1.0-rc0", + ] + self.assertEqual(utils.get_latest_rc_tag("2.0.0", remote="origin"), "2.0.0-rc2") + mock_get_remote_tags.assert_called_once_with("origin") + class DetermineNextVersionTest(TempDirTestCase): def setUp(self): @@ -942,7 +954,7 @@ def test_create_rc_success_first_rc(self): - [x] Create Release branch | status=done branch=release/2.0 commit=abcdef12 - [ ] Tag RC0 | status=pending """ - self.mock_git.get_tags.return_value = [] + self.mock_git.get_remote_tags.return_value = [] self.mock_git.get_tags_at_head.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" @@ -988,7 +1000,7 @@ def test_create_rc_success_next_rc(self): - [x] Tag RC0 | status=done tag=2.0.0-rc0 commit=abcdef12 - [ ] Tag RC1 | status=pending """ - self.mock_git.get_tags.return_value = ["2.0.0-rc0"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc0"] self.mock_git.get_tags_at_head.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" @@ -1032,7 +1044,7 @@ def test_create_rc_already_tagged(self): - [x] Create Release branch | status=done branch=release/2.0 commit=abcdef12 - [ ] Tag RC0 | status=pending """ - self.mock_git.get_tags.return_value = [] + self.mock_git.get_remote_tags.return_value = [] self.mock_git.get_tags_at_head.return_value = ["2.0.0-rc0"] # Act @@ -1052,7 +1064,7 @@ def setUp(self): def test_promote_rc_success(self): # Arrange args = MagicMock(version="2.0.0", issue=123, dry_run=False) - self.mock_git.get_tags.return_value = ["2.0.0-rc0", "2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc0", "2.0.0-rc1"] self.mock_git.get_commit_sha.return_value = "abcdef123456" self.mock_git.tag_exists.return_value = False initial_body = "- [ ] Tag Final" @@ -1088,7 +1100,7 @@ def test_promote_rc_success(self): def test_promote_rc_resolve_issue_success(self): # Arrange args = MagicMock(version="2.0.0", issue=None, dry_run=False) - self.mock_git.get_tags.return_value = ["2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc1"] self.mock_git.tag_exists.return_value = False self.mock_gh.get_release_tracking_issue.side_effect = None self.mock_gh.get_release_tracking_issue.return_value = 123 @@ -1124,7 +1136,8 @@ def test_promote_rc_defaults_to_determine_next_version(self): # Arrange args = MagicMock(version=None, issue=123, dry_run=False) self.mock_git.get_current_branch.return_value = "release/2.0" - self.mock_git.get_tags.return_value = ["2.0.0", "2.0.1-rc0"] + self.mock_git.get_tags.return_value = ["2.0.0"] + self.mock_git.get_remote_tags.return_value = ["2.0.1-rc0"] self.mock_git.get_commit_sha.return_value = "12345678" self.mock_git.tag_exists.return_value = False initial_body = "- [ ] Tag Final" @@ -1136,7 +1149,8 @@ def test_promote_rc_defaults_to_determine_next_version(self): # Assert self.assertEqual(result, 0) self.mock_git.get_current_branch.assert_called_once() - self.assertTrue(self.mock_git.get_tags.call_count >= 2) + self.mock_git.get_tags.assert_called_once() + self.mock_git.get_remote_tags.assert_called_once_with("upstream") self.mock_git.checkout.assert_not_called() self.mock_git.get_commit_sha.assert_called_once_with("2.0.1-rc0") @@ -1159,7 +1173,7 @@ def test_promote_rc_defaults_to_determine_next_version(self): def test_promote_rc_dry_run_success(self): # Arrange args = MagicMock(version="2.0.0", issue=123, dry_run=True) - self.mock_git.get_tags.return_value = ["2.0.0-rc0", "2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc0", "2.0.0-rc1"] self.mock_git.get_commit_sha.return_value = "abcdef123456" self.mock_git.tag_exists.return_value = False initial_body = "- [ ] Tag Final" @@ -1183,7 +1197,7 @@ def test_promote_rc_dry_run_success(self): def test_promote_rc_tag_already_exists(self): # Arrange args = MagicMock(version="2.0.0", issue=123) - self.mock_git.get_tags.return_value = ["2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc1"] self.mock_git.tag_exists.return_value = True # Act @@ -1200,7 +1214,7 @@ def test_promote_rc_tag_already_exists(self): def test_promote_rc_issue_not_found(self): # Arrange args = MagicMock(version="2.0.0", issue=None) - self.mock_git.get_tags.return_value = ["2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc1"] self.mock_git.tag_exists.return_value = False self.mock_gh.get_release_tracking_issue.side_effect = NoTrackingIssueError( "Not found" @@ -1220,7 +1234,7 @@ def test_promote_rc_issue_not_found(self): def test_promote_rc_issue_malformed(self): # Arrange args = MagicMock(version="2.0.0", issue=123) - self.mock_git.get_tags.return_value = ["2.0.0-rc1"] + self.mock_git.get_remote_tags.return_value = ["2.0.0-rc1"] self.mock_git.tag_exists.return_value = False self.mock_git.get_commit_sha.return_value = "abcdef123456" initial_body = "malformed body" @@ -1240,7 +1254,7 @@ def test_promote_rc_issue_malformed(self): def test_promote_rc_no_rc_found(self): # Arrange args = MagicMock(version="2.0.0", issue=123) - self.mock_git.get_tags.return_value = [] + self.mock_git.get_remote_tags.return_value = [] # Act result = releaser.cmd_promote_rc(args) diff --git a/tools/private/release/create_rc.py b/tools/private/release/create_rc.py index 9cd1a3b291..78d81be729 100644 --- a/tools/private/release/create_rc.py +++ b/tools/private/release/create_rc.py @@ -53,7 +53,7 @@ def cmd_create_rc(args): # Determine next RC tag git.fetch(args.remote) git.fetch(args.remote, tags=True, force=True) - latest_rc = get_latest_rc_tag(version) + latest_rc = get_latest_rc_tag(version, remote=args.remote) if not latest_rc: next_rc_num = 0 diff --git a/tools/private/release/git.py b/tools/private/release/git.py index ce2bd8ca03..c8b01d8d51 100644 --- a/tools/private/release/git.py +++ b/tools/private/release/git.py @@ -150,3 +150,30 @@ def is_ancestor(ancestor, descendant): return True except subprocess.CalledProcessError: return False + + +def get_remote_tags(remote: str) -> list[str]: + """Returns a list of tags present on the specified remote repository. + + Args: + remote: The name of the git remote to query (e.g., 'origin', 'upstream'). + + Returns: + A list of tag names (strings) found on the remote, excluding peeled tags. + """ + output = run_cmd("git", "ls-remote", "--tags", remote) + tags = [] + for line in output.splitlines(): + if not line: + continue + parts = line.split() + if len(parts) < 2: + continue + ref = parts[1] + if ref.startswith("refs/tags/"): + tag = ref[len("refs/tags/") :] + # Skip peeled tags (e.g. tag^{}) to avoid + # duplicate tag names in the output. + if not tag.endswith("^{}"): + tags.append(tag) + return tags diff --git a/tools/private/release/release.py b/tools/private/release/release.py index 7bc6f9ba05..7ed921ddd6 100644 --- a/tools/private/release/release.py +++ b/tools/private/release/release.py @@ -141,8 +141,8 @@ def cmd_process_backports(args): branch_name = f"release/{branch_version}" # Determine next RC tag to write to backport metadata - git.fetch("--tags", "--force") - latest_rc = get_latest_rc_tag(version) + git.fetch("origin", tags=True, force=True) + latest_rc = get_latest_rc_tag(version, remote="origin") if not latest_rc: next_rc_suffix = "rc0" else: @@ -242,7 +242,7 @@ def cmd_promote_rc(args): # Fetch from upstream to ensure we have the latest tags git.fetch("upstream", tags=True, force=True) - latest_rc = get_latest_rc_tag(version) + latest_rc = get_latest_rc_tag(version, remote="upstream") if not latest_rc: print(f"Error: No release candidate tags found matching {version}-rc*") return 1 diff --git a/tools/private/release/utils.py b/tools/private/release/utils.py index 6f7383f8ec..2d050022b1 100644 --- a/tools/private/release/utils.py +++ b/tools/private/release/utils.py @@ -67,9 +67,12 @@ def get_latest_version(): return stable_versions[-1] -def get_latest_rc_tag(version): +def get_latest_rc_tag(version, remote=None): """Queries git tags and returns the highest RC tag for the version.""" - tags = git.get_tags() + if remote: + tags = git.get_remote_tags(remote) + else: + tags = git.get_tags() pattern = rf"^{re.escape(version)}-rc\d+$" rc_tags = [tag.strip() for tag in tags if re.match(pattern, tag.strip())] if not rc_tags: From 933b6d711ff6e15f05216b612eddc139ae583c3f Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 03:23:26 +0000 Subject: [PATCH 2/6] refactor(release): avoid local checkout in create-rc --- tests/tools/private/release/release_test.py | 24 +++++++++++++-------- tools/private/release/create_rc.py | 12 +++++------ tools/private/release/git.py | 6 +++--- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/tests/tools/private/release/release_test.py b/tests/tools/private/release/release_test.py index ce04ba9c0e..709341fc08 100644 --- a/tests/tools/private/release/release_test.py +++ b/tests/tools/private/release/release_test.py @@ -35,7 +35,7 @@ def _mock_git_and_gh(test_case): mock_git.get_current_branch.return_value = None mock_git.get_tags.return_value = [] mock_git.get_remote_tags.return_value = [] - mock_git.get_tags_at_head.return_value = [] + mock_git.get_tags_at_ref.return_value = [] mock_git.status.return_value = "" mock_git.branch_exists.return_value = False mock_git.tag_exists.return_value = False @@ -955,7 +955,7 @@ def test_create_rc_success_first_rc(self): - [ ] Tag RC0 | status=pending """ self.mock_git.get_remote_tags.return_value = [] - self.mock_git.get_tags_at_head.return_value = [] + self.mock_git.get_tags_at_ref.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" # Act @@ -966,9 +966,11 @@ def test_create_rc_success_first_rc(self): self.mock_git.fetch.assert_has_calls( [call("my-remote"), call("my-remote", tags=True, force=True)] ) - self.mock_git.checkout.assert_called_once_with("my-remote/release/2.0") - self.mock_git.tag.assert_called_once_with("2.0.0-rc0", "HEAD") + self.mock_git.checkout.assert_not_called() + self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") + self.mock_git.tag.assert_called_once_with("2.0.0-rc0", "my-remote/release/2.0") self.mock_git.push.assert_called_once_with("my-remote", "2.0.0-rc0") + self.mock_git.get_commit_sha.assert_called_once_with("my-remote/release/2.0") self.mock_gh.update_issue_body.assert_called_once() call_args = self.mock_gh.update_issue_body.call_args[0] @@ -1001,7 +1003,7 @@ def test_create_rc_success_next_rc(self): - [ ] Tag RC1 | status=pending """ self.mock_git.get_remote_tags.return_value = ["2.0.0-rc0"] - self.mock_git.get_tags_at_head.return_value = [] + self.mock_git.get_tags_at_ref.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" # Act @@ -1012,9 +1014,11 @@ def test_create_rc_success_next_rc(self): self.mock_git.fetch.assert_has_calls( [call("my-remote"), call("my-remote", tags=True, force=True)] ) - self.mock_git.checkout.assert_called_once_with("my-remote/release/2.0") - self.mock_git.tag.assert_called_once_with("2.0.0-rc1", "HEAD") + self.mock_git.checkout.assert_not_called() + self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") + self.mock_git.tag.assert_called_once_with("2.0.0-rc1", "my-remote/release/2.0") self.mock_git.push.assert_called_once_with("my-remote", "2.0.0-rc1") + self.mock_git.get_commit_sha.assert_called_once_with("my-remote/release/2.0") self.mock_gh.update_issue_body.assert_called_once() call_args = self.mock_gh.update_issue_body.call_args[0] @@ -1036,7 +1040,7 @@ def test_create_rc_success_next_rc(self): def test_create_rc_already_tagged(self): # Arrange - args = MagicMock(issue=123) + args = MagicMock(issue=123, remote="my-remote") self.mock_gh.get_issue_title.return_value = "Release 2.0.0" self.mock_gh.get_issue_body.return_value = """ ## Checklist @@ -1045,13 +1049,15 @@ def test_create_rc_already_tagged(self): - [ ] Tag RC0 | status=pending """ self.mock_git.get_remote_tags.return_value = [] - self.mock_git.get_tags_at_head.return_value = ["2.0.0-rc0"] + self.mock_git.get_tags_at_ref.return_value = ["2.0.0-rc0"] # Act result = releaser.cmd_create_rc(args) # Assert self.assertEqual(result, 0) + self.mock_git.checkout.assert_not_called() + self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") self.mock_git.tag.assert_not_called() self.mock_git.push.assert_not_called() self.mock_gh.update_issue_body.assert_not_called() diff --git a/tools/private/release/create_rc.py b/tools/private/release/create_rc.py index 78d81be729..01053733a0 100644 --- a/tools/private/release/create_rc.py +++ b/tools/private/release/create_rc.py @@ -79,18 +79,18 @@ def cmd_create_rc(args): ) return 1 - # Verify HEAD is not already tagged - git.checkout(f"{args.remote}/{branch_name}") - head_tags = git.get_tags_at_head() - if any(tag.startswith(f"{version}-rc") for tag in head_tags): + # Verify target commit is not already tagged + target_ref = f"{args.remote}/{branch_name}" + target_tags = git.get_tags_at_ref(target_ref) + if any(tag.startswith(f"{version}-rc") for tag in target_tags): print(f"HEAD of {branch_name} is already tagged with an RC. Skipping.") return 0 print(f"Tagging and pushing next RC: {next_rc}...") - git.tag(next_rc, "HEAD") + git.tag(next_rc, target_ref) git.push(args.remote, next_rc) - commit_sha = git.get_commit_sha("HEAD") + commit_sha = git.get_commit_sha(target_ref) # Check off the appropriate "Tag RC{N}" task in the checklist print(f"Checking off Tag RC{next_rc_num} task...") diff --git a/tools/private/release/git.py b/tools/private/release/git.py index c8b01d8d51..f566451806 100644 --- a/tools/private/release/git.py +++ b/tools/private/release/git.py @@ -123,9 +123,9 @@ def sort_commits_chronologically(shas): return output.splitlines() if output else [] -def get_tags_at_head(): - """Returns a list of tags pointing at the current HEAD commit.""" - output = run_cmd("git", "tag", "--points-at", "HEAD") +def get_tags_at_ref(ref: str = "HEAD") -> list[str]: + """Returns a list of tags pointing at the specified reference.""" + output = run_cmd("git", "tag", "--points-at", ref) return output.splitlines() if output else [] From 06abed3591fbb338f78fa2a5a146591968b1beb7 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 03:23:49 +0000 Subject: [PATCH 3/6] refactor(release): make ref a required arg in get_tags_at_ref --- tools/private/release/git.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/private/release/git.py b/tools/private/release/git.py index f566451806..fff8ddb64e 100644 --- a/tools/private/release/git.py +++ b/tools/private/release/git.py @@ -123,7 +123,7 @@ def sort_commits_chronologically(shas): return output.splitlines() if output else [] -def get_tags_at_ref(ref: str = "HEAD") -> list[str]: +def get_tags_at_ref(ref: str) -> list[str]: """Returns a list of tags pointing at the specified reference.""" output = run_cmd("git", "tag", "--points-at", ref) return output.splitlines() if output else [] From be14602741f12395842590fd2a507c00f738962f Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 03:29:09 +0000 Subject: [PATCH 4/6] refactor(release): remove tag verification check in create-rc --- tests/tools/private/release/release_test.py | 30 +-------------------- tools/private/release/create_rc.py | 8 +----- tools/private/release/git.py | 6 ----- 3 files changed, 2 insertions(+), 42 deletions(-) diff --git a/tests/tools/private/release/release_test.py b/tests/tools/private/release/release_test.py index 709341fc08..d06b9097a9 100644 --- a/tests/tools/private/release/release_test.py +++ b/tests/tools/private/release/release_test.py @@ -35,7 +35,7 @@ def _mock_git_and_gh(test_case): mock_git.get_current_branch.return_value = None mock_git.get_tags.return_value = [] mock_git.get_remote_tags.return_value = [] - mock_git.get_tags_at_ref.return_value = [] + mock_git.status.return_value = "" mock_git.branch_exists.return_value = False mock_git.tag_exists.return_value = False @@ -955,7 +955,6 @@ def test_create_rc_success_first_rc(self): - [ ] Tag RC0 | status=pending """ self.mock_git.get_remote_tags.return_value = [] - self.mock_git.get_tags_at_ref.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" # Act @@ -967,7 +966,6 @@ def test_create_rc_success_first_rc(self): [call("my-remote"), call("my-remote", tags=True, force=True)] ) self.mock_git.checkout.assert_not_called() - self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") self.mock_git.tag.assert_called_once_with("2.0.0-rc0", "my-remote/release/2.0") self.mock_git.push.assert_called_once_with("my-remote", "2.0.0-rc0") self.mock_git.get_commit_sha.assert_called_once_with("my-remote/release/2.0") @@ -1003,7 +1001,6 @@ def test_create_rc_success_next_rc(self): - [ ] Tag RC1 | status=pending """ self.mock_git.get_remote_tags.return_value = ["2.0.0-rc0"] - self.mock_git.get_tags_at_ref.return_value = [] self.mock_git.get_commit_sha.return_value = "1234567890" # Act @@ -1015,7 +1012,6 @@ def test_create_rc_success_next_rc(self): [call("my-remote"), call("my-remote", tags=True, force=True)] ) self.mock_git.checkout.assert_not_called() - self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") self.mock_git.tag.assert_called_once_with("2.0.0-rc1", "my-remote/release/2.0") self.mock_git.push.assert_called_once_with("my-remote", "2.0.0-rc1") self.mock_git.get_commit_sha.assert_called_once_with("my-remote/release/2.0") @@ -1038,30 +1034,6 @@ def test_create_rc_success_next_rc(self): ) self.assertNotIn("🚀", comment_call_args[1]) - def test_create_rc_already_tagged(self): - # Arrange - args = MagicMock(issue=123, remote="my-remote") - self.mock_gh.get_issue_title.return_value = "Release 2.0.0" - self.mock_gh.get_issue_body.return_value = """ -## Checklist -- [x] Prepare Release | status=done pr=#122 commit=abcdef12 -- [x] Create Release branch | status=done branch=release/2.0 commit=abcdef12 -- [ ] Tag RC0 | status=pending -""" - self.mock_git.get_remote_tags.return_value = [] - self.mock_git.get_tags_at_ref.return_value = ["2.0.0-rc0"] - - # Act - result = releaser.cmd_create_rc(args) - - # Assert - self.assertEqual(result, 0) - self.mock_git.checkout.assert_not_called() - self.mock_git.get_tags_at_ref.assert_called_once_with("my-remote/release/2.0") - self.mock_git.tag.assert_not_called() - self.mock_git.push.assert_not_called() - self.mock_gh.update_issue_body.assert_not_called() - class CmdPromoteRcTest(unittest.TestCase): def setUp(self): diff --git a/tools/private/release/create_rc.py b/tools/private/release/create_rc.py index 01053733a0..5273ca8195 100644 --- a/tools/private/release/create_rc.py +++ b/tools/private/release/create_rc.py @@ -79,19 +79,13 @@ def cmd_create_rc(args): ) return 1 - # Verify target commit is not already tagged target_ref = f"{args.remote}/{branch_name}" - target_tags = git.get_tags_at_ref(target_ref) - if any(tag.startswith(f"{version}-rc") for tag in target_tags): - print(f"HEAD of {branch_name} is already tagged with an RC. Skipping.") - return 0 + commit_sha = git.get_commit_sha(target_ref) print(f"Tagging and pushing next RC: {next_rc}...") git.tag(next_rc, target_ref) git.push(args.remote, next_rc) - commit_sha = git.get_commit_sha(target_ref) - # Check off the appropriate "Tag RC{N}" task in the checklist print(f"Checking off Tag RC{next_rc_num} task...") metadata = {"status": "done", "tag": next_rc, "commit": commit_sha[:8]} diff --git a/tools/private/release/git.py b/tools/private/release/git.py index fff8ddb64e..f7021b6f5c 100644 --- a/tools/private/release/git.py +++ b/tools/private/release/git.py @@ -123,12 +123,6 @@ def sort_commits_chronologically(shas): return output.splitlines() if output else [] -def get_tags_at_ref(ref: str) -> list[str]: - """Returns a list of tags pointing at the specified reference.""" - output = run_cmd("git", "tag", "--points-at", ref) - return output.splitlines() if output else [] - - def get_current_branch(): """Returns the current git branch name.""" return run_cmd("git", "rev-parse", "--abbrev-ref", "HEAD") From a6548471128e055957564aefaff583093b4741d4 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 06:05:40 +0000 Subject: [PATCH 5/6] fix(release): exclude release directories from version marker check --- .github/workflows/check_version_markers.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/check_version_markers.sh b/.github/workflows/check_version_markers.sh index b8d35aec9d..15a0a67dc8 100755 --- a/.github/workflows/check_version_markers.sh +++ b/.github/workflows/check_version_markers.sh @@ -20,9 +20,8 @@ grep_exit_code=0 # Exclude CONTRIBUTING.md, RELEASING.md because they document how to use these strings. grep --exclude=CONTRIBUTING.md \ --exclude=RELEASING.md \ - --exclude=release.py \ - --exclude=release_test.py \ --exclude-dir=.* \ + --exclude-dir=release \ VERSION_NEXT_ -r || grep_exit_code=$? if [[ $grep_exit_code -eq 0 ]]; then From fdc3871b41dab9f78021069fdca3f606f901d2a8 Mon Sep 17 00:00:00 2001 From: Richard Levasseur Date: Wed, 1 Jul 2026 06:09:07 +0000 Subject: [PATCH 6/6] fix(release): fetch upstream tags before determining version in promote-rc --- tools/private/release/release.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/private/release/release.py b/tools/private/release/release.py index 7ed921ddd6..e1ebf8ec2e 100644 --- a/tools/private/release/release.py +++ b/tools/private/release/release.py @@ -236,12 +236,13 @@ def cmd_process_backports(args): def cmd_promote_rc(args): """Executes the promote-rc subcommand (Phase 3).""" + # Fetch from upstream to ensure we have the latest tags + git.fetch("upstream", tags=True, force=True) + version = args.version if version is None: version = determine_next_version() - # Fetch from upstream to ensure we have the latest tags - git.fetch("upstream", tags=True, force=True) latest_rc = get_latest_rc_tag(version, remote="upstream") if not latest_rc: print(f"Error: No release candidate tags found matching {version}-rc*")