Skip to content

Commit 06fb285

Browse files
authored
fix: better handling of GitHub events (#808)
1 parent 9216510 commit 06fb285

File tree

5 files changed

+105
-32
lines changed

5 files changed

+105
-32
lines changed

mergify_cli/ci/detector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def get_github_pull_request_number() -> int | None:
178178
match get_ci_provider():
179179
case "github_actions":
180180
try:
181-
event = utils.get_github_event()
181+
_, event = utils.get_github_event()
182182
except utils.GitHubEventNotFoundError:
183183
return None
184184
pr = event.get("pull_request")

mergify_cli/ci/scopes/base_detector.py

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
from __future__ import annotations
22

33
import dataclasses
4-
import os
54
import typing
65

76
import yaml
@@ -69,32 +68,70 @@ def _detect_base_from_event(ev: dict[str, typing.Any]) -> str | None:
6968
return None
7069

7170

71+
def _detect_default_branch_from_event(ev: dict[str, typing.Any]) -> str | None:
72+
repo = ev.get("repository")
73+
if isinstance(repo, dict):
74+
sha = repo.get("default_branch")
75+
if isinstance(sha, str) and sha:
76+
return sha
77+
return None
78+
79+
80+
def _detect_base_from_push_event(ev: dict[str, typing.Any]) -> str | None:
81+
sha = ev.get("before")
82+
if isinstance(sha, str) and sha:
83+
return sha
84+
return None
85+
86+
7287
@dataclasses.dataclass
7388
class Base:
7489
ref: str
7590
is_merge_queue: bool
7691

7792

93+
PULL_REQUEST_EVENTS = {
94+
"pull_request",
95+
"pull_request_review",
96+
"pull_request_review_comment",
97+
"pull_request_target",
98+
}
99+
100+
78101
def detect() -> Base:
79102
try:
80-
event = utils.get_github_event()
103+
event_name, event = utils.get_github_event()
81104
except utils.GitHubEventNotFoundError:
82-
pass
105+
# fallback to last commit
106+
return Base("HEAD^", is_merge_queue=False)
83107
else:
84-
# 0) merge-queue PR override
85-
mq_sha = _detect_base_from_merge_queue_payload(event)
86-
if mq_sha:
87-
return Base(mq_sha, is_merge_queue=True)
88-
89-
# 1) standard event payload
90-
event_sha = _detect_base_from_event(event)
91-
if event_sha:
92-
return Base(event_sha, is_merge_queue=False)
93-
94-
# 2) base ref (e.g., PR target branch)
95-
base_ref = os.environ.get("GITHUB_BASE_REF")
96-
if base_ref:
97-
return Base(base_ref, is_merge_queue=False)
98-
99-
msg = "Could not detect base SHA. Provide GITHUB_EVENT_PATH / GITHUB_BASE_REF."
108+
if event_name in PULL_REQUEST_EVENTS:
109+
# 0) merge-queue PR override
110+
mq_sha = _detect_base_from_merge_queue_payload(event)
111+
if mq_sha:
112+
return Base(mq_sha, is_merge_queue=True)
113+
114+
# 1) standard event payload
115+
event_sha = _detect_base_from_event(event)
116+
if event_sha:
117+
return Base(event_sha, is_merge_queue=False)
118+
119+
# 2) standard event payload
120+
event_sha = _detect_default_branch_from_event(event)
121+
if event_sha:
122+
return Base(event_sha, is_merge_queue=False)
123+
124+
elif event_name == "push":
125+
event_sha = _detect_base_from_push_event(event)
126+
if event_sha:
127+
return Base(event_sha, is_merge_queue=False)
128+
129+
event_sha = _detect_default_branch_from_event(event)
130+
if event_sha:
131+
return Base(event_sha, is_merge_queue=False)
132+
else:
133+
msg = "Unhandled GITHUB_EVENT_NAME"
134+
raise BaseNotFoundError(msg)
135+
136+
msg = "Could not detect base SHA. Provide GITHUB_EVENT_NAME / GITHUB_EVENT_PATH."
100137
raise BaseNotFoundError(msg)

mergify_cli/tests/ci/scopes/test_base_detector.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,41 @@
66
from mergify_cli.ci.scopes import base_detector
77

88

9-
def test_detect_base_github_base_ref(
9+
@pytest.mark.parametrize("event_name", ["pull_request", "pull_request_review", "push"])
10+
def test_detect_base_from_repository_default_branch(
11+
event_name: str,
1012
monkeypatch: pytest.MonkeyPatch,
13+
tmp_path: pathlib.Path,
1114
) -> None:
12-
monkeypatch.setenv("GITHUB_BASE_REF", "main")
13-
monkeypatch.delenv("GITHUB_EVENT_PATH", raising=False)
15+
event_data = {"repository": {"default_branch": "main"}}
16+
event_file = tmp_path / "event.json"
17+
event_file.write_text(json.dumps(event_data))
18+
19+
monkeypatch.setenv("GITHUB_EVENT_NAME", event_name)
20+
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
1421

1522
result = base_detector.detect()
1623

1724
assert result == base_detector.Base("main", is_merge_queue=False)
1825

1926

20-
def test_detect_base_from_event_path(
27+
def test_detect_base_from_push_event(
28+
monkeypatch: pytest.MonkeyPatch,
29+
tmp_path: pathlib.Path,
30+
) -> None:
31+
event_data = {"before": "abc123"}
32+
event_file = tmp_path / "event.json"
33+
event_file.write_text(json.dumps(event_data))
34+
35+
monkeypatch.setenv("GITHUB_EVENT_NAME", "push")
36+
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
37+
38+
result = base_detector.detect()
39+
40+
assert result == base_detector.Base("abc123", is_merge_queue=False)
41+
42+
43+
def test_detect_base_from_pull_request_event_path(
2144
monkeypatch: pytest.MonkeyPatch,
2245
tmp_path: pathlib.Path,
2346
) -> None:
@@ -29,8 +52,8 @@ def test_detect_base_from_event_path(
2952
event_file = tmp_path / "event.json"
3053
event_file.write_text(json.dumps(event_data))
3154

55+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
3256
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
33-
monkeypatch.delenv("GITHUB_BASE_REF", raising=False)
3457

3558
result = base_detector.detect()
3659

@@ -51,16 +74,24 @@ def test_detect_base_merge_queue_override(
5174
event_file = tmp_path / "event.json"
5275
event_file.write_text(json.dumps(event_data))
5376

77+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
5478
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
5579

5680
result = base_detector.detect()
5781

5882
assert result == base_detector.Base("xyz789", is_merge_queue=True)
5983

6084

61-
def test_detect_base_no_info(monkeypatch: pytest.MonkeyPatch) -> None:
62-
monkeypatch.delenv("GITHUB_EVENT_PATH", raising=False)
63-
monkeypatch.delenv("GITHUB_BASE_REF", raising=False)
85+
def test_detect_base_no_info(
86+
tmp_path: pathlib.Path,
87+
monkeypatch: pytest.MonkeyPatch,
88+
) -> None:
89+
event_data: dict[str, str] = {}
90+
event_file = tmp_path / "event.json"
91+
event_file.write_text(json.dumps(event_data))
92+
93+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
94+
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
6495

6596
with pytest.raises(
6697
base_detector.BaseNotFoundError,

mergify_cli/tests/test_utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,11 @@ def test_get_github_event_success(
117117
event_file = tmp_path / "event.json"
118118
event_file.write_text(json.dumps(event_data))
119119

120+
monkeypatch.setenv("GITHUB_EVENT_NAME", "pull_request")
120121
monkeypatch.setenv("GITHUB_EVENT_PATH", str(event_file))
121-
result = utils.get_github_event()
122-
assert result == event_data
122+
name, event = utils.get_github_event()
123+
assert name == "pull_request"
124+
assert event == event_data
123125

124126

125127
def test_get_github_event_not_found(monkeypatch: pytest.MonkeyPatch) -> None:

mergify_cli/utils.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,12 +321,15 @@ class GitHubEventNotFoundError(Exception):
321321
pass
322322

323323

324-
def get_github_event() -> typing.Any: # noqa: ANN401
324+
def get_github_event() -> tuple[str, typing.Any]:
325+
event_name = os.environ.get("GITHUB_EVENT_NAME")
326+
if not event_name:
327+
raise GitHubEventNotFoundError
325328
event_path = os.environ.get("GITHUB_EVENT_PATH")
326329
if event_path and pathlib.Path(event_path).is_file():
327330
try:
328331
with pathlib.Path(event_path).open("r", encoding="utf-8") as f:
329-
return json.load(f)
332+
return event_name, json.load(f)
330333
except FileNotFoundError:
331334
pass
332335
raise GitHubEventNotFoundError

0 commit comments

Comments
 (0)