From 412d2f906490615f96a78fd7c13d4813c7a388af Mon Sep 17 00:00:00 2001 From: Ty J Everett Date: Fri, 31 Jul 2026 13:22:46 -0700 Subject: [PATCH] fix(ci): run push lanes past PR-only skips --- .github/workflows/ci.yml | 14 ++++++++++++-- scripts/ci-orchestration.test.mjs | 16 ++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e5114a4a..1e55876a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -188,6 +188,7 @@ jobs: needs: - early-gates - scope + if: always() && needs.early-gates.result == 'success' && needs.scope.result == 'success' runs-on: ubuntu-latest timeout-minutes: 30 permissions: @@ -1144,6 +1145,7 @@ jobs: needs: - early-gates - scope + if: always() && needs.early-gates.result == 'success' && needs.scope.result == 'success' runs-on: ubuntu-latest timeout-minutes: 5 permissions: {} @@ -1249,7 +1251,11 @@ jobs: timeout-minutes: 20 # Run on every PR (cheap and protects the docs site) and on pushes that touch docs # The build step inside will fail fast on frontmatter or link problems before they reach production - if: needs.scope.outputs.docs == 'true' + if: >- + always() && + needs.early-gates.result == 'success' && + needs.scope.result == 'success' && + needs.scope.outputs.docs == 'true' permissions: contents: read steps: @@ -1291,7 +1297,11 @@ jobs: needs: - early-gates - scope - if: needs.scope.outputs.conformance == 'true' + if: >- + always() && + needs.early-gates.result == 'success' && + needs.scope.result == 'success' && + needs.scope.outputs.conformance == 'true' runs-on: ubuntu-latest timeout-minutes: 20 permissions: diff --git a/scripts/ci-orchestration.test.mjs b/scripts/ci-orchestration.test.mjs index 5cf40e0dc..a60df4eb8 100644 --- a/scripts/ci-orchestration.test.mjs +++ b/scripts/ci-orchestration.test.mjs @@ -74,6 +74,22 @@ test('CI skips empty duplicate lanes without weakening the aggregate gate', () = assert.equal(workflow.match(/mongodb-memory-server binary cache warmed/g)?.length, 2) }) +test('CI push jobs survive intentionally skipped pull-request-only gates', () => { + const workflow = readFileSync(CI_PATH, 'utf8') + const jobs = Object.fromEntries(workflowJobBlocks(workflow).map(job => [job.name, job.source])) + const directGateCondition = + "always() && needs.early-gates.result == 'success' && needs.scope.result == 'success'" + + assert.ok(jobs.prepare.includes(` if: ${directGateCondition}\n`)) + assert.ok(jobs['infra-scope'].includes(` if: ${directGateCondition}\n`)) + for (const jobName of ['docs-validate', 'conformance']) { + assert.match(jobs[jobName], /^ if: >-$/m) + assert.match(jobs[jobName], /^ always\(\) &&$/m) + assert.match(jobs[jobName], /^ needs\.early-gates\.result == 'success' &&$/m) + assert.match(jobs[jobName], /^ needs\.scope\.result == 'success' &&$/m) + } +}) + test('CI bounds every job and allocates no runner for an empty infrastructure matrix', () => { const workflow = readFileSync(CI_PATH, 'utf8') const jobs = workflowJobBlocks(workflow)