Skip to content

Hourly PR Queue Governance #518

Hourly PR Queue Governance

Hourly PR Queue Governance #518

name: Hourly PR Queue Governance
on:
workflow_dispatch:
schedule:
- cron: "0 * * * *"
push:
branches: [main]
paths:
- .github/workflows/hourly-pr-governance.yml
- scripts/audit_workflow_registry.py
- scripts/build_pr_queue_governance.py
- scripts/capture_pr_queue_snapshot.py
- tests/test_capture_pr_queue_snapshot.py
- tests/test_capture_pr_queue_snapshot_missing_branch.py
- tests/test_hourly_pr_governance_workflow.py
- tests/test_hourly_snapshot_split_workflow.py
- tests/test_pr_queue_governance.py
- tests/test_workflow_registry_audit.py
permissions:
actions: read
contents: read
pull-requests: read
concurrency:
group: hourly-pr-governance-${{ github.repository }}
cancel-in-progress: true
jobs:
governance-evidence:
name: Hourly PR queue governance evidence
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out reviewed source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version: "3.12"
- name: Verify the workflow contract without third-party dependencies
run: |
python - <<'PY'
import runpy
namespace = runpy.run_path("tests/test_hourly_pr_governance_workflow.py")
test_names = [
name
for name in sorted(namespace)
if name.startswith("test_hourly_governance_workflow_")
]
if not test_names:
raise RuntimeError("no hourly governance contract tests were discovered")
for name in test_names:
namespace[name]()
PY
- name: Build live PR queue governance evidence
id: governance
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
is_retryable_github_failure() {
python - <<'PY'
import json
from pathlib import Path
import re
path = Path("hourly-pr-queue-governance/pr_queue_governance_manifest.json")
if not path.is_file():
print("false")
raise SystemExit
try:
manifest = json.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError):
print("false")
raise SystemExit
status_failed = manifest.get("status") == "failed"
if not status_failed:
print("false")
raise SystemExit
failed_checks = manifest.get("failed_checks")
retryable_failed_check_names = {"github:snapshot", "github:base_sha"}
if (
not isinstance(failed_checks, list)
or not failed_checks
or not all(
isinstance(check, dict) and check.get("ok") is False
for check in failed_checks
)
):
print("false")
raise SystemExit
failed_check_names = {
str(check.get("name", "")) for check in failed_checks
}
only_transient_snapshot_checks_failed = (
bool(failed_check_names)
and failed_check_names.issubset(retryable_failed_check_names)
)
github = manifest.get("github", {})
errors = github.get("errors", []) if isinstance(github, dict) else []
retry_status = re.compile(r"\bHTTP (?:502|503|504)\b", re.IGNORECASE)
retryable = (
only_transient_snapshot_checks_failed
and bool(errors)
and all(
isinstance(error, dict)
and type(error.get("returncode")) is int
and error.get("returncode") != 0
and isinstance(error.get("stderr"), str)
and retry_status.search(error.get("stderr", "")) is not None
for error in errors
)
)
print("true" if retryable else "false")
PY
}
max_attempts=3
attempt=1
while true; do
rm -rf hourly-pr-queue-governance
mkdir -p hourly-pr-queue-governance
snapshot_rc=0
python scripts/capture_pr_queue_snapshot.py \
--repo ContextualWisdomLab/fast-mlsirm \
--out hourly-pr-queue-governance/github_snapshot.json \
|| snapshot_rc=$?
builder_rc=0
python scripts/build_pr_queue_governance.py \
--repo ContextualWisdomLab/fast-mlsirm \
--out hourly-pr-queue-governance \
--offline-snapshot hourly-pr-queue-governance/github_snapshot.json \
|| builder_rc=$?
if [[ "$snapshot_rc" -eq 0 && "$builder_rc" -eq 0 ]]; then
break
fi
retryable="$(is_retryable_github_failure)"
if [[ "$retryable" != "true" || "$attempt" -ge "$max_attempts" ]]; then
exit 1
fi
delay=$((10 * (2 ** (attempt - 1))))
echo "::warning::Transient GitHub API failure on attempt ${attempt}; retrying in ${delay}s."
sleep "$delay"
attempt=$((attempt + 1))
done
- name: Build live workflow registry drift evidence
env:
GH_TOKEN: ${{ github.token }}
run: |
python scripts/audit_workflow_registry.py \
--repo ContextualWisdomLab/fast-mlsirm \
--out hourly-pr-queue-governance/workflow_registry_audit.json
- name: Publish hourly governance evidence
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
with:
name: hourly-pr-queue-governance-${{ github.run_id }}
path: |
hourly-pr-queue-governance/github_snapshot.json
hourly-pr-queue-governance/pr_queue_governance_manifest.json
hourly-pr-queue-governance/pr_queue_governance_report.html
hourly-pr-queue-governance/workflow_registry_audit.json
if-no-files-found: error
retention-days: 30