What broke
The required-checks ruleset on main rejects the catalog bot's hourly push:
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote: - 4 of 4 required status checks are expected.
! [remote rejected] HEAD -> main (push declined due to repository rule violations)github-actions[bot] holds no repository role, so the existing write/maintain/admin bypasses never applied to it. update-packages.yml has been failing since 15:33Z; check-desktop-updates.yml would fail its daily manifest push identically (its rebase-and-retry loop answers a race, not a ruleset — it would rebase five times and fail anyway).
Why not a bypass
Excusing the Actions app would exempt every workflow that ever pushes, not just this one, and would leave the generated catalog — generated.zig, src/packages/*, the action bundle — as the only thing reaching main that nobody checks. Routing both bots through a pull request closes that gap rather than widening it.
The trap this works around
GitHub suppresses events caused by GITHUB_TOKEN. That covers a pull request opened with it exactly as it covers a push, so pull_request never fires and nothing would ever report against the four required contexts — the PR would sit unmergeable forever. .github/actions/merge-via-pr therefore dispatches ci.yml at the head branch: a check run attaches to a commit, and that commit is the one the PR is gated on.
Behaviour
- Supersedes any older open PR from the same prefix before opening a new one, so a slow or red run cannot pile up a queue.
- Waits for
lint,typecheck,test,zig-testsonly — an unrelated red job such ascontinuous-releasedoes not block, matching the ruleset. - Counts
skipped/neutralas satisfied, the way the ruleset does. - On failed checks, timeout, or a refused merge it leaves the PR open so a red catalog is visible rather than silently retried.
update-packages.yml's registry dispatch now keys offsteps.land.outputs.merged, so publishing still happens only after the catalog is actually onmain.- Job timeout raised 30 → 80 minutes to cover the wait.
Verification
YAML parses for all three files; the action's script passes bash -n; the check-evaluation logic was exercised against canned check-runs payloads covering all green, one red, still-running, nothing-reported-yet, cancelled, and skipped-counts-as-pass. The end-to-end path can only be proven by the first scheduled run.