Files
pulse/scripts/release_control/readiness_assertion_guard_test.py
rcourtman 971520a8e5 fix(release-control): scrub hook git env in remaining scratch-repo git users
The core.bare=true corruption of the shared repository recurred on
2026-07-17: a script that runs scratch git commands while the pre-commit
environment from a linked worktree (absolute GIT_DIR) is still exported
re-initializes the REAL repository as bare. a0fda6b26 fixed four helper
test files but missed two spots in scripts/release_control/internal:

- verify_commit_slice_test.py's git() helper only popped GIT_INDEX_FILE,
  so its scratch 'git init' calls re-init the real repo when GIT_DIR is
  inherited. It now scrubs via the shared repo_file_io.strip_local_git_env.
- verify_commit_slice.py's production git_env() kept the inherited hook
  env even when unit tests patch REPO_ROOT to a temporary repository,
  pointing git plumbing (including index writes) at the wrong repo. It
  now scrubs in the test-patched branch only, matching format_staged_go.

Regression teeth:
- verify_commit_slice_test.py gains a canary test that exports the real
  hook env shape (absolute GIT_DIR + GIT_INDEX_FILE, no GIT_WORK_TREE —
  with GIT_WORK_TREE set the corruption does not reproduce) against a
  scratch repo + linked worktree and asserts core.bare stays false.
- repo_file_io_test.py (runs in the pre-commit battery) gains a static
  guard failing any release-control *_test.py that runs scratch
  'git init' without referencing strip_local_git_env.
- The six hand-rolled 4-var pop loops from a0fda6b26 migrate to the
  shared strip_local_git_env helper so the guard enforces one pattern.

Verified: full release-control battery green; every touched test file
also green with GIT_DIR/GIT_INDEX_FILE pointed at a canary repo's linked
worktree, canary config and status intact afterward.
2026-07-17 16:39:17 +01:00

348 lines
13 KiB
Python

import json
import os
import subprocess
import tempfile
import unittest
from pathlib import Path
from unittest import mock
import readiness_assertion_guard
from repo_file_io import strip_local_git_env
def write_status(repo_root: Path, payload: dict) -> None:
status_path = repo_root / "docs" / "release-control" / "v6" / "internal" / "status.json"
status_path.parent.mkdir(parents=True, exist_ok=True)
status_path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
def base_payload() -> dict:
return {
"readiness_assertions": [
{
"id": "RA1",
"blocking_level": "repo-ready",
"proof_type": "automated",
"proof_commands": [
{
"id": "pass",
"run": ["python3", "-c", "print('ok')"],
}
],
}
]
}
class ReadinessAssertionGuardTest(unittest.TestCase):
def git(self, repo_root: Path, *args: str) -> subprocess.CompletedProcess:
# Scrub the full hook environment: with only GIT_INDEX_FILE removed, a
# pre-commit run from a linked worktree exports an absolute GIT_DIR and
# "git init" here re-initializes the REAL repository as bare.
env = strip_local_git_env(os.environ.copy())
return subprocess.run(
["git", *args],
cwd=repo_root,
check=True,
capture_output=True,
text=True,
env=env,
)
def test_parse_args_accepts_filters_and_staged(self) -> None:
args = readiness_assertion_guard.parse_args(
[
"--staged",
"--active-target",
"--blocking-level",
"rc-ready",
"--proof-type",
"automated",
"--assertion",
"RA1",
]
)
self.assertTrue(args.staged)
self.assertTrue(args.active_target)
self.assertEqual(args.blocking_level, ["rc-ready"])
self.assertEqual(args.proof_type, ["automated"])
self.assertEqual(args.assertion, ["RA1"])
def test_selected_proof_commands_filters_by_blocking_level_and_proof_type(self) -> None:
payload = {
"readiness_assertions": [
{
"id": "RA1",
"blocking_level": "repo-ready",
"proof_type": "automated",
"proof_commands": [{"id": "a", "run": ["python3", "-c", "print('a')"]}],
},
{
"id": "RA2",
"blocking_level": "rc-ready",
"proof_type": "hybrid",
"proof_commands": [{"id": "b", "run": ["python3", "-c", "print('b')"]}],
},
{
"id": "RA3",
"blocking_level": "release-ready",
"proof_type": "hybrid",
"proof_commands": [{"id": "c", "run": ["python3", "-c", "print('c')"]}],
},
]
}
commands, errors = readiness_assertion_guard.selected_proof_commands(
payload,
blocking_levels={"repo-ready"},
proof_types={"automated"},
)
self.assertEqual(errors, [])
self.assertEqual(len(commands), 1)
self.assertEqual(commands[0]["assertion_id"], "RA1")
self.assertEqual(commands[0]["command_id"], "a")
def test_main_active_target_uses_control_plane_phase(self) -> None:
payload = {
"readiness_assertions": [
{
"id": "RA1",
"blocking_level": "repo-ready",
"proof_type": "automated",
"proof_commands": [{"id": "repo", "run": ["python3", "-c", "print('repo')"]}],
},
{
"id": "RA2",
"blocking_level": "rc-ready",
"proof_type": "hybrid",
"proof_commands": [{"id": "rc", "run": ["python3", "-c", "print('rc')"]}],
},
{
"id": "RA8",
"blocking_level": "release-ready",
"proof_type": "hybrid",
"proof_commands": [{"id": "ga", "run": ["python3", "-c", "print('ga')"]}],
},
]
}
with mock.patch.object(readiness_assertion_guard, "load_status_payload", return_value=payload), mock.patch.object(
readiness_assertion_guard,
"active_target_blocking_levels",
return_value=("repo-ready", "rc-ready"),
), mock.patch.object(readiness_assertion_guard, "run_selected_proof_commands", return_value=0) as runner:
exit_code = readiness_assertion_guard.main(["--active-target", "--proof-type", "hybrid"])
self.assertEqual(exit_code, 0)
self.assertEqual(
runner.call_args.args[0],
[
{
"assertion_id": "RA2",
"command_id": "rc",
"cwd": ".",
"run": ["python3", "-c", "print('rc')"],
}
],
)
def test_main_blocks_conflicting_active_target_and_explicit_blocking_levels(self) -> None:
payload = {
"readiness_assertions": [
{
"id": "RA8",
"blocking_level": "release-ready",
"proof_type": "hybrid",
"proof_commands": [{"id": "ga", "run": ["python3", "-c", "print('ga')"]}],
}
]
}
with mock.patch.object(readiness_assertion_guard, "load_status_payload", return_value=payload), mock.patch.object(
readiness_assertion_guard,
"active_target_blocking_levels",
return_value=("repo-ready", "rc-ready"),
):
exit_code = readiness_assertion_guard.main(
["--active-target", "--blocking-level", "release-ready", "--proof-type", "hybrid"]
)
self.assertEqual(exit_code, 1)
def test_main_skips_active_target_with_no_machine_proof_scope(self) -> None:
payload = base_payload()
with mock.patch.object(readiness_assertion_guard, "load_status_payload", return_value=payload), mock.patch.object(
readiness_assertion_guard,
"active_target_blocking_levels",
return_value=(),
), mock.patch.object(readiness_assertion_guard, "run_selected_proof_commands") as runner:
exit_code = readiness_assertion_guard.main(["--active-target", "--proof-type", "automated"])
self.assertEqual(exit_code, 0)
runner.assert_not_called()
def test_selected_proof_commands_blocks_automated_assertion_without_commands(self) -> None:
commands, errors = readiness_assertion_guard.selected_proof_commands(
{
"readiness_assertions": [
{
"id": "RA1",
"blocking_level": "repo-ready",
"proof_type": "automated",
}
]
},
blocking_levels={"repo-ready"},
proof_types={"automated"},
)
self.assertEqual(commands, [])
self.assertEqual(errors, ["RA1 is automated but has no proof_commands"])
def test_deduplicated_proof_commands_groups_shared_runs(self) -> None:
deduped = readiness_assertion_guard.deduplicated_proof_commands(
[
{
"assertion_id": "RA3",
"command_id": "shared-a",
"cwd": ".",
"run": ["python3", "-c", "print('shared')"],
},
{
"assertion_id": "RA4",
"command_id": "shared-b",
"cwd": ".",
"run": ["python3", "-c", "print('shared')"],
},
{
"assertion_id": "RA2",
"command_id": "unique",
"cwd": ".",
"run": ["python3", "-c", "print('unique')"],
},
]
)
self.assertEqual(len(deduped), 2)
self.assertEqual(deduped[0]["assertion_ids"], ["RA3", "RA4"])
self.assertEqual(deduped[0]["command_ids"], ["shared-a", "shared-b"])
self.assertEqual(deduped[1]["assertion_ids"], ["RA2"])
def test_main_can_read_staged_status_payload(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
repo_root = Path(tmpdir)
self.git(repo_root, "init")
payload = base_payload()
payload["readiness_assertions"][0]["proof_commands"][0]["run"] = [
"python3",
"-c",
"from pathlib import Path; Path('proof.out').write_text('ok', encoding='utf-8')",
]
write_status(repo_root, payload)
self.git(repo_root, "add", "docs/release-control/v6/internal/status.json")
payload["readiness_assertions"][0]["proof_commands"][0]["run"] = ["python3", "-c", "raise SystemExit(1)"]
write_status(repo_root, payload)
with mock.patch.object(readiness_assertion_guard, "REPO_ROOT", repo_root), mock.patch(
"repo_file_io.REPO_ROOT", repo_root
):
exit_code = readiness_assertion_guard.main(
["--staged", "--blocking-level", "repo-ready", "--proof-type", "automated"]
)
self.assertEqual(exit_code, 0)
self.assertEqual((repo_root / "proof.out").read_text(encoding="utf-8"), "ok")
def test_run_selected_proof_commands_executes_staged_repo_python_script(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
repo_root = Path(tmpdir)
self.git(repo_root, "init")
script_rel = "scripts/release_control/proof_script.py"
script_path = repo_root / script_rel
script_path.parent.mkdir(parents=True, exist_ok=True)
script_path.write_text(
"from helper_module import write_ok\nwrite_ok()\n",
encoding="utf-8",
)
helper_path = repo_root / "scripts" / "release_control" / "helper_module.py"
helper_path.write_text(
"from pathlib import Path\n\n\ndef write_ok():\n Path('proof.out').write_text('ok', encoding='utf-8')\n",
encoding="utf-8",
)
self.git(repo_root, "add", script_rel, "scripts/release_control/helper_module.py")
script_path.write_text("raise SystemExit(1)\n", encoding="utf-8")
commands = [
{
"assertion_id": "RA8",
"command_id": "staged-script",
"cwd": ".",
"run": ["python3", script_rel],
}
]
with mock.patch.object(readiness_assertion_guard, "REPO_ROOT", repo_root), mock.patch(
"repo_file_io.REPO_ROOT", repo_root
):
exit_code = readiness_assertion_guard.run_selected_proof_commands(commands, staged=True)
self.assertEqual(exit_code, 0)
self.assertEqual((repo_root / "proof.out").read_text(encoding="utf-8"), "ok")
def test_staged_repo_python_script_preserves_file_and_argv_identity(self) -> None:
with tempfile.TemporaryDirectory() as tmpdir:
repo_root = Path(tmpdir)
self.git(repo_root, "init")
script_rel = "scripts/release_control/proof_script.py"
script_path = repo_root / script_rel
script_path.parent.mkdir(parents=True, exist_ok=True)
script_path.write_text(
"\n".join(
[
"from pathlib import Path",
"import sys",
"",
"Path('proof.out').write_text(",
" f'{Path(__file__).resolve()}\\n{sys.argv[0]}\\n{sys.argv[1]}',",
" encoding='utf-8',",
")",
"",
]
),
encoding="utf-8",
)
self.git(repo_root, "add", script_rel)
script_path.write_text("raise SystemExit(1)\n", encoding="utf-8")
commands = [
{
"assertion_id": "RA8",
"command_id": "staged-script",
"cwd": ".",
"run": ["python3", script_rel, "--flag"],
}
]
with mock.patch.object(readiness_assertion_guard, "REPO_ROOT", repo_root), mock.patch(
"repo_file_io.REPO_ROOT", repo_root
):
exit_code = readiness_assertion_guard.run_selected_proof_commands(commands, staged=True)
self.assertEqual(exit_code, 0)
self.assertEqual(
(repo_root / "proof.out").read_text(encoding="utf-8").splitlines(),
[str(script_path.resolve()), str(script_path.resolve()), "--flag"],
)
if __name__ == "__main__":
unittest.main()