Skip to content

ci: add a branch-protection fan-in gate per workflow - #1173

Merged
trunk-io[bot] merged 2 commits into
mainfrom
tyler/aggregate-gate
Aug 27, 2026
Merged

ci: add a branch-protection fan-in gate per workflow#1173
trunk-io[bot] merged 2 commits into
mainfrom
tyler/aggregate-gate

Conversation

@TylerJang27

Copy link
Copy Markdown
Collaborator

Prep for Dynamic CI (#1170 stacks on this), but a standalone fix for a problem the repo already has.

The problem

GitHub evaluates a job's if: before expanding its matrix. So a matrix job skipped at job level reports one check run under the unexpanded name:

Build CLI for ${{ matrix.platform.target }}     <- literally this

Branch protection on main requires 12 expanded per-leg contexts (Build CLI for x86_64-apple-darwin, macos (macos-14, aarch64, 16), …). Those never report, and the PR hangs on "Expected — Waiting for status to be reported" forever.

Non-matrix jobs are unaffected: they report skipped, which satisfies a required check.

There's a second, pre-existing problem with the current context list: it hard-codes runner labels and Xcode versions, so any matrix edit silently breaks branch protection. And the required context build is ambiguous — it matches the build job in both ruby.yml and wasm.yml.

The fix

Each PR workflow now ends in a gate job that always runs and passes when every job it needs finished success-or-skipped:

  gate:
    name: PR Gate
    runs-on: ubuntu-latest
    if: always()
    needs: [build_release, test, trunk_check_runner, build_pyo3, build_wasm]
Gate context Fans in
PR Gate build_release, test, trunk_check_runner, build_pyo3, build_wasm
context-py Gate linux, macos, sdist
rspec Gate build
context-js Gate build

Each gate's needs lists the jobs that are required checks today, so the required set is preserved rather than widened. linux-pytest, build-ruby-gem and test-ruby-gem-uploads are deliberately omitted for that reason — one-line additions if they should start blocking merge.

No behavior change on its own. The gate only aggregates results; nothing is skipped by this PR.

Ruleset edit (after this merges, before #1170)

Ruleset main (id 14925321): replace all 17 contexts with the 4 gate names. strict_required_status_checks_policy stays false; bypass_actors (2 exempt Integrations) and the deletion / non_fast_forward / pull_request rules are untouched.

Two notes on that edit:

  • PUT /rulesets/{id} replaces the entire ruleset, so omitting bypass_actors would silently strip the two exempt Integrations. A UI edit avoids the hazard.
  • Other open PRs won't have the gate jobs until they rebase onto main, so they'll show the 4 new contexts as "Expected" until they do.

One deliberate tightening

Branch protection currently requires only 4 of 5 matrix legs for build_release and test — the Windows legs are excluded. A fan-in can only aggregate at job granularity, so Build CLI for x86_64-pc-windows-gnu and Test for x86_64-pc-windows-gnu will start blocking merge. Accepted deliberately.

Rejected alternatives

  • Glob / wildcard required checks — not supported on any plan. Contexts are exact-match strings; a pattern just hangs in "Expected" (community #197566).
  • The workflows ruleset rule ("Require workflows to pass before merging") would need no YAML at all and is immune to renames — but it is GitHub Enterprise Cloud only and trunk-io is on Team. Attempting it returns 422 Invalid rule 'workflows' with an empty per-entry error.

Test plan

  • trunk check clean (actionlint, prettier, yamllint, checkov, shellcheck, shfmt).
  • All four gates have already been observed passing with every job they fan in skipped, on an earlier revision of ci: gate PR jobs with trunk-io/dynamic-ci #1170 — which is the case that matters, and the one the per-leg contexts fail.

GitHub evaluates a job's `if:` before expanding its matrix, so a matrix job
skipped at job level reports one check run under the unexpanded name --
`Build CLI for ${{ matrix.platform.target }}` rather than one context per
platform. Any per-leg context required by branch protection then never
reports and the PR hangs on "Expected -- Waiting for status to be reported".

Each PR workflow now ends in a `gate` job that always runs and passes when
every job it needs finished success-or-skipped. That gives branch protection
one stable context per workflow instead of 12 hand-typed matrix-leg names
that also break on any matrix edit (runner labels and Xcode versions are
currently baked into them).

Each gate's `needs` lists the jobs that are required checks today, so the
required set is preserved rather than widened. It also removes a latent
ambiguity: the required context `build` currently matches the `build` job in
both ruby.yml and wasm.yml.

No behavior change on its own -- the gate only aggregates results.
@trunk-io

trunk-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

😎 This pull request was merged.

The gate only reads `needs.*.result`, so anything beyond a few seconds means
it is wedged rather than working -- and a wedged required check blocks merges
until the default 6h job timeout expires.
@trunk-staging-io

trunk-staging-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

Failed Test Failure Summary Logs
pending_quarantine_test should be quarantined when run with variant A test marked as pending was expected to fail but unexpectedly passed. Logs ↗︎
variant_quarantine_test should be quarantined when run with variant A test expected the sum of 2 + 2 to be 5, but it was actually 4, indicating a failing assertion. Logs ↗︎

View Full Report ↗︎Docs

@trunk-io

trunk-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@codecov-commenter

codecov-commenter commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.31%. Comparing base (8c100a4) to head (33b531b).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1173      +/-   ##
==========================================
+ Coverage   83.07%   83.31%   +0.23%     
==========================================
  Files          72       72              
  Lines       16313    16313              
==========================================
+ Hits        13552    13591      +39     
+ Misses       2761     2722      -39     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@trunk-io

trunk-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

Stacked PR 1170 failed testing in the merge queue. Please investigate the failure and re-submit the stack.

@trunk-io
trunk-io Bot merged commit 9b1a81f into main Aug 27, 2026
31 checks passed
@trunk-io

trunk-io Bot commented Aug 27, 2026

Copy link
Copy Markdown

This pull request was merged into main as part of stacked PR 1170.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants