From 018f3f4750d792861232d723560d8546bea7d026 Mon Sep 17 00:00:00 2001 From: Jiacheng Xu <13862180016@163.com> Date: Fri, 31 Jul 2026 21:18:03 +0800 Subject: [PATCH 1/2] ci: honor Triage role for GPU requests --- .ci/slurm/runner.py | 2 +- .ci/slurm/test_runner.py | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.ci/slurm/runner.py b/.ci/slurm/runner.py index 894e9dc0ea..1e033f3d73 100644 --- a/.ci/slurm/runner.py +++ b/.ci/slurm/runner.py @@ -1220,7 +1220,7 @@ def github_admit() -> int: event_data = json.loads(Path(os.environ["GITHUB_EVENT_PATH"]).read_text(encoding="utf-8")) user = event_data["comment"]["user"]["login"] permission = _gh("repos/{}/collaborators/{}/permission".format(repository, user)) - if permission.get("permission") not in ("admin", "maintain", "write", "triage"): + if permission.get("role_name") not in ("admin", "maintain", "write", "triage"): raise ValueError("commenter needs Triage permission") number = str(event_data["issue"]["number"]) pull = _gh("repos/{}/pulls/{}".format(repository, number)) diff --git a/.ci/slurm/test_runner.py b/.ci/slurm/test_runner.py index afbfd6a0e7..37fd2a3526 100644 --- a/.ci/slurm/test_runner.py +++ b/.ci/slurm/test_runner.py @@ -808,6 +808,26 @@ def test_mpi_startup_failure_requires_complete_signature(self): class GitHubTests(unittest.TestCase): + def test_read_user_cannot_trigger_pr_validation(self): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + event = root / "event.json" + event.write_text(json.dumps({ + "comment": {"user": {"login": "reader"}}, + "issue": {"number": 23}, + }), encoding="utf-8") + output = root / "output" + environment = { + "GITHUB_EVENT_NAME": "issue_comment", "GITHUB_REPOSITORY": "owner/repo", + "GITHUB_EVENT_PATH": str(event), "GITHUB_OUTPUT": str(output), + } + with mock.patch.dict(os.environ, environment, clear=True), \ + mock.patch("runner._gh", return_value={"permission": "read", "role_name": "read"}) as api: + with self.assertRaisesRegex(ValueError, "commenter needs Triage permission"): + runner.github_admit() + api.assert_called_once_with("repos/owner/repo/collaborators/reader/permission") + self.assertFalse(output.exists()) + def test_pr_comment_is_created_queued_and_updated_in_place(self): source_sha = "a" * 40 with tempfile.TemporaryDirectory() as directory: @@ -819,7 +839,7 @@ def test_pr_comment_is_created_queued_and_updated_in_place(self): }), encoding="utf-8") output = root / "output" admitted = [ - {"permission": "triage"}, + {"permission": "read", "role_name": "triage"}, {"state": "open", "head": {"repo": {"full_name": "owner/fork"}, "sha": source_sha}}, {"id": 456}, {"id": 123}, ] From 39fcb1f7128a544562b610a9b6bfc9458fa929a4 Mon Sep 17 00:00:00 2001 From: Jiacheng Xu <13862180016@163.com> Date: Sat, 1 Aug 2026 01:24:44 +0800 Subject: [PATCH 2/2] ci: retry transient Slurm accounting failures --- .ci/slurm/slurm.py | 11 ++++++++++- .ci/slurm/test_runner.py | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.ci/slurm/slurm.py b/.ci/slurm/slurm.py index ace368baff..04e057d214 100644 --- a/.ci/slurm/slurm.py +++ b/.ci/slurm/slurm.py @@ -71,8 +71,17 @@ def wait( raise time.sleep(self.poll_seconds) + failures = 0 for _ in range(30): - rows = self._accounting(ids) + try: + rows = self._accounting(ids) + failures = 0 + except SlurmError: + failures += 1 + if failures == 6: + raise + time.sleep(self.poll_seconds) + continue required = [] for job in jobs: count = self.jobs[job] diff --git a/.ci/slurm/test_runner.py b/.ci/slurm/test_runner.py index 37fd2a3526..4518caed0a 100644 --- a/.ci/slurm/test_runner.py +++ b/.ci/slurm/test_runner.py @@ -259,6 +259,18 @@ def test_submit_and_accounting_require_each_array_task(self): self.assertEqual(states["101_0"], ("COMPLETED", "0:0")) self.assertEqual(states["101_1"], ("FAILED", "1:0")) + def test_accounting_retries_transient_failure(self): + responses = [ + mock.Mock(returncode=0, stdout="", stderr=""), + mock.Mock(returncode=1, stdout="", stderr="Socket timed out"), + mock.Mock(returncode=0, stdout="101|COMPLETED|0:0\n", stderr=""), + ] + with mock.patch("slurm.subprocess.run", side_effect=responses): + client = slurm.Slurm(poll_seconds=0) + client.jobs["101"] = None + states = client.wait(("101",)) + self.assertEqual(states["101"], ("COMPLETED", "0:0")) + def test_pass_requires_successful_slurm_accounting(self): config = runner.Config( runner.Site("Example cluster", "https://cluster.example/", "Computing resources were provided by"),