mirror of
https://github.com/rustfs/rustfs.git
synced 2026-10-26 22:07:53 +00:00
116 lines
6.8 KiB
Python
116 lines
6.8 KiB
Python
"""Runner diagnostics must remain read-only when the shared fleet is unavailable."""
|
|
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
import subprocess
|
|
import tempfile
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
import inspect_validation_runner as inspection
|
|
|
|
|
|
class RunnerInspectionTests(unittest.TestCase):
|
|
def request(self):
|
|
return {"validation_runner_inspect_only": True, "validation_case": "",
|
|
"validation_tools_only": False, "i05_diagnostic_branch": "timeout",
|
|
"validation_tools_run_attempt": "1"}
|
|
|
|
def test_exclusive_request_rejects_every_execution_mode_before_api_access(self):
|
|
inspection.validate_request(self.request())
|
|
for key, value in [("validation_runner_inspect_only", False),
|
|
("validation_case", "environment.inspect"), ("build_run_id", "123"),
|
|
("validation_package_sha", "a" * 40), ("validation_tools_only", True),
|
|
("validation_native_tools", True), ("validation_shared_tools", True),
|
|
("validation_manager_tools", True), ("validation_cleanup_run_id", "123"),
|
|
("auto_testing_sha", "a" * 40), ("validation_tools_run_id", "123"),
|
|
("i05_diagnostic_branch", "queued-successor"),
|
|
("validation_tools_run_attempt", "2")]:
|
|
with self.subTest(key=key), self.assertRaises(ValueError):
|
|
inspection.validate_request({**self.request(), key: value})
|
|
|
|
def fixture(self, runners, *, unknown_jobs=False):
|
|
def api(path):
|
|
self.assertTrue(path.startswith("repos/rustfs/rustfs/actions/"))
|
|
if "/runners?" in path:
|
|
return {"runners": runners}
|
|
if "/runs?status=queued&" in path:
|
|
return {"workflow_runs": [{"id": 123, "name": "RustFS Functional Chain",
|
|
"status": "queued", "created_at": "2026-10-26T00:00:00Z", "html_url": "run-url"}]}
|
|
if "/runs?status=" in path:
|
|
return {"workflow_runs": []}
|
|
self.assertIn("/runs/123/jobs?", path)
|
|
return {"jobs": [] if unknown_jobs else [
|
|
{"id": 456, "name": "validation", "status": "queued", "runner_name": "",
|
|
"labels": ["smoke-testing"], "html_url": "job-url", "steps": [{"secret": "excluded"}]},
|
|
{"id": 457, "name": "native", "status": "in_progress", "labels": ["ubuntu-latest"]},
|
|
{"id": 458, "name": "prior", "status": "completed", "labels": ["smoke-testing"]}]}
|
|
return api
|
|
|
|
def test_offline_idle_busy_and_unregistered_are_distinct_with_only_fleet_jobs(self):
|
|
runner = {"id": 7, "name": "rustfs-smoke-testing", "status": "offline", "busy": False,
|
|
"labels": [{"name": "smoke-testing"}], "extra": {"secret": "excluded"}}
|
|
for state, busy, expected in [("offline", False, "offline"), ("online", True, "online-busy"),
|
|
("online", False, "online-idle"), (None, False, "unregistered")]:
|
|
with self.subTest(expected=expected):
|
|
rows = [{**runner, "status": state, "busy": busy}] if state else []
|
|
report = {}
|
|
with patch.object(inspection, "api", side_effect=self.fixture(rows)):
|
|
inspection.collect(report)
|
|
self.assertEqual(report["runnerAvailability"], expected)
|
|
self.assertTrue(report["complete"])
|
|
self.assertEqual([row["jobId"] for row in report["fleetJobs"]], [456])
|
|
self.assertNotIn("secret", json.dumps(report))
|
|
|
|
def test_jobless_workflow_is_retained_without_inventing_a_runner_assignment(self):
|
|
report = {}
|
|
with patch.object(inspection, "api", side_effect=self.fixture([], unknown_jobs=True)):
|
|
inspection.collect(report)
|
|
self.assertEqual(report["fleetJobs"], [])
|
|
self.assertEqual(report["runsWithoutJobs"][0]["runId"], 123)
|
|
|
|
def test_inventory_pagination_is_bounded_and_cannot_claim_complete_when_truncated(self):
|
|
row = {"id": 7}
|
|
with patch.object(inspection, "api", return_value={"runners": [row] * 100}) as api:
|
|
with self.assertRaisesRegex(ValueError, "bounded inspection"):
|
|
inspection.pages("repos/rustfs/rustfs/actions/runners", "runners")
|
|
self.assertEqual(api.call_count, 10)
|
|
|
|
def test_api_failure_keeps_partial_report_without_subprocess_diagnostics_or_fleet_claims(self):
|
|
for inputs, expected_calls in [(self.request(), 1), ({**self.request(), "validation_tools_only": True}, 0)]:
|
|
with self.subTest(inputs=inputs), tempfile.TemporaryDirectory() as directory:
|
|
output = Path(directory) / "report.json"
|
|
with patch.dict(os.environ, RUNNER_INSPECTION_INPUTS=json.dumps(inputs)), \
|
|
patch.object(inspection.sys, "argv", ["inspect", "--output", str(output)]), \
|
|
patch.object(inspection, "api", side_effect=subprocess.CalledProcessError(
|
|
1, ["gh", "api"], stderr=b"secret-token")) as api:
|
|
self.assertEqual(inspection.main(), 1)
|
|
report = json.loads(output.read_text())
|
|
self.assertFalse(report["complete"])
|
|
for field in ("mutated", "fleetAccessed", "cleanStateCertified",
|
|
"sharedWorkflowIdleCertified", "canonicalCasePassClaimed"):
|
|
self.assertIs(report[field], False)
|
|
self.assertNotIn("secret-token", output.read_text())
|
|
self.assertEqual(api.call_count, expected_calls)
|
|
|
|
def test_workflow_is_hosted_and_uses_a_separate_concurrency_group(self):
|
|
workflow = Path(__file__).resolve().parents[1] / ".github/workflows/rustfs-functional-chain.yml"
|
|
source = workflow.read_text()
|
|
job = source.split(" validation-runner-inspection:\n", 1)[1].split(" validation-package-request:", 1)[0]
|
|
self.assertIn("runs-on: ubuntu-latest", job)
|
|
self.assertIn("timeout-minutes: 10", job)
|
|
self.assertIn("RUNNER_INSPECTION_INPUTS: ${{ toJSON(inputs) }}", job)
|
|
self.assertIn("if: ${{ always() }}", job)
|
|
self.assertNotIn("RUSTFS_SECRET_KEY", job)
|
|
concurrency = source.split("concurrency:\n", 1)[1].split("jobs:\n", 1)[0]
|
|
self.assertLess(concurrency.index("validation_runner_inspect_only"), concurrency.index("validation_package_sha"))
|
|
self.assertIn("rustfs-functional-validation-runner-inspection", concurrency)
|
|
for name in ("validation-package-request", "validation-package", "prepare", "validation"):
|
|
job = source.split(" " + name + ":\n", 1)[1].split("\n runs-on:", 1)[0].split("\n uses:", 1)[0]
|
|
self.assertIn("!inputs.validation_runner_inspect_only", job)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|