From 22a1752eb34b5939a8a7152293b405585ef91651 Mon Sep 17 00:00:00 2001 From: core-devops Date: Mon, 11 May 2026 12:32:22 -0700 Subject: [PATCH] feat(ci): add all-required sentinel job (RFC#219 Phase 4 / closes internal#286) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the `all-required` aggregator sentinel job to .gitea/workflows/ci.yml, mirroring the molecule-controlplane Phase 2a impl. The sentinel needs every non-event-gated job (changes, platform-build, canvas-build, shellcheck, python-lint) and asserts result==success per dep so skipped-as-green can't sneak through. Two immediate effects: 1. .gitea/workflows/ci-required-drift.yml stops hard-failing with exit 3 on the missing sentinel (see comment lines 26-31 of that workflow). 2. Branch protection can now (Step 5 follow-up, separate PR per feedback_never_admin_merge_bypass) point status_check_contexts at the single 'ci / all-required (pull_request)' name and CI churn underneath no longer requires protection edits. NOT in this PR (deferred Step 5 follow-up): - PATCH branch_protections/main to add 'ci / all-required (pull_request)' to status_check_contexts — Owners-tier change, separate PR. - Mirror the same context into audit-force-merge.yml REQUIRED_CHECKS env (RFC §6 — drift detector F3 will flag if the two diverge). Refs: - internal#219 (parent RFC, §2 Aggregator sentinel) - internal#286 (Phase 4 emergency bump — 2026-05-11 broken-merge evidence) - molecule-controlplane Phase 2a (reference impl, CP PR#112) - feedback_phantom_required_check_after_gitea_migration (incident class) - feedback_path_filtered_workflow_cant_be_required (sentinel has no paths: filter; fires on every push/PR per RFC §2) Co-Authored-By: Claude Opus 4.7 (1M context) --- .gitea/workflows/ci.yml | 74 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 6936ae9d..ffeebe19 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -451,3 +451,77 @@ jobs: echo " adjusting the floor with rationale in COVERAGE_FLOOR.md." exit 1 fi + + all-required: + # Aggregator sentinel — RFC internal#219 §2 (Phase 4 — closes internal#286). + # + # Single stable required-status name that branch protection points at; + # CI churns underneath in `needs:` without any protection edits. Mirrors + # the molecule-controlplane Phase 2a impl shipped in CP PR#112 and + # referenced by `internal#286` ("Phase 4 is a single small PR... mirrors + # CP's existing one"). + # + # Closes the failure mode where status_check_contexts on molecule-core/main + # only listed `Secret scan` + `sop-tier-check` (the 2 meta-gates), so real + # `Platform (Go)` / `Canvas (Next.js)` / `Python Lint & Test` / `Shellcheck` + # red silently merged through. See internal#286 for the three concrete + # tonight-of-2026-05-11 incidents that prompted the emergency bump. + # + # Three properties of this job each close a failure mode: + # + # 1. `if: always()` — runs even when an upstream fails. Without it the + # sentinel is `skipped` and protection treats that as missing → merge + # ungated. + # + # 2. Assertion is `result == "success"` per dep, NOT `!= "failure"`. + # A `skipped` upstream (job gated by `if:` evaluating false, matrix + # entry that couldn't run) must NOT silently pass through. + # `skipped`-as-green is exactly the failure mode this gate closes. + # + # 3. `needs:` is the canonical list of "what counts as required." + # status_check_contexts will reference only `ci/all-required` (Step 5 + # follow-up — branch-protection PATCH is Owners-tier per + # `feedback_never_admin_merge_bypass`, separate PR); a new job is + # added simply by listing it in `needs:` here. + # `.gitea/workflows/ci-required-drift.yml` files a [ci-drift] issue + # hourly if this list diverges from status_check_contexts or from + # audit-force-merge.yml's REQUIRED_CHECKS env (RFC §4 + §6). + # + # Excluded from `needs:`: `canvas-deploy-reminder` — gated by + # `if: ... github.event_name == 'push' && github.ref == 'refs/heads/main'`, + # so on PR events it's legitimately `skipped`. The drift detector + # explicitly excludes `github.event_name`-gated jobs from F1 (see + # `.gitea/scripts/ci-required-drift.py::ci_job_names`). + # + # NOTE: `continue-on-error: true` is intentionally NOT set here — Phase 3 + # (parent PR for ci.yml port, RFC §1) sets it on the underlying build + # jobs to surface defects without blocking. The sentinel itself must + # hard-fail; that's the whole point. + runs-on: ubuntu-latest + timeout-minutes: 1 + needs: + - changes + - platform-build + - canvas-build + - shellcheck + - python-lint + if: always() + steps: + - name: Assert every required dependency succeeded + run: | + set -euo pipefail + # `needs.*.result` is one of: success | failure | cancelled | skipped + # We assert success per dep (not != failure) — see RFC §2 reasoning above. + results='${{ toJSON(needs) }}' + echo "$results" + echo "$results" | python3 -c ' + import json, sys + ns = json.load(sys.stdin) + bad = [(k, v.get("result")) for k, v in ns.items() if v.get("result") != "success"] + if bad: + print(f"FAIL: jobs not green:", file=sys.stderr) + for k, r in bad: + print(f" - {k}: {r}", file=sys.stderr) + sys.exit(1) + print(f"OK: all {len(ns)} required jobs succeeded") + '