diff --git a/mergify_cli/ci/cli.py b/mergify_cli/ci/cli.py index 7850f876..9ee84bd0 100644 --- a/mergify_cli/ci/cli.py +++ b/mergify_cli/ci/cli.py @@ -4,6 +4,7 @@ from mergify_cli import utils from mergify_cli.ci import detector +from mergify_cli.ci.git_refs import detector as git_refs_detector from mergify_cli.ci.junit_processing import cli as junit_processing_cli from mergify_cli.ci.scopes import cli as scopes_cli from mergify_cli.ci.scopes import exceptions as scopes_exc @@ -193,6 +194,17 @@ async def junit_process( ) +@ci.command( + help="""Give the base/head git references of the pull request""", + short_help="""Give the base/head git references of the pull request""", +) +def git_refs() -> None: + ref = git_refs_detector.detect() + click.echo(f"Base: {ref.base}") + click.echo(f"Head: {ref.head}") + ref.maybe_write_to_github_outputs() + + @ci.command( help="""Give the list scope impacted by changed files""", short_help="""Give the list scope impacted by changed files""", diff --git a/mergify_cli/ci/git_refs/__init__.py b/mergify_cli/ci/git_refs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/mergify_cli/ci/scopes/git_refs_detector.py b/mergify_cli/ci/git_refs/detector.py similarity index 90% rename from mergify_cli/ci/scopes/git_refs_detector.py rename to mergify_cli/ci/git_refs/detector.py index 2eb03e72..e2e9c799 100644 --- a/mergify_cli/ci/scopes/git_refs_detector.py +++ b/mergify_cli/ci/git_refs/detector.py @@ -1,6 +1,8 @@ from __future__ import annotations import dataclasses +import os +import pathlib import typing import yaml @@ -9,6 +11,10 @@ from mergify_cli.ci.scopes import exceptions +GITHUB_ACTIONS_BASE_OUTPUT_NAME = "base" +GITHUB_ACTIONS_HEAD_OUTPUT_NAME = "head" + + class BaseNotFoundError(exceptions.ScopesError): pass @@ -107,6 +113,14 @@ class References: head: str is_merge_queue: bool + def maybe_write_to_github_outputs(self) -> None: + gha = os.environ.get("GITHUB_OUTPUT") + if not gha: + return + with pathlib.Path(gha).open("a", encoding="utf-8") as fh: + fh.write(f"{GITHUB_ACTIONS_BASE_OUTPUT_NAME}={self.base}\n") + fh.write(f"{GITHUB_ACTIONS_HEAD_OUTPUT_NAME}={self.head}\n") + PULL_REQUEST_EVENTS = { "pull_request", diff --git a/mergify_cli/ci/scopes/cli.py b/mergify_cli/ci/scopes/cli.py index 10f122d1..6a9a474b 100644 --- a/mergify_cli/ci/scopes/cli.py +++ b/mergify_cli/ci/scopes/cli.py @@ -10,18 +10,16 @@ import pydantic from mergify_cli import utils +from mergify_cli.ci.git_refs import detector as git_refs_detector from mergify_cli.ci.scopes import changed_files from mergify_cli.ci.scopes import config from mergify_cli.ci.scopes import exceptions -from mergify_cli.ci.scopes import git_refs_detector if typing.TYPE_CHECKING: from collections import abc GITHUB_ACTIONS_SCOPES_OUTPUT_NAME = "scopes" -GITHUB_ACTIONS_BASE_OUTPUT_NAME = "base" -GITHUB_ACTIONS_HEAD_OUTPUT_NAME = "head" def match_scopes( @@ -56,8 +54,6 @@ def match_scopes( def maybe_write_github_outputs( - base: str, - head: str, all_scopes: abc.Iterable[str], scopes_hit: set[str], ) -> None: @@ -74,8 +70,6 @@ def maybe_write_github_outputs( data = { key: "true" if key in scopes_hit else "false" for key in sorted(all_scopes) } - fh.write(f"{GITHUB_ACTIONS_BASE_OUTPUT_NAME}={base}\n") - fh.write(f"{GITHUB_ACTIONS_HEAD_OUTPUT_NAME}={head}\n") fh.write( f"{GITHUB_ACTIONS_SCOPES_OUTPUT_NAME}<<{delimiter}\n{json.dumps(data)}\n{delimiter}\n", ) @@ -164,7 +158,8 @@ def detect(config_path: str) -> DetectedScope: else: click.echo("No scopes matched.") - maybe_write_github_outputs(git_refs.base, git_refs.head, all_scopes, scopes_hit) + git_refs.maybe_write_to_github_outputs() + maybe_write_github_outputs(all_scopes, scopes_hit) maybe_write_github_step_summary( git_refs.base, git_refs.head, diff --git a/mergify_cli/tests/ci/scopes/test_git_refs_detector.py b/mergify_cli/tests/ci/git_refs/test_git_refs_detector.py similarity index 70% rename from mergify_cli/tests/ci/scopes/test_git_refs_detector.py rename to mergify_cli/tests/ci/git_refs/test_git_refs_detector.py index d4462c2e..8bb65f89 100644 --- a/mergify_cli/tests/ci/scopes/test_git_refs_detector.py +++ b/mergify_cli/tests/ci/git_refs/test_git_refs_detector.py @@ -5,7 +5,7 @@ import pytest -from mergify_cli.ci.scopes import git_refs_detector +from mergify_cli.ci.git_refs import detector if TYPE_CHECKING: @@ -25,9 +25,34 @@ def test_detect_base_from_repository_default_branch( monkeypatch.setenv("GITHUB_EVENT_NAME", event_name) monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) - result = git_refs_detector.detect() + result = detector.detect() - assert result == git_refs_detector.References("main", "HEAD", is_merge_queue=False) + assert result == detector.References("main", "HEAD", is_merge_queue=False) + + +def test_maybe_write_github_outputs( + tmp_path: pathlib.Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + event_data = {"before": "abc123", "after": "xyz987"} + event_file = tmp_path / "event.json" + event_file.write_text(json.dumps(event_data)) + + output_file = tmp_path / "github_output" + + monkeypatch.setenv("GITHUB_OUTPUT", str(output_file)) + monkeypatch.setenv("GITHUB_EVENT_NAME", "push") + monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) + + result = detector.detect() + + result.maybe_write_to_github_outputs() + + content = output_file.read_text() + expected = """base=abc123 +head=xyz987 +""" + assert content == expected def test_detect_base_from_push_event( @@ -41,9 +66,9 @@ def test_detect_base_from_push_event( monkeypatch.setenv("GITHUB_EVENT_NAME", "push") monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) - result = git_refs_detector.detect() + result = detector.detect() - assert result == git_refs_detector.References( + assert result == detector.References( "abc123", "xyz987", is_merge_queue=False, @@ -66,9 +91,9 @@ def test_detect_base_from_pull_request_event_path( monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request") monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) - result = git_refs_detector.detect() + result = detector.detect() - assert result == git_refs_detector.References( + assert result == detector.References( "abc123", "xyz987", is_merge_queue=False, @@ -92,9 +117,9 @@ def test_detect_base_merge_queue_override( monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request") monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) - result = git_refs_detector.detect() + result = detector.detect() - assert result == git_refs_detector.References("xyz789", "HEAD", is_merge_queue=True) + assert result == detector.References("xyz789", "HEAD", is_merge_queue=True) def test_detect_base_no_info( @@ -109,10 +134,10 @@ def test_detect_base_no_info( monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) with pytest.raises( - git_refs_detector.BaseNotFoundError, + detector.BaseNotFoundError, match="Could not detect base SHA", ): - git_refs_detector.detect() + detector.detect() def test_yaml_docs_from_fenced_blocks_valid() -> None: @@ -126,9 +151,9 @@ def test_yaml_docs_from_fenced_blocks_valid() -> None: ``` More text""" - result = git_refs_detector._yaml_docs_from_fenced_blocks(body) + result = detector._yaml_docs_from_fenced_blocks(body) - assert result == git_refs_detector.MergeQueueMetadata( + assert result == detector.MergeQueueMetadata( { "checking_base_sha": "xyz789", "pull_requests": [{"number": 1}], @@ -140,7 +165,7 @@ def test_yaml_docs_from_fenced_blocks_valid() -> None: def test_yaml_docs_from_fenced_blocks_no_yaml() -> None: body = "No yaml here" - result = git_refs_detector._yaml_docs_from_fenced_blocks(body) + result = detector._yaml_docs_from_fenced_blocks(body) assert result is None @@ -151,6 +176,6 @@ def test_yaml_docs_from_fenced_blocks_empty_yaml() -> None: ``` More text""" - result = git_refs_detector._yaml_docs_from_fenced_blocks(body) + result = detector._yaml_docs_from_fenced_blocks(body) assert result is None diff --git a/mergify_cli/tests/ci/scopes/test_cli.py b/mergify_cli/tests/ci/scopes/test_cli.py index 2f937b1e..57ecc4bc 100644 --- a/mergify_cli/tests/ci/scopes/test_cli.py +++ b/mergify_cli/tests/ci/scopes/test_cli.py @@ -8,9 +8,9 @@ import respx import yaml +from mergify_cli.ci.git_refs import detector from mergify_cli.ci.scopes import cli from mergify_cli.ci.scopes import config -from mergify_cli.ci.scopes import git_refs_detector if TYPE_CHECKING: @@ -293,12 +293,10 @@ def test_maybe_write_github_outputs( scopes_hit = {"backend", "docs"} with mock.patch("uuid.uuid4", return_value="fixed-uuid"): - cli.maybe_write_github_outputs("base-sha", "head-sha", all_scopes, scopes_hit) + cli.maybe_write_github_outputs(all_scopes, scopes_hit) content = output_file.read_text() - expected = """base=base-sha -head=head-sha -scopes< None: + event_data = {"before": "abc123", "after": "xyz987"} + event_file = tmp_path / "event.json" + event_file.write_text(json.dumps(event_data)) + + output_file = tmp_path / "github_output" + + monkeypatch.setenv("GITHUB_OUTPUT", str(output_file)) + monkeypatch.setenv("GITHUB_EVENT_NAME", "push") + monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file)) + + runner = testing.CliRunner() + result = runner.invoke(ci_cli.git_refs, []) + assert result.exit_code == 0, result.output + + content = output_file.read_text() + expected = """base=abc123 +head=xyz987 +""" + assert content == expected