diff --git a/tests/tools/private/release/git_test.py b/tests/tools/private/release/git_test.py index 59b5c31989..16667b8715 100644 --- a/tests/tools/private/release/git_test.py +++ b/tests/tools/private/release/git_test.py @@ -44,5 +44,43 @@ def test_checkout_track_remote_existing_branch( mock_reset_hard.assert_called_once_with("origin/my-branch") +class GitFetchTest(unittest.TestCase): + def setUp(self): + self.git = Git(".") + self.patcher = patch.object(self.git, "_run_git") + self.mock_run_git = self.patcher.start() + self.addCleanup(self.patcher.stop) + + def test_fetch_default(self): + self.git.fetch() + self.mock_run_git.assert_called_once_with( + "fetch", "origin", capture_output=False + ) + + def test_fetch_custom_remote(self): + self.git.fetch("upstream") + self.mock_run_git.assert_called_once_with( + "fetch", "upstream", capture_output=False + ) + + def test_fetch_with_refspec(self): + self.git.fetch("origin", refspec="my-branch") + self.mock_run_git.assert_called_once_with( + "fetch", "origin", "my-branch", capture_output=False + ) + + def test_fetch_with_tags_and_force(self): + self.git.fetch("origin", tags=True, force=True) + self.mock_run_git.assert_called_once_with( + "fetch", "origin", "--tags", "--force", capture_output=False + ) + + def test_fetch_all_options(self): + self.git.fetch("origin", refspec="my-branch", tags=True, force=True) + self.mock_run_git.assert_called_once_with( + "fetch", "origin", "my-branch", "--tags", "--force", capture_output=False + ) + + if __name__ == "__main__": unittest.main() diff --git a/tests/tools/private/release/promote_rc_test.py b/tests/tools/private/release/promote_rc_test.py index 68797e2e1e..f6fa2da970 100644 --- a/tests/tools/private/release/promote_rc_test.py +++ b/tests/tools/private/release/promote_rc_test.py @@ -50,9 +50,12 @@ def test_promote_rc_success(self): 123, expected_updated_body ) expected_comment = ( - "Version 2.0.0 has been tagged.\n\n" - "- **Release Page**: https://github.com/bazel-contrib/rules_python/releases/tag/2.0.0\n" - '- **BCR PR Search**: [is:pr ("bazel-contrib/rules_python" in:title) ("@2.0.0" in:title)](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.0%22%20in%3Atitle%29)' + "**New Release Tagged!** 🐍🌿\n\n" + "Version **2.0.0** has been successfully generated and tagged on branch [`release/2.0`](https://github.com/bazel-contrib/rules_python/tree/release/2.0).\n\n" + "- [Github Release 2.0.0](https://github.com/bazel-contrib/rules_python/releases/tag/2.0.0)\n" + "- [BCR Entry 2.0.0](https://registry.bazel.build/modules/rules_python/2.0.0)\n" + "- [BCR PRs](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.0%22%20in%3Atitle%29)\n" + "- [Release workflow status](https://github.com/bazel-contrib/rules_python/actions/workflows/release_promote_rc.yaml)" ) self.mock_gh.post_issue_comment.assert_called_once_with(123, expected_comment) @@ -95,9 +98,12 @@ def test_promote_rc_resolve_issue_success(self): 123, expected_updated_body ) expected_comment = ( - "Version 2.0.0 has been tagged.\n\n" - "- **Release Page**: https://github.com/bazel-contrib/rules_python/releases/tag/2.0.0\n" - '- **BCR PR Search**: [is:pr ("bazel-contrib/rules_python" in:title) ("@2.0.0" in:title)](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.0%22%20in%3Atitle%29)' + "**New Release Tagged!** 🐍🌿\n\n" + "Version **2.0.0** has been successfully generated and tagged on branch [`release/2.0`](https://github.com/bazel-contrib/rules_python/tree/release/2.0).\n\n" + "- [Github Release 2.0.0](https://github.com/bazel-contrib/rules_python/releases/tag/2.0.0)\n" + "- [BCR Entry 2.0.0](https://registry.bazel.build/modules/rules_python/2.0.0)\n" + "- [BCR PRs](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.0%22%20in%3Atitle%29)\n" + "- [Release workflow status](https://github.com/bazel-contrib/rules_python/actions/workflows/release_promote_rc.yaml)" ) self.mock_gh.post_issue_comment.assert_called_once_with(123, expected_comment) @@ -142,9 +148,12 @@ def test_promote_rc_resolves_version_from_issue(self): 123, expected_updated_body ) expected_comment = ( - "Version 2.0.1 has been tagged.\n\n" - "- **Release Page**: https://github.com/bazel-contrib/rules_python/releases/tag/2.0.1\n" - '- **BCR PR Search**: [is:pr ("bazel-contrib/rules_python" in:title) ("@2.0.1" in:title)](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.1%22%20in%3Atitle%29)' + "**New Release Tagged!** 🐍🌿\n\n" + "Version **2.0.1** has been successfully generated and tagged on branch [`release/2.0`](https://github.com/bazel-contrib/rules_python/tree/release/2.0).\n\n" + "- [Github Release 2.0.1](https://github.com/bazel-contrib/rules_python/releases/tag/2.0.1)\n" + "- [BCR Entry 2.0.1](https://registry.bazel.build/modules/rules_python/2.0.1)\n" + "- [BCR PRs](https://github.com/bazelbuild/bazel-central-registry/pulls?q=is%3Apr%20%28%22bazel-contrib/rules_python%22%20in%3Atitle%29%20%28%22%402.0.1%22%20in%3Atitle%29)\n" + "- [Release workflow status](https://github.com/bazel-contrib/rules_python/actions/workflows/release_promote_rc.yaml)" ) self.mock_gh.post_issue_comment.assert_called_once_with(123, expected_comment) diff --git a/tools/private/release/git.py b/tools/private/release/git.py index 69edba3565..3e7f77f39a 100644 --- a/tools/private/release/git.py +++ b/tools/private/release/git.py @@ -135,16 +135,23 @@ def push( self._run_git(*cmd, capture_output=False) def fetch( - self, remote: str = "origin", tags: bool = False, force: bool = False + self, + remote: str = "origin", + refspec: str | None = None, + tags: bool = False, + force: bool = False, ) -> None: """Fetches updates from a remote repository. Args: remote: The remote repository name. Defaults to 'origin'. + refspec: The refspec to fetch. tags: If True, fetches all tags. force: If True, force fetches updates. """ cmd = ["fetch", remote] + if refspec: + cmd.append(refspec) if tags: cmd.append("--tags") if force: diff --git a/tools/private/release/promote_rc.py b/tools/private/release/promote_rc.py index ac3a841526..4a261c3b84 100644 --- a/tools/private/release/promote_rc.py +++ b/tools/private/release/promote_rc.py @@ -1,6 +1,7 @@ """Subcommand to promote a release candidate to final release.""" import argparse +import os import urllib.parse from tools.private.release.gh import GitHub @@ -161,16 +162,29 @@ def run(self) -> int: print(f"Posting comment to tracking issue #{issue_num}...") + branch_url = f"{REPO_URL}/tree/{branch_name}" release_url = f"{REPO_URL}/releases/tag/{version}" + bcr_entry_url = f"https://registry.bazel.build/modules/rules_python/{version}" bcr_query = ( f'is:pr ("bazel-contrib/rules_python" in:title) ("@{version}" in:title)' ) bcr_search_url = f"https://github.com/bazelbuild/bazel-central-registry/pulls?q={urllib.parse.quote(bcr_query)}" - comment_body = ( - f"Version {version} has been tagged.\n\n" - f"- **Release Page**: {release_url}\n" - f"- **BCR PR Search**: [{bcr_query}]({bcr_search_url})" - ) + + if run_id := os.environ.get("GITHUB_RUN_ID"): + release_workflow_url = f"{REPO_URL}/actions/runs/{run_id}" + else: + release_workflow_url = ( + f"{REPO_URL}/actions/workflows/release_promote_rc.yaml" + ) + + comment_body = f"""**New Release Tagged!** 🐍🌿 + +Version **{version}** has been successfully generated and tagged on branch [`{branch_name}`]({branch_url}). + +- [Github Release {version}]({release_url}) +- [BCR Entry {version}]({bcr_entry_url}) +- [BCR PRs]({bcr_search_url}) +- [Release workflow status]({release_workflow_url})""" self.gh.post_issue_comment(issue_num, comment_body) return 0 diff --git a/tools/private/release/release.py b/tools/private/release/release.py index 6364c61b23..8ad9c2e33e 100644 --- a/tools/private/release/release.py +++ b/tools/private/release/release.py @@ -46,6 +46,7 @@ def create_parser(): def main(): + print(f"sys.argv: {sys.argv}") if "BUILD_WORKSPACE_DIRECTORY" in os.environ: os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"])