Something went wrong. Try again.
Personal fork of prime agent. Mirror of: https://mnemosyne.sigilzero.dev/sigilzero/prime-agent
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156#!/usr/bin/env python3"""Test battery for the PR-files-to-crates mapping (ci.yml's changes job).
The contracts, pinned on real pulls/files-API shapes (the `filename` +`previous_filename` rows — the API's own field names, so a field-nameregression fails safe instead of silently narrowing to nothing): - a crate-only PR maps to those crates and their transitive dependents; - ANY non-crate path - and a rename's removed side too - fails safe to the full selection; - an undecidable list (empty input, an empty filename row, the API's 3000-file ceiling) fails safe to the full selection, never to an empty selection: a narrowed wave that runs nothing would masquerade as green.
Run: python3 scripts/test_ci_pr_crates.py (or: make shard-gates)"""
from __future__ import annotations
import importlib.utilimport osimport subprocessimport sysimport tempfileimport unittestfrom pathlib import Path
SCRIPTS_DIR = Path(__file__).resolve().parentsys.path.insert(0, str(SCRIPTS_DIR))
import ci_pr_crates # noqa: E402 (the tool under test)
MAPPER = SCRIPTS_DIR / "ci_pr_crates.py"
def run_mapper(rows: list[str]) -> tuple[int, str, dict[str, str]]: output = Path(tempfile.mkdtemp()) / "github-output" env = dict(os.environ) env["GITHUB_OUTPUT"] = str(output) listing = Path(tempfile.mkdtemp()) / "pr-files.tsv" listing.write_text("\n".join(rows) + "\n", encoding="utf-8") result = subprocess.run([sys.executable, str(MAPPER), str(listing)], capture_output=True, text=True, env=env, check=False) outputs = {} for line in output.read_text().splitlines(): key, _, value = line.partition("=") outputs[key] = value return result.returncode, result.stdout, outputs
class TheMappingTestCase(unittest.TestCase):
def test_a_crate_only_pr_narrows_to_those_crates(self): rc, out, outputs = run_mapper([ "crates/pa-daemon/src/main.rs", "crates/pa-daemon/src/roster.rs", "crates/pa-tui/src/view/runs.rs", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "pa-cli,pa-daemon,pa-tui") self.assertIn("crates (3: pa-cli, pa-daemon, pa-tui)", outputs["scope"])
def test_any_non_crate_path_fails_safe_to_the_full_selection(self): rc, out, outputs = run_mapper([ "crates/pa-core/src/lib.rs", ".github/workflows/ci.yml", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertEqual(outputs["scope"], "all") self.assertIn("non-crate path .github/workflows/ci.yml", out)
def test_a_renames_removed_side_counts_too(self): # A rename from a non-crate path INTO a crate: the PR removed the # old path, so the full selection runs. rc, out, outputs = run_mapper([ "crates/pa-cli/src/new.rs\tdocs/old-location.md", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertIn("non-crate path docs/old-location.md", out)
def test_a_rename_within_crates_narrows_to_both_crates(self): rc, out, outputs = run_mapper([ "crates/pa-tui/src/editor/selection.rs\tcrates/pa-tui/src/selection.rs", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "pa-cli,pa-tui")
def test_pa_types_only_runs_every_crate(self): rc, out, outputs = run_mapper(["crates/pa-types/src/lib.rs"]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], ",".join(sorted(ci_pr_crates.WORKSPACE_DEPS)))
def test_pa_tui_only_runs_pa_cli_too(self): rc, out, outputs = run_mapper(["crates/pa-tui/src/lib.rs"]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "pa-cli,pa-tui")
def test_an_unknown_crate_fails_safe(self): rc, out, outputs = run_mapper(["crates/pa-future/src/lib.rs"]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertIn("unknown crate pa-future", out)
def test_an_empty_filename_row_fails_safe(self): # The field-name regression the reviewer demanded pinned: a row whose # filename column is empty (e.g. reading `.path` from the files API, # whose field is `filename`) must never narrow the wave to nothing - # the run fails safe to the full selection instead. rc, out, outputs = run_mapper([ "\tcrates/pa-core/src/lib.rs", "crates/pa-daemon/src/lib.rs", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertEqual(outputs["scope"], "all") self.assertIn("empty filename", out)
def test_a_null_field_read_also_fails_safe(self): # jq renders a missing field as the string "null": not a crate path, # so the full selection runs (nothing narrows on a broken column). rc, out, outputs = run_mapper([ "null\tdocs/removed.md", "crates/pa-core/src/lib.rs", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "")
def test_an_empty_list_fails_safe_to_the_full_selection(self): rc, out, outputs = run_mapper([]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertEqual(outputs["scope"], "all")
def test_a_whitespace_prefixed_path_is_a_non_crate_path(self): # The fields are read raw: a path with a leading space (or any # non-crate prefix) must never be stripped into a crate mapping. rc, out, outputs = run_mapper([ " crates/pa-core/src/lib.rs", "crates/pa-tui/src/lib.rs", ]) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertIn("non-crate path crates/pa-core/src/lib.rs", out)
def test_the_files_api_ceiling_fails_safe(self): rows = ["crates/pa-core/src/lib.rs"] * ci_pr_crates.FILES_API_CEILING rc, out, outputs = run_mapper(rows) self.assertEqual(rc, 0, out) self.assertEqual(outputs["crates"], "") self.assertIn("ceiling", out)
if __name__ == "__main__": unittest.main(verbosity=2)