You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Highest priority. Master CI was red for six consecutive commits while every PR showed green, and a release was nearly cut on it.
Why PR-green cannot predict master-green
.github/workflows/test.yml:104 — the full Test Ruby & Rails matrix is deliberately kept off pull requests:
# Cost-intentional: full matrix stays off PRs by default (free-tier# Actions minutes). Runs on master pushes, manual dispatch, the weekly# scheduled drift check, and PRs opted in via the 'full-ci' label.if: > github.ref == 'refs/heads/master' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || contains(github.event.pull_request.labels.*.name, 'full-ci')
That trade-off is reasonable. The consequence is not obvious: the job that breaks master is a job that never ran on the PR, so PR checks are green by construction and every merge is a blind push.
What actually broke (tracked separately)
Subprocess probes chdir into a temp directory — correct, and the documented rule — while inheriting the workflow's relativeBUNDLE_GEMFILE: gemfiles/rails81_gems.rb (test.yml:30), which then fails to resolve:
/tmp/d20260824-2715-vtghif/gemfiles/rails81_gems.rb not found (Bundler::GemfileNotFound)
Invisible locally, because bundle exec normalises BUNDLE_GEMFILE to an absolute path before spawning. The documented rule is chdir out and scrub RUBYOPT/BUNDLE_GEMFILE — the chdir landed, the scrub did not. Fix in flight on fix/probe-env-under-ci.
The gatekeeper
Process rule recorded in the loop protocol: after every merge, check gh run list --branch master --limit 1. A red master blocks the next pull. cancelled is not a pass — it means a later push superseded the run.
Live monitor watching master's latest run, reporting every terminal conclusion (success, failure, cancelled) rather than only failures — silence must not look like success.
Label rule: any PR touching subprocess probes, env handling, gemfiles, or CI itself gets the full-ci label before merge, so the matrix runs where it can still block. Document this in CONTRIBUTING.md next to the label.
Decide whether full-ci should be automatic for paths that have historically broken master — test/**, gemfiles/**, .github/**. A paths-based label bot, or simply making the matrix run on PRs that touch those paths. Costs minutes; buys the guarantee that PR-green means something.
A CI configuration that runs different jobs on PRs than on master is a configuration where green means two different things depending on where you read it. That is defensible for cost, but it must be stated where people merge, not only in a comment inside the workflow.
Highest priority. Master CI was red for six consecutive commits while every PR showed green, and a release was nearly cut on it.
Why PR-green cannot predict master-green
.github/workflows/test.yml:104— the fullTest Ruby & Railsmatrix is deliberately kept off pull requests:That trade-off is reasonable. The consequence is not obvious: the job that breaks master is a job that never ran on the PR, so PR checks are green by construction and every merge is a blind push.
What actually broke (tracked separately)
Subprocess probes
chdirinto a temp directory — correct, and the documented rule — while inheriting the workflow's relativeBUNDLE_GEMFILE: gemfiles/rails81_gems.rb(test.yml:30), which then fails to resolve:Invisible locally, because
bundle execnormalisesBUNDLE_GEMFILEto an absolute path before spawning. The documented rule is chdir out and scrubRUBYOPT/BUNDLE_GEMFILE— the chdir landed, the scrub did not. Fix in flight onfix/probe-env-under-ci.The gatekeeper
gh run list --branch master --limit 1. A red master blocks the next pull.cancelledis not a pass — it means a later push superseded the run.full-cilabel before merge, so the matrix runs where it can still block. Document this inCONTRIBUTING.mdnext to the label.full-cishould be automatic for paths that have historically broken master —test/**,gemfiles/**,.github/**. Apaths-based label bot, or simply making the matrix run on PRs that touch those paths. Costs minutes; buys the guarantee that PR-green means something.The general lesson, for the record
A CI configuration that runs different jobs on PRs than on master is a configuration where green means two different things depending on where you read it. That is defensible for cost, but it must be stated where people merge, not only in a comment inside the workflow.