The required checks lint, build, test (HTTPX2), test (Python 3.10) and test (Python 3.14) all come from jobs that declare needs: dependency-locks, and dependency-locks is not itself a required check. Because GitHub treats a skipped required check as satisfied, a failure in dependency-locks skips all five and the branch rule is met with none of them having run.
From About protected branches:
Required status checks must have a successful, skipped, or neutral status before collaborators can make changes to a protected branch.
The state in .github/workflows/ci.yml on main today:
| job |
check name |
required |
needs |
dependency-locks |
dependency lock freshness |
no |
— |
lint |
lint |
yes |
dependency-locks |
build |
build |
yes |
dependency-locks |
test |
test (Python 3.10 / 3.14) |
yes |
dependency-locks |
test-httpx2 |
test (HTTPX2) |
yes |
dependency-locks |
None of the five carries an always() or !cancelled() guard, so the default skip-on-upstream-failure behaviour applies. dependency-locks failing is not hypothetical — it is the job that fails when pyproject.toml and uv.lock disagree, which is exactly the situation where you would most want lint and the test suite to run.
The narrowest fix is to make the dependency it gates on a gate itself, by adding dependency lock freshness to the required checks in the ruleset. Nothing in the workflow changes, and a lock failure then blocks on its own terms rather than by silently withdrawing four other checks.
The alternative, if you would rather not grow the required list, is the aggregate-gate shape you already have elsewhere in the ecosystem: one job with if: always() that inspects needs.*.result and exits non-zero, required in place of the individual checks.
Two caveats on scope. Those five jobs also carry if: github.event_name == 'push' || github.event_name == 'merge_group' || github.event.pull_request.head.repo.fork, so on a same-repo pull request they are skipped by design and the real run happens in the merge queue; the exposure I am describing is inside the queue, where a dependency-locks failure would skip the rest of the run and the queue would see satisfied checks. And I can only read your rulesets, not classic branch protection, so if additional enforcement exists that I cannot see, this may already be covered.
Found with greenwash, a tool I wrote for auditing this specific failure mode; greenwash audit --repo openai/openai-python reproduces it.
The required checks
lint,build,test (HTTPX2),test (Python 3.10)andtest (Python 3.14)all come from jobs that declareneeds: dependency-locks, anddependency-locksis not itself a required check. Because GitHub treats a skipped required check as satisfied, a failure independency-locksskips all five and the branch rule is met with none of them having run.From About protected branches:
The state in
.github/workflows/ci.ymlonmaintoday:needsdependency-lockslintdependency-locksbuilddependency-lockstestdependency-lockstest-httpx2dependency-locksNone of the five carries an
always()or!cancelled()guard, so the default skip-on-upstream-failure behaviour applies.dependency-locksfailing is not hypothetical — it is the job that fails whenpyproject.tomlanduv.lockdisagree, which is exactly the situation where you would most want lint and the test suite to run.The narrowest fix is to make the dependency it gates on a gate itself, by adding
dependency lock freshnessto the required checks in the ruleset. Nothing in the workflow changes, and a lock failure then blocks on its own terms rather than by silently withdrawing four other checks.The alternative, if you would rather not grow the required list, is the aggregate-gate shape you already have elsewhere in the ecosystem: one job with
if: always()that inspectsneeds.*.resultand exits non-zero, required in place of the individual checks.Two caveats on scope. Those five jobs also carry
if: github.event_name == 'push' || github.event_name == 'merge_group' || github.event.pull_request.head.repo.fork, so on a same-repo pull request they are skipped by design and the real run happens in the merge queue; the exposure I am describing is inside the queue, where adependency-locksfailure would skip the rest of the run and the queue would see satisfied checks. And I can only read your rulesets, not classic branch protection, so if additional enforcement exists that I cannot see, this may already be covered.Found with greenwash, a tool I wrote for auditing this specific failure mode;
greenwash audit --repo openai/openai-pythonreproduces it.