Skip to content

Commit 7dda895

Browse files
authored
refactor: use new /quarantines/check endpoint to check for failed quarantined tests (#720)
Depends-On: Mergifyio/engine#20853
1 parent 2588395 commit 7dda895

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

mergify_cli/ci/cli.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@
4949
"--test-language",
5050
help="Test language",
5151
)
52+
@click.option(
53+
"--tests-target-branch",
54+
"-ttb",
55+
help="The branch used to check if failing tests can be ignored with Mergify's Quarantine.",
56+
required=True,
57+
envvar=["GITHUB_BASE_REF", "MERGIFY_TESTS_TARGET_BRANCH"],
58+
)
5259
@click.argument(
5360
"files",
5461
nargs=-1,
@@ -63,6 +70,7 @@ async def junit_upload( # noqa: PLR0913
6370
repository: str,
6471
test_framework: str | None,
6572
test_language: str | None,
73+
tests_target_branch: str,
6674
files: tuple[str, ...],
6775
) -> None:
6876
await _process_junit_files(
@@ -71,6 +79,7 @@ async def junit_upload( # noqa: PLR0913
7179
repository=repository,
7280
test_framework=test_framework,
7381
test_language=test_language,
82+
tests_target_branch=tests_target_branch,
7483
files=files,
7584
)
7685

@@ -110,6 +119,13 @@ async def junit_upload( # noqa: PLR0913
110119
"--test-language",
111120
help="Test language",
112121
)
122+
@click.option(
123+
"--tests-target-branch",
124+
"-ttb",
125+
help="The branch used to check if failing tests can be ignored with Mergify's Quarantine.",
126+
required=True,
127+
envvar=["GITHUB_BASE_REF", "MERGIFY_TESTS_TARGET_BRANCH"],
128+
)
113129
@click.argument(
114130
"files",
115131
nargs=-1,
@@ -124,6 +140,7 @@ async def junit_process( # noqa: PLR0913
124140
repository: str,
125141
test_framework: str | None,
126142
test_language: str | None,
143+
tests_target_branch: str,
127144
files: tuple[str, ...],
128145
) -> None:
129146
await _process_junit_files(
@@ -132,6 +149,7 @@ async def junit_process( # noqa: PLR0913
132149
repository=repository,
133150
test_framework=test_framework,
134151
test_language=test_language,
152+
tests_target_branch=tests_target_branch,
135153
files=files,
136154
)
137155

@@ -143,6 +161,7 @@ async def _process_junit_files( # noqa: PLR0913
143161
repository: str,
144162
test_framework: str | None,
145163
test_language: str | None,
164+
tests_target_branch: str,
146165
files: tuple[str, ...],
147166
) -> None:
148167
try:
@@ -195,6 +214,7 @@ async def _process_junit_files( # noqa: PLR0913
195214
api_url,
196215
token,
197216
repository,
217+
tests_target_branch,
198218
[fspan.name for fspan in failing_spans],
199219
)
200220

@@ -209,6 +229,7 @@ async def check_failing_spans_with_quarantine(
209229
api_url: str,
210230
token: str,
211231
repository: str,
232+
tests_target_branch: str,
212233
failing_spans_names: list[str],
213234
) -> None:
214235
fspans_str = "\n".join(failing_spans_names)
@@ -217,13 +238,25 @@ async def check_failing_spans_with_quarantine(
217238
err=False,
218239
)
219240

241+
try:
242+
repo_owner, repo_name = repository.split("/")
243+
except ValueError:
244+
click.echo(
245+
click.style(
246+
f"Unable to extract repository owner and name from {repository}",
247+
fg="red",
248+
),
249+
err=True,
250+
)
251+
sys.exit(1)
252+
220253
async with utils.get_http_client(
221-
server=f"{api_url}/v1/ci/{repository}/quarantine",
254+
server=f"{api_url}/v1/ci/{repo_owner}/repositories/{repo_name}/quarantines",
222255
headers={"Authorization": f"Bearer {token}"},
223256
) as client:
224257
response = await client.post(
225258
"/check",
226-
json={"tests_names": failing_spans_names},
259+
json={"tests_names": failing_spans_names, "branch": tests_target_branch},
227260
)
228261

229262
if response.status_code != 200:

mergify_cli/tests/ci/test_check_failing_spans.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
async def test_status_code_resp_not_200(
1212
respx_mock: respx.MockRouter,
1313
) -> None:
14-
respx_mock.post("/v1/ci/foo/bar/quarantine/check").respond(
14+
respx_mock.post("/v1/ci/foo/repositories/bar/quarantines/check").respond(
1515
422,
1616
json={"detail": "No subscription"},
1717
)
@@ -21,6 +21,7 @@ async def test_status_code_resp_not_200(
2121
API_MERGIFY_BASE_URL,
2222
"token",
2323
"foo/bar",
24+
"main",
2425
["test_stuff.py::foo"],
2526
)
2627

@@ -31,7 +32,7 @@ async def test_status_code_resp_not_200(
3132
async def test_no_failing_tests_quarantined(
3233
respx_mock: respx.MockRouter,
3334
) -> None:
34-
respx_mock.post("/v1/ci/foo/bar/quarantine/check").respond(
35+
respx_mock.post("/v1/ci/foo/repositories/bar/quarantines/check").respond(
3536
200,
3637
json={
3738
"quarantined_tests_names": [],
@@ -44,6 +45,7 @@ async def test_no_failing_tests_quarantined(
4445
API_MERGIFY_BASE_URL,
4546
"token",
4647
"foo/bar",
48+
"main",
4749
["test_me.py::test_mee"],
4850
)
4951

@@ -54,7 +56,7 @@ async def test_no_failing_tests_quarantined(
5456
async def test_some_failing_tests_quarantined(
5557
respx_mock: respx.MockRouter,
5658
) -> None:
57-
respx_mock.post("/v1/ci/foo/bar/quarantine/check").respond(
59+
respx_mock.post("/v1/ci/foo/repositories/bar/quarantines/check").respond(
5860
200,
5961
json={
6062
"quarantined_tests_names": ["test_me.py::test_me2"],
@@ -67,6 +69,7 @@ async def test_some_failing_tests_quarantined(
6769
API_MERGIFY_BASE_URL,
6870
"token",
6971
"foo/bar",
72+
"main",
7073
[
7174
"test_me.py::test_me1",
7275
"test_me.py::test_me2",
@@ -80,7 +83,7 @@ async def test_some_failing_tests_quarantined(
8083
async def test_all_failing_tests_quarantined(
8184
respx_mock: respx.MockRouter,
8285
) -> None:
83-
respx_mock.post("/v1/ci/foo/bar/quarantine/check").respond(
86+
respx_mock.post("/v1/ci/foo/repositories/bar/quarantines/check").respond(
8487
200,
8588
json={
8689
"quarantined_tests_names": [
@@ -95,6 +98,7 @@ async def test_all_failing_tests_quarantined(
9598
API_MERGIFY_BASE_URL,
9699
"token",
97100
"foo/bar",
101+
"main",
98102
[
99103
"test_me.py::test_me1",
100104
"test_me.py::test_me2",

mergify_cli/tests/ci/test_cli.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"GITHUB_REPOSITORY": "user/repo",
2525
"GITHUB_SHA": "3af96aa24f1d32fcfbb7067793cacc6dc0c6b199",
2626
"GITHUB_WORKFLOW": "JOB",
27+
"GITHUB_BASE_REF": "main",
2728
},
2829
id="GitHub",
2930
),
@@ -36,6 +37,7 @@
3637
"CIRCLE_REPOSITORY_URL": "https://github.com/user/repo",
3738
"CIRCLE_SHA1": "3af96aa24f1d32fcfbb7067793cacc6dc0c6b199",
3839
"CIRCLE_JOB": "JOB",
40+
"MERGIFY_TESTS_TARGET_BRANCH": "main",
3941
},
4042
id="CircleCI",
4143
),
@@ -55,12 +57,17 @@ def test_cli(env: dict[str, str], monkeypatch: pytest.MonkeyPatch) -> None:
5557
) as mocked_upload,
5658
mock.patch.object(cli_junit_upload, "check_failing_spans_with_quarantine"),
5759
):
58-
result = runner.invoke(
60+
result_process = runner.invoke(
61+
cli_junit_upload.junit_process,
62+
[str(REPORT_XML)],
63+
)
64+
result_upload = runner.invoke(
5965
cli_junit_upload.junit_upload,
6066
[str(REPORT_XML)],
6167
)
62-
assert result.exit_code == 0, result.stdout
63-
assert mocked_upload.call_count == 1
68+
assert result_process.exit_code == 0, result_process.stdout
69+
assert result_upload.exit_code == 0, result_upload.stdout
70+
assert mocked_upload.call_count == 2
6471
assert mocked_upload.call_args.kwargs == {
6572
"api_url": "https://api.mergify.com",
6673
"token": "abc",
@@ -78,6 +85,7 @@ def test_upload_error(monkeypatch: pytest.MonkeyPatch) -> None:
7885
"GITHUB_REPOSITORY": "user/repo",
7986
"GITHUB_SHA": "3af96aa24f1d32fcfbb7067793cacc6dc0c6b199",
8087
"GITHUB_WORKFLOW": "JOB",
88+
"GITHUB_BASE_REF": "main",
8189
}.items():
8290
monkeypatch.setenv(key, value)
8391

0 commit comments

Comments
 (0)