repo-manager/tests/test_register_command.py

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"