Skip to content

ci: make required checks always report on path-scoped workflows - #404

Merged
mohabbis merged 2 commits into
masterfrom
ci/required-checks-always-report
Aug 4, 2026
Merged

ci: make required checks always report on path-scoped workflows#404
mohabbis merged 2 commits into
masterfrom
ci/required-checks-always-report

Conversation

@mohabbis

@mohabbis mohabbis commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Why

Every cloud-only PR is currently unmergeable. master requires fourteen Rust CI contexts; rust.yml carried paths-ignore: cloud/**, so on a cloud-only change the workflow never started, never created those check runs, and the PR sits at "Expected — Waiting for status" forever — mergeStateStatus: BLOCKED, every check that actually ran green, no way forward except an admin override. PR #403 is the live example.

What changed

A workflow skipped by a path filter creates no check runs. A job skipped by an if: condition does create one, concludes skipped, and branch protection counts that as satisfied.

So both workflows now always start, decide once in a changes job whether their tree was touched, and let every other job skip itself when it wasn't.

  • rust.ymlpaths-ignore removed from on:; all 8 jobs gained needs: changes + if: needs.changes.outputs.rust == 'true'. The ignore list moved verbatim into the detection step.
  • cloud.yml — same shape, mirrored.
  • changes reads the PR file list via gh api .../pulls/N/files rather than fetch-depth: 0 on every job.
  • Push events skip detection and run everything; only PRs are gated by branch protection.
  • Fail-open: an empty or unreadable file list runs CI. The failure mode is wasted minutes, not an ungated merge.

Follow-up (after this merges)

build (cloud) can become a required context for the first time — it now reports on Rust-only PRs as skipped instead of never appearing. Required-check list to be updated once this is on master.

Validation

Both files parse; all 9 + 2 jobs confirmed gated. Because this PR touches .github/workflows/rust.yml, changes resolves rust=true and the full Rust matrix runs for real here — this PR validates itself.

🤖 Generated with Claude Code

Every cloud-only PR was permanently unmergeable. Branch protection requires
fourteen Rust CI contexts; rust.yml carried `paths-ignore: cloud/**`, so on a
cloud-only change the workflow never started, never created those check runs,
and the PR sat at "Expected — Waiting for status" with nothing to click.
mergeStateStatus BLOCKED, every check that did run green, no way forward
except an admin override. PR #403 is the current example.

A workflow skipped by a path filter creates no check runs. A *job* skipped by
an `if:` condition does create one, concludes "skipped", and branch protection
counts that as satisfied. So both workflows now always start, decide once in a
`changes` job whether their tree was touched, and let every other job skip
itself when it wasn't.

`changes` reads the PR's file list from the API rather than cloning full
history to diff it — this repo is large enough that fetch-depth: 0 on every
job is a real cost. Push events skip the detection entirely and run
everything, since only pull requests are gated by branch protection. An empty
or unreadable file list falls through to running CI, so the failure mode is
wasted minutes rather than an ungated merge.

This also lets cloud's `build` become a required context for the first time:
it now reports on Rust-only PRs (as skipped) instead of never appearing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ghost Ready Ready Preview Aug 4, 2026 5:54pm

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

Two defects in the previous commit, both caught by its own PR run.

The cloud detection job inherited the workflow-level `working-directory:
cloud` but never checks out, so bash could not start: "No such file or
directory". rust.yml has no such default, which is why only one of the two
failed.

The worse one: `build` still reported "skipped" after that failure, and
branch protection accepts skipped. A broken detection step would therefore
have merged cloud changes with no CI at all — fail-open, the exact hazard
this whole change exists to remove. Both workflows now run the gated jobs
when detection itself fails. `!cancelled()` is required for a job to be
considered at all once a dependency has failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mohabbis
mohabbis merged commit 8dcafe6 into master Aug 4, 2026
27 checks passed
@mohabbis
mohabbis deleted the ci/required-checks-always-report branch August 4, 2026 18:04
mohabbis added a commit that referenced this pull request Aug 4, 2026
#405)

* ci: require one aggregate Rust context instead of fourteen matrix ones

PR #404 moved path scoping into an `if:` so required checks would always
report. That works for non-matrix jobs — Rustfmt, Version consistency and
Frontend contract tests all reported "skipped" on #403 as intended — and does
not work for the matrix ones.

A matrix job skipped by an `if:` condition never expands its matrix, so its
check run is created under the literal name "Check (${{ matrix.os }})" rather
than "Check (ubuntu-latest)". Requiring the expanded names therefore leaves
them waiting forever on a cloud-only PR: the same deadlock #404 set out to
fix, one level down, which is why #403 was still BLOCKED afterwards.

A non-matrix aggregator has a static name in every case. `rust-ci` needs the
seven previously-required jobs, runs with `always()` so it still reports when
they skipped, and fails if any of them failed or was cancelled.

Required contexts become "Rust CI" and "build" — two instead of fifteen, and
adding an OS to the matrix no longer means editing branch protection.
`experimental` is deliberately not among the dependencies: it was not a
required context before this change and this is not the commit that makes it
one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* ci: fix invalid expression in the Rust CI aggregator

GitHub expressions accept single-quoted string literals only. The aggregator
used join(needs.*.result, ",") with double quotes, which is a workflow-file
syntax error rather than a runtime one: the run fails to start, no jobs are
created, and the PR shows no Rust checks at all — not a failure that points at
the offending line.

Replaced with the contains(needs.*.result, 'failure') pattern, which needs no
string literal argument and is the more conventional spelling anyway.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant