144 lines
4.5 KiB
Python
144 lines
4.5 KiB
Python
"""Shared repository register spine coverage for RMGR-WP-0008-T05."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import yaml
|
|
|
|
from repo_manager.commands.register import mutate_register_entry
|
|
from repo_manager.observe import observe_repository
|
|
from repo_manager.parse.register import SUPPORTED_REGISTER_KINDS
|
|
|
|
|
|
def _git(repo: Path, *args: str) -> None:
|
|
subprocess.run(["git", *args], cwd=repo, check=True, capture_output=True)
|
|
|
|
|
|
def _fixture(tmp_path: Path) -> Path:
|
|
repo = tmp_path / "pilot"
|
|
repo.mkdir()
|
|
_git(repo, "init")
|
|
_git(repo, "config", "user.email", "test@example.com")
|
|
_git(repo, "config", "user.name", "Test")
|
|
(repo / ".repo-classification.yaml").write_text(
|
|
"repo_classification:\n category: tooling\n domain: infotech\n",
|
|
encoding="utf-8",
|
|
)
|
|
_git(repo, "add", ".")
|
|
_git(repo, "commit", "-m", "seed")
|
|
return repo
|
|
|
|
|
|
def test_all_register_kinds_are_file_backed_and_indexed(tmp_path: Path) -> None:
|
|
repo = _fixture(tmp_path)
|
|
payloads = {
|
|
"sbom-inventory": {"package_name": "pyyaml", "ecosystem": "pypi"},
|
|
"repo-goals": {"description": "Keep repository records authoritative."},
|
|
"upstream-contributions": {"type": "patch"},
|
|
"technical-debt": {"severity": "medium"},
|
|
"extension-points": {"ep_type": "api"},
|
|
"register-entries": {"register_kind": "custom"},
|
|
}
|
|
|
|
for sequence, kind in enumerate(sorted(SUPPORTED_REGISTER_KINDS), start=1):
|
|
result = mutate_register_entry(
|
|
repo,
|
|
kind,
|
|
f"ENTRY-{sequence:02d}",
|
|
operation="upsert",
|
|
title=f"{kind} entry",
|
|
data=payloads[kind],
|
|
)
|
|
assert result.status == "applied", result
|
|
assert result.evidence["git_sha"]
|
|
document = yaml.safe_load((repo / "registers" / f"{kind}.yaml").read_text())
|
|
assert document["schema"] == "repo-manager.register.v0"
|
|
assert document["kind"] == kind
|
|
|
|
snapshot, index = observe_repository(repo, slug="pilot")
|
|
records = [record for record in index.work_records if record.kind.startswith("register:")]
|
|
assert snapshot["index"]["register_entry_count"] == 6
|
|
assert len(records) == 6
|
|
|
|
|
|
def test_update_note_defer_and_idempotency(tmp_path: Path, monkeypatch) -> None:
|
|
repo = _fixture(tmp_path)
|
|
monkeypatch.setenv("RM_IDEMPOTENCY_PATH", str(tmp_path / "idempotency.json"))
|
|
created = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="upsert",
|
|
title="Coupled persistence",
|
|
data={"severity": "high"},
|
|
idempotency_key="td-create",
|
|
)
|
|
replay = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="upsert",
|
|
title="Coupled persistence",
|
|
data={"severity": "high"},
|
|
idempotency_key="td-create",
|
|
)
|
|
assert replay.evidence["git_sha"] == created.evidence["git_sha"]
|
|
|
|
updated = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="upsert",
|
|
status="in_progress",
|
|
data={"severity": "critical"},
|
|
)
|
|
assert updated.status == "applied"
|
|
noted = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="note",
|
|
note="Migration owner assigned.",
|
|
note_author="operator",
|
|
)
|
|
assert noted.status == "applied"
|
|
deferred = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="defer",
|
|
)
|
|
assert deferred.status == "applied"
|
|
|
|
document = yaml.safe_load((repo / "registers" / "technical-debt.yaml").read_text())
|
|
entry = document["entries"][0]
|
|
assert entry["status"] == "deferred"
|
|
assert entry["severity"] == "critical"
|
|
assert entry["notes"][0]["author"] == "operator"
|
|
|
|
|
|
def test_schema_and_safety_validation(tmp_path: Path) -> None:
|
|
repo = _fixture(tmp_path)
|
|
missing = mutate_register_entry(
|
|
repo,
|
|
"sbom-inventory",
|
|
"PKG-01",
|
|
operation="upsert",
|
|
title="package",
|
|
data={"package_name": "demo"},
|
|
)
|
|
assert missing.status == "rejected"
|
|
assert missing.error and "ecosystem" in missing.error["message"]
|
|
|
|
protected = mutate_register_entry(
|
|
repo,
|
|
"technical-debt",
|
|
"TD-001",
|
|
operation="upsert",
|
|
title="Debt",
|
|
data={"id": "replacement"},
|
|
)
|
|
assert protected.status == "rejected"
|
|
assert protected.error and protected.error["code"] == "validation_error"
|