diff --git a/scripts/ci/analyze_e2e_flaky_tests.py b/scripts/ci/analyze_e2e_flaky_tests.py index bf5aef53ffadb..c56fb7e48ebfc 100755 --- a/scripts/ci/analyze_e2e_flaky_tests.py +++ b/scripts/ci/analyze_e2e_flaky_tests.py @@ -65,8 +65,13 @@ def escape_slack_mrkdwn(text: str) -> str: def gh_api(endpoint: str, **kwargs: str) -> str | None: - """Call GitHub API via gh CLI.""" - cmd = ["gh", "api", endpoint] + """Call GitHub API via gh CLI. + + Forces ``--method GET``: ``gh api`` defaults to POST whenever ``-f`` + parameters are present, which makes read-only endpoints (such as the + workflow runs list) return 404. + """ + cmd = ["gh", "api", "--method", "GET", endpoint] for key, value in kwargs.items(): cmd.extend(["-f", f"{key}={value}"]) result = subprocess.run(cmd, capture_output=True, text=True, check=False) diff --git a/scripts/tests/ci/test_analyze_e2e_flaky_tests.py b/scripts/tests/ci/test_analyze_e2e_flaky_tests.py index ff7097c7aeeca..fcd56d15adae7 100644 --- a/scripts/tests/ci/test_analyze_e2e_flaky_tests.py +++ b/scripts/tests/ci/test_analyze_e2e_flaky_tests.py @@ -17,8 +17,10 @@ from __future__ import annotations import importlib.util +import subprocess import sys from pathlib import Path +from unittest.mock import patch import pytest @@ -37,6 +39,17 @@ def analyze_module(): return module +class TestGhApi: + def test_forces_get_method(self, analyze_module): + """`gh api` defaults to POST when -f is passed; we must force GET to avoid 404.""" + completed = subprocess.CompletedProcess(args=[], returncode=0, stdout="{}", stderr="") + with patch.object(subprocess, "run", return_value=completed) as mock_run: + analyze_module.gh_api("repos/apache/airflow/actions/workflows/x/runs", branch="main") + args = mock_run.call_args[0][0] + assert "--method" in args + assert args[args.index("--method") + 1] == "GET" + + class TestEscapeSlackMrkdwn: def test_escapes_ampersand(self, analyze_module): assert analyze_module.escape_slack_mrkdwn("a & b") == "a & b"