infra: enforce governance registry sync checks in CI (#330)
Some checks failed
Gitea CI / test (pull_request) Waiting to run
Gitea CI / test (push) Has been cancelled

This commit is contained in:
agentson
2026-02-28 14:36:05 +09:00
parent 13a6d6612a
commit 2e394cd17c
2 changed files with 75 additions and 1 deletions

View File

@@ -13,6 +13,8 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -26,7 +28,18 @@ jobs:
run: python3 scripts/session_handover_check.py --strict run: python3 scripts/session_handover_check.py --strict
- name: Validate governance assets - name: Validate governance assets
run: python3 scripts/validate_governance_assets.py run: |
RANGE=""
if [ "${{ github.event_name }}" = "pull_request" ] && [ -n "${{ github.event.pull_request.base.sha }}" ]; then
RANGE="${{ github.event.pull_request.base.sha }}...${{ github.sha }}"
elif [ -n "${{ github.event.before }}" ] && [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then
RANGE="${{ github.event.before }}...${{ github.sha }}"
fi
if [ -n "$RANGE" ]; then
python3 scripts/validate_governance_assets.py "$RANGE"
else
python3 scripts/validate_governance_assets.py
fi
- name: Validate Ouroboros docs - name: Validate Ouroboros docs
run: python3 scripts/validate_ouroboros_docs.py run: python3 scripts/validate_ouroboros_docs.py

View File

@@ -3,9 +3,12 @@
from __future__ import annotations from __future__ import annotations
import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
REQUIREMENTS_REGISTRY = "docs/ouroboros/01_requirements_registry.md"
def must_contain(path: Path, required: list[str], errors: list[str]) -> None: def must_contain(path: Path, required: list[str], errors: list[str]) -> None:
if not path.exists(): if not path.exists():
@@ -17,8 +20,64 @@ def must_contain(path: Path, required: list[str], errors: list[str]) -> None:
errors.append(f"{path}: missing required token -> {token}") errors.append(f"{path}: missing required token -> {token}")
def normalize_changed_path(path: str) -> str:
normalized = path.strip().replace("\\", "/")
if normalized.startswith("./"):
normalized = normalized[2:]
return normalized
def is_policy_file(path: str) -> bool:
normalized = normalize_changed_path(path)
if not normalized.endswith(".md"):
return False
if not normalized.startswith("docs/ouroboros/"):
return False
return normalized != REQUIREMENTS_REGISTRY
def load_changed_files(args: list[str], errors: list[str]) -> list[str]:
if not args:
return []
# Single range input (e.g. BASE..HEAD or BASE...HEAD)
if len(args) == 1 and ".." in args[0]:
range_spec = args[0]
try:
completed = subprocess.run(
["git", "diff", "--name-only", range_spec],
check=True,
capture_output=True,
text=True,
)
except (subprocess.CalledProcessError, FileNotFoundError) as exc:
errors.append(f"failed to load changed files from range '{range_spec}': {exc}")
return []
return [
normalize_changed_path(line)
for line in completed.stdout.splitlines()
if line.strip()
]
return [normalize_changed_path(path) for path in args if path.strip()]
def validate_registry_sync(changed_files: list[str], errors: list[str]) -> None:
if not changed_files:
return
changed_set = set(changed_files)
policy_changed = any(is_policy_file(path) for path in changed_set)
registry_changed = REQUIREMENTS_REGISTRY in changed_set
if policy_changed and not registry_changed:
errors.append(
"policy file changed without updating docs/ouroboros/01_requirements_registry.md"
)
def main() -> int: def main() -> int:
errors: list[str] = [] errors: list[str] = []
changed_files = load_changed_files(sys.argv[1:], errors)
pr_template = Path(".gitea/PULL_REQUEST_TEMPLATE.md") pr_template = Path(".gitea/PULL_REQUEST_TEMPLATE.md")
issue_template = Path(".gitea/ISSUE_TEMPLATE/runtime_verification.md") issue_template = Path(".gitea/ISSUE_TEMPLATE/runtime_verification.md")
@@ -81,6 +140,8 @@ def main() -> int:
if not handover_script.exists(): if not handover_script.exists():
errors.append(f"missing file: {handover_script}") errors.append(f"missing file: {handover_script}")
validate_registry_sync(changed_files, errors)
if errors: if errors:
print("[FAIL] governance asset validation failed") print("[FAIL] governance asset validation failed")
for err in errors: for err in errors: