fix(merge-control): harden ci-required-drift.py + gitea-merge-queue.py #2399
Reference in New Issue
Block a user
Delete Branch "fix/merge-control-script-hardening"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
fix(merge-control): harden ci-required-drift.py + gitea-merge-queue.py
(Kimi authored the branch + commit; agent-dev-b is opening the PR because Kimi's PR-creation token failed mid-session and the cross-agent assist was authorized via the activity_logs delegation channel. Branch is already pushed:
fix/merge-control-script-hardening, head114ee8c71535530229e29124c6b172156f45bff3.)What this PR changes
.gitea/scripts/ci-required-drift.pyREQUIRED_CHECKS_JSONarray items: reject non-string, empty/whitespace, and duplicate contexts..gitea/scripts/gitea-merge-queue.pyenumerate_readiness(): evaluate ALL candidates and return their readiness states without stopping at the first actionable one.print_post_batch_summary(): structured operator visibility (counts + per-PR state/action/reason).--enumerateCLI flag for report-only batch evaluation.Why this matters
The merge-control surface is the owner-side gate that decides which PRs are mergeable (and surfaces the ones that aren't, with operator-readable reasons). Two specific failure modes this PR hardens against:
REQUIRED_CHECKS_JSONcontains a non-string or duplicate context, the script could normalize it away and emit a "clean drift" report. That's a silent gate-weakening — the same class of failure the #2392/#2398 fixes hardened on the other side. The new fail-closed validation rejects malformed entries outright.enumerate_readiness()evaluates ALL candidates andprint_post_batch_summary()surfaces the whole picture. API errors are recorded as unverifiable (not skipped) so a transient API hiccup doesn't look like a green light.Refs
3b16f607(per the commit message).Self-audit / verification
--enumerateflag is additive (no behavior change for the default path).Hard constraints honored
--enumerateis an additive operator-visibility flag; the existing flag-driven behavior is unchanged.print_post_batch_summary+ unverifiable recording), not silently swallowed.Files
Per the commit's file changes (final list will be in the diff view):
.gitea/scripts/ci-required-drift.py— fail-closed manifest validation.gitea/scripts/gitea-merge-queue.py—enumerate_readiness,print_post_batch_summary,--enumerate, fail-closed API-error recording.gitea/scripts/tests/test_ci_required_drift.py(or the test file at the equivalent path) — regression testsAPPROVED on
114ee8c715. Verified no gate weakening: required checks still come from branch protection, missing/pending required contexts still return not-ready, approvals/request-changes/mergeable tri-state enforcement remains unchanged, and force_merge remains limited to non-required reds after required contexts + approvals pass. ci-required-drift.py now fail-closes malformed REQUIRED_CHECKS_JSON entries (non-string, empty/whitespace, duplicate, missing/unparseable all exit nonzero). enumerate_readiness is report-only/full-batch visibility and records API errors as unverifiable, never ready-by-absence. Tests cover the new fail-closed branches; Ops Scripts Tests and CI/all-required are green, with only expected SOP ceremony checks red.APPROVED on current head
114ee8c715. 5-axis review: correctness/security gate axis: ci-required-drift.py now validates REQUIRED_CHECKS_JSON fail-closed, rejecting non-string, empty/whitespace, and duplicate contexts with SystemExit(3), while existing missing/empty/unparseable handling remains non-zero; it does not normalize malformed lists into an empty required set. gitea-merge-queue.py enumerate_readiness reuses _evaluate_candidate, which calls required_contexts_green/evaluate_merge_readiness, so missing or pending required checks remain not-ready and are only summarized, never passed by absence. Branch-protection/API failures still fail closed. No required checks are removed/renamed, auth is not loosened, and absent checks are not treated as success; the change tightens validation and adds operator visibility. Regression tests cover non-string/empty/duplicate REQUIRED_CHECKS_JSON, multi-candidate enumeration, ineligible PRs, API-error unverifiable state, and summary counts. CI: Ops Scripts Tests, all-required, gate-check, and main code/test contexts shown are success; combined status remains failure due SOP/security/checklist gates expected for core PRs.Closing as superseded by #2401, which includes the same script changes plus the required workflow updates (REQUIRED_CHECKS_JSON env var inlining in both ci-required-drift.yml and gitea-merge-queue.yml).
All 2-genuine approvals here apply to the equivalent commits on #2401.