CI & Release / Verify documentation (push) Skipped
CI & Release / Verify simulator (push) Skipped
CI & Release / Trivy scan (push) Skipped
CI & Release / Semantic Release (push) Skipped
CI & Release / Verify documentation (pull_request) Successful in 6s
CI & Release / Verify simulator (pull_request) Failing after 10s
CI & Release / Trivy scan (pull_request) Skipped
CI & Release / Semantic Release (pull_request) Skipped
Restore docs/adr to main; add check_adrs.py CI gate so existing ADR-*.md files cannot be modified — supersede with a new numbered ADR instead.
76 lines
1.9 KiB
Python
76 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Reject modifications to accepted Architecture Decision Records."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
ADR_PREFIX = "docs/adr/ADR-"
|
|
|
|
|
|
def _git(*args: str) -> str:
|
|
return subprocess.check_output(
|
|
["git", *args],
|
|
cwd=ROOT,
|
|
text=True,
|
|
stderr=subprocess.DEVNULL,
|
|
).strip()
|
|
|
|
|
|
def _exists_on(base: str, path: str) -> bool:
|
|
try:
|
|
_git("cat-file", "-e", f"{base}:{path}")
|
|
return True
|
|
except subprocess.CalledProcessError:
|
|
return False
|
|
|
|
|
|
def find_modified_adrs(base: str) -> list[str]:
|
|
try:
|
|
diff_out = _git("diff", "--name-only", f"{base}...HEAD", "--", "docs/adr/")
|
|
except subprocess.CalledProcessError:
|
|
return []
|
|
|
|
modified: list[str] = []
|
|
for rel in diff_out.splitlines():
|
|
if not rel.startswith(ADR_PREFIX) or not rel.endswith(".md"):
|
|
continue
|
|
if _exists_on(base, rel):
|
|
modified.append(rel)
|
|
return sorted(modified)
|
|
|
|
|
|
def run_check(base: str = "origin/main") -> int:
|
|
modified = find_modified_adrs(base)
|
|
if modified:
|
|
print("Immutable ADR violation — accepted records cannot be edited:")
|
|
for path in modified:
|
|
print(f" error: {path}")
|
|
print(
|
|
"\nReversal or refinement → new ADR-NNNN file. "
|
|
"Never edit an existing ADR-*.md."
|
|
)
|
|
return 1
|
|
|
|
print(f"ADR immutability OK (base {base})")
|
|
return 0
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument(
|
|
"--base",
|
|
default="origin/main",
|
|
help="Git ref to compare against (default: origin/main)",
|
|
)
|
|
args = parser.parse_args()
|
|
sys.exit(run_check(base=args.base))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|