From 3eef828173c935431a402e2a645c9b2ec0904af4 Mon Sep 17 00:00:00 2001 From: Molecule AI Core-DevOps Date: Thu, 14 May 2026 12:59:38 +0000 Subject: [PATCH] fix(ci): skip github.ref-gated jobs in ci_job_names (mc#958 mc#959) Adds `github.ref` as a skip condition in ci_job_names(), matching the existing github.event_name skip. Jobs gated on github.ref (e.g. canvas-deploy-reminder: only runs on pushes to refs/heads/main) never execute in a PR context, so flagging them as missing from all-required.needs: is a false positive that triggers mc#958/mc#959. Co-Authored-By: Claude Opus 4.7 --- .gitea/scripts/ci-required-drift.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.gitea/scripts/ci-required-drift.py b/.gitea/scripts/ci-required-drift.py index 9d4e60c8a..5bf56abce 100755 --- a/.gitea/scripts/ci-required-drift.py +++ b/.gitea/scripts/ci-required-drift.py @@ -13,8 +13,9 @@ Sources: Three failure classes: F1 Job in (A) is not under the sentinel's `needs:` โ€” sentinel doesn't gate it, so a red job on that name can sneak through. - Ignores jobs whose `if:` references `github.event_name` (those - run only on specific events and may be `skipped` legitimately). + Ignores jobs whose `if:` references `github.event_name` or + `github.ref` (those run only on specific events or refs and may + be `skipped` legitimately). F2 Context in (B) corresponds to no emitter โ€” i.e. there's no job in ci.yml whose runtime status-name maps to that context. A stale required-check name is silent: protection demands a @@ -203,12 +204,17 @@ def ci_jobs_all(ci_doc: dict) -> set[str]: def ci_job_names(ci_doc: dict) -> set[str]: """Set of job keys in ci.yml MINUS the sentinel itself MINUS jobs - whose `if:` gates on `github.event_name` (those are event-scoped - and can legitimately be `skipped` for a given trigger; if we - required them under the sentinel `needs:`, every PR-only job + whose `if:` gates on `github.event_name` or `github.ref` (those are + event-scoped and can legitimately be `skipped` for a given trigger; + if we required them under the sentinel `needs:`, every PR-only job would be `skipped` on push and the sentinel would interpret `skipped != success` as failure). RFC ยง4 spec. + `github.ref` is the companion gate for jobs that run only on direct + pushes to specific branches (e.g. `github.ref == 'refs/heads/main'`). + These never execute in a PR context, so flagging them as missing + from `all-required.needs:` is a false positive (mc#958 / mc#959). + Used for F1 (jobs missing from sentinel needs). NOT used for F1b (typos in needs) โ€” see `ci_jobs_all` for that.""" jobs = ci_doc.get("jobs") @@ -221,7 +227,9 @@ def ci_job_names(ci_doc: dict) -> set[str]: continue if isinstance(v, dict): gate = v.get("if") - if isinstance(gate, str) and "github.event_name" in gate: + if isinstance(gate, str) and ( + "github.event_name" in gate or "github.ref" in gate + ): continue names.add(k) return names -- 2.52.0