Skip to content

Commit b33c078

Browse files
authored
feat(scopes): automatically add a merge-queue scopes (#805)
This will simplify two steps CIs setup. Users can easly list the jobs that need to be run only in the MQ.
1 parent e05b1b0 commit b33c078

File tree

4 files changed

+30
-13
lines changed

4 files changed

+30
-13
lines changed

mergify_cli/ci/scopes/base_detector.py

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

3+
import dataclasses
34
import json
45
import os
56
import pathlib
@@ -64,7 +65,13 @@ def _detect_base_from_event(ev: dict[str, typing.Any]) -> str | None:
6465
return None
6566

6667

67-
def detect() -> str:
68+
@dataclasses.dataclass
69+
class Base:
70+
ref: str
71+
is_merge_queue: bool
72+
73+
74+
def detect() -> Base:
6875
event_path = os.environ.get("GITHUB_EVENT_PATH")
6976
event: dict[str, typing.Any] | None = None
7077
if event_path and pathlib.Path(event_path).is_file():
@@ -78,17 +85,17 @@ def detect() -> str:
7885
# 0) merge-queue PR override
7986
mq_sha = _detect_base_from_merge_queue_payload(event)
8087
if mq_sha:
81-
return mq_sha
88+
return Base(mq_sha, is_merge_queue=True)
8289

8390
# 1) standard event payload
8491
event_sha = _detect_base_from_event(event)
8592
if event_sha:
86-
return event_sha
93+
return Base(event_sha, is_merge_queue=False)
8794

8895
# 2) base ref (e.g., PR target branch)
8996
base_ref = os.environ.get("GITHUB_BASE_REF")
9097
if base_ref:
91-
return base_ref
98+
return Base(base_ref, is_merge_queue=False)
9299

93100
msg = (
94101
"Could not detect base SHA. Ensure checkout has sufficient history "

mergify_cli/ci/scopes/cli.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class ScopeConfig(pydantic.BaseModel):
4545

4646
class Config(pydantic.BaseModel):
4747
scopes: dict[ScopeName, ScopeConfig]
48+
merge_queue_scope: str | None = "merge-queue"
4849

4950
@classmethod
5051
def from_dict(cls, data: dict[str, typing.Any] | typing.Any) -> Config: # noqa: ANN401
@@ -113,12 +114,18 @@ def detect(config_path: str) -> None:
113114
cfg = Config.from_yaml(config_path)
114115
base = base_detector.detect()
115116
try:
116-
changed = changed_files.git_changed_files(base)
117+
changed = changed_files.git_changed_files(base.ref)
117118
except changed_files.ChangedFilesError as e:
118119
raise ChangedFilesError(str(e))
119120
scopes_hit, per_scope = match_scopes(cfg, changed)
120121

121-
click.echo(f"Base: {base}")
122+
all_scopes = set(cfg.scopes.keys())
123+
if cfg.merge_queue_scope is not None:
124+
all_scopes.add(cfg.merge_queue_scope)
125+
if base.is_merge_queue:
126+
scopes_hit.add(cfg.merge_queue_scope)
127+
128+
click.echo(f"Base: {base.ref}")
122129
if scopes_hit:
123130
click.echo("Scopes touched:")
124131
for s in sorted(scopes_hit):
@@ -129,4 +136,4 @@ def detect(config_path: str) -> None:
129136
else:
130137
click.echo("No scopes matched.")
131138

132-
maybe_write_github_outputs(cfg.scopes.keys(), scopes_hit)
139+
maybe_write_github_outputs(all_scopes, scopes_hit)

mergify_cli/tests/ci/scopes/test_base_detector.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_detect_base_github_base_ref(
1515

1616
result = base_detector.detect()
1717

18-
assert result == "main"
18+
assert result == base_detector.Base("main", is_merge_queue=False)
1919

2020

2121
def test_detect_base_from_event_path(
@@ -35,7 +35,7 @@ def test_detect_base_from_event_path(
3535

3636
result = base_detector.detect()
3737

38-
assert result == "abc123"
38+
assert result == base_detector.Base("abc123", is_merge_queue=False)
3939

4040

4141
def test_detect_base_merge_queue_override(
@@ -56,7 +56,7 @@ def test_detect_base_merge_queue_override(
5656

5757
result = base_detector.detect()
5858

59-
assert result == "xyz789"
59+
assert result == base_detector.Base("xyz789", is_merge_queue=True)
6060

6161

6262
def test_detect_base_no_info(monkeypatch: pytest.MonkeyPatch) -> None:

mergify_cli/tests/ci/scopes/test_cli.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
import yaml
66

7+
from mergify_cli.ci.scopes import base_detector
78
from mergify_cli.ci.scopes import cli
89

910

@@ -23,6 +24,7 @@ def test_from_yaml_valid(tmp_path: pathlib.Path) -> None:
2324

2425
config = cli.Config.from_yaml(str(config_file))
2526
assert config.model_dump() == {
27+
"merge_queue_scope": "merge-queue",
2628
"scopes": {
2729
"backend": {"include": ("api/**/*.py", "backend/**/*.py"), "exclude": ()},
2830
"frontend": {"include": ("ui/**/*.js", "ui/**/*.tsx"), "exclude": ()},
@@ -223,7 +225,7 @@ def test_detect_with_matches(
223225
config_file.write_text(yaml.dump(config_data))
224226

225227
# Setup mocks
226-
mock_detect_base.return_value = "main"
228+
mock_detect_base.return_value = base_detector.Base("main", is_merge_queue=True)
227229
mock_git_changed.return_value = ["api/models.py", "other.txt"]
228230

229231
# Capture output
@@ -240,6 +242,7 @@ def test_detect_with_matches(
240242
assert "Base: main" in calls
241243
assert "Scopes touched:" in calls
242244
assert "- backend" in calls
245+
assert "- merge-queue" in calls
243246

244247

245248
@mock.patch("mergify_cli.ci.scopes.cli.base_detector.detect")
@@ -257,7 +260,7 @@ def test_detect_no_matches(
257260
config_file.write_text(yaml.dump(config_data))
258261

259262
# Setup mocks
260-
mock_detect_base.return_value = "main"
263+
mock_detect_base.return_value = base_detector.Base("main", is_merge_queue=False)
261264
mock_git_changed.return_value = ["other.txt"]
262265

263266
# Capture output
@@ -287,7 +290,7 @@ def test_detect_debug_output(
287290
config_file.write_text(yaml.dump(config_data))
288291

289292
# Setup mocks
290-
mock_detect_base.return_value = "main"
293+
mock_detect_base.return_value = base_detector.Base("main", is_merge_queue=False)
291294
mock_git_changed.return_value = ["api/models.py", "api/views.py"]
292295

293296
# Capture output

0 commit comments

Comments
 (0)