From 972519ba2d93db14985714a0ede7fedb5be0dd06 Mon Sep 17 00:00:00 2001 From: t8y2 Date: Sun, 11 Oct 2026 08:54:55 +0800 Subject: [PATCH] chore(ci): run full validation jobs on draft pull requests --- .github/scripts/ci-gate.mjs | 17 +++++------- .github/scripts/ci-plan.test.mjs | 24 ----------------- .github/workflows/ci.yml | 45 +++++++++----------------------- 3 files changed, 19 insertions(+), 67 deletions(-) diff --git a/.github/scripts/ci-gate.mjs b/.github/scripts/ci-gate.mjs index ab61f1011a..e20f083383 100644 --- a/.github/scripts/ci-gate.mjs +++ b/.github/scripts/ci-gate.mjs @@ -11,11 +11,6 @@ export function gateFailures(needs, mode) { const routedJobs = { frontend: "frontend", packages: "packages", "github-scripts": "github_scripts", "windows-standard-check": "windows_standard", "windows-win7-bundle": "windows_win7_bundle", "duckdb-windows-driver": "duckdb_windows", jdbc: "jdbc", "offline-jdbc-release": "offline_jdbc", "nix-packaging": "nix" }; - // Draft PRs intentionally skip the heavy validation jobs; the gate may only - // demand them once ready_for_review re-triggers the workflow without draft. - const draft = needs.changes.outputs.draft === "true"; - const draftSkippable = new Set(["rust-test", "frontend-test", "agent-java", "agent-go", "agent-rust", "agent-integration", - "packages", "windows-standard-check", "windows-win7-bundle", "duckdb-windows-driver", "jdbc", "offline-jdbc-release", "nix-packaging"]); if (mode === "all" && !Object.values(routedJobs).every((output) => ["true", "false"].includes(needs.changes.outputs[output]))) { return ["missing or invalid job selection outputs"]; } @@ -23,18 +18,18 @@ export function gateFailures(needs, mode) { return ["missing or invalid frontend selection output"]; } const expected = mode === "rust" ? { - "fast-checks": plan.fast, "rust-fmt-clippy": plan.rust, "rust-test": plan.rust && !draft, + "fast-checks": plan.fast, "rust-fmt-clippy": plan.rust, "rust-test": plan.rust, } : mode === "agents" ? { - "fast-checks": plan.fast, "agent-checks": plan.agents, "agent-java": plan.agent_java && !draft, "agent-go": plan.agent_go_changed && !draft, - "agent-rust": plan.agent_rust_changed && !draft, "agent-integration": plan.agent_integration_changed && !draft, + "fast-checks": plan.fast, "agent-checks": plan.agents, "agent-java": plan.agent_java, "agent-go": plan.agent_go_changed, + "agent-rust": plan.agent_rust_changed, "agent-integration": plan.agent_integration_changed, } : mode === "frontend" ? { "frontend-checks": needs.changes.outputs.frontend === "true", "frontend-typecheck": needs.changes.outputs.frontend === "true", - "frontend-test": needs.changes.outputs.frontend === "true" && !draft, + "frontend-test": needs.changes.outputs.frontend === "true", } : mode === "all" ? { rust: true, agents: true, "fast-checks": plan.fast, ...Object.fromEntries(Object.entries(routedJobs) - .map(([job, output]) => [job, needs.changes.outputs[output] === "true" && !(draft && draftSkippable.has(job))])), + .map(([job, output]) => [job, needs.changes.outputs[output] === "true"])), } : null; if (!expected) return [`unknown gate: ${mode}`]; return Object.entries(expected).flatMap(([job, required]) => { @@ -48,5 +43,5 @@ if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.ar if (failures.length) { console.error(failures.join("\n")); process.exitCode = 1; - } else console.log("All selected CI jobs succeeded; only unselected or draft-skipped jobs may be skipped."); + } else console.log("All selected CI jobs succeeded; only unselected jobs may be skipped."); } diff --git a/.github/scripts/ci-plan.test.mjs b/.github/scripts/ci-plan.test.mjs index 8f967726df..1c6fc37404 100644 --- a/.github/scripts/ci-plan.test.mjs +++ b/.github/scripts/ci-plan.test.mjs @@ -406,30 +406,6 @@ test("the frontend gate checks every selected frontend job", () => { assert.deepEqual(gateFailures(needs, "frontend"), []); }); -test("draft runs may skip heavy validation jobs without failing gates", () => { - const needs = results(["Cargo.lock"]); - needs.changes.outputs.draft = "true"; - for (const job of ["rust-test", "agent-java", "agent-go", "agent-rust", "agent-integration"]) { - needs[job] = { result: "skipped" }; - } - assert.deepEqual(gateFailures(needs, "rust"), []); - assert.deepEqual(gateFailures(needs, "agents"), []); - needs.changes.outputs.frontend = "true"; - needs["frontend-checks"] = { result: "success" }; - needs["frontend-typecheck"] = { result: "success" }; - needs["frontend-test"] = { result: "skipped" }; - assert.deepEqual(gateFailures(needs, "frontend"), []); - // Draft only relaxes the skippable set: a real failure is still a failure, - // and jobs the draft policy keeps (clippy, fast-checks) stay required. - needs["frontend-test"].result = "failure"; - assert.ok(gateFailures(needs, "frontend").length); - needs["rust-fmt-clippy"].result = "skipped"; - assert.ok(gateFailures(needs, "rust").length); - // Without the draft output the heavy jobs are required again. - delete needs.changes.outputs.draft; - assert.ok(gateFailures(needs, "rust").length); -}); - test("git diff routing includes both sides of renames, deleted files, and unusual filenames", () => { const directory = mkdtempSync(path.join(tmpdir(), "dbx-ci-plan-")); const git = (...args) => execFileSync("git", args, { cwd: directory, encoding: "utf8", stdio: "pipe" }).trim(); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97f5c40ecd..1e18bb51bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,6 @@ on: branches: [ main ] pull_request: branches: [ main ] - # ready_for_review is required: heavy jobs are skipped while a PR is a - # draft, so flipping to ready must re-trigger the full CI. - types: [opened, synchronize, reopened, ready_for_review] concurrency: group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.event.pull_request.user.login != github.repository_owner && format('pr-author-{0}', github.event.pull_request.user.id) || github.ref }} @@ -96,8 +93,7 @@ jobs: frontend-test: needs: changes - if: needs.changes.outputs.frontend == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.frontend == 'true' runs-on: ubuntu-24.04 env: NPM_CONFIG_LOGLEVEL: error strategy: @@ -181,8 +177,7 @@ jobs: packages: needs: changes - if: needs.changes.outputs.packages == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.packages == 'true' runs-on: ubuntu-24.04 env: # Unsupported-platform package warnings are expected while validating cross-platform package metadata. NPM_CONFIG_LOGLEVEL: error @@ -304,8 +299,7 @@ jobs: windows-standard-check: needs: changes - if: needs.changes.outputs.windows_standard == 'true' && needs.changes.outputs.draft != 'true' - runs-on: windows-2022 + if: needs.changes.outputs.windows_standard == 'true' runs-on: windows-2022 timeout-minutes: 45 env: CARGO_INCREMENTAL: "0" @@ -333,8 +327,7 @@ jobs: windows-win7-bundle: needs: changes - if: needs.changes.outputs.windows_win7_bundle == 'true' && needs.changes.outputs.draft != 'true' - runs-on: windows-2022 + if: needs.changes.outputs.windows_win7_bundle == 'true' runs-on: windows-2022 timeout-minutes: 120 env: CARGO_INCREMENTAL: "0" @@ -723,8 +716,7 @@ jobs: duckdb-windows-driver: needs: changes - if: needs.changes.outputs.duckdb_windows == 'true' && needs.changes.outputs.draft != 'true' - runs-on: windows-2022 + if: needs.changes.outputs.duckdb_windows == 'true' runs-on: windows-2022 timeout-minutes: 60 env: CARGO_INCREMENTAL: "0" @@ -872,8 +864,7 @@ jobs: needs: - changes - fast-checks - if: needs.changes.outputs.rust == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.rust == 'true' runs-on: ubuntu-24.04 env: # sccache cannot reuse Cargo incremental artifacts, so avoid generating them in CI. CARGO_INCREMENTAL: "0" @@ -1021,8 +1012,7 @@ jobs: jdbc: needs: changes - if: needs.changes.outputs.jdbc == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.jdbc == 'true' runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 with: @@ -1049,8 +1039,7 @@ jobs: offline-jdbc-release: needs: changes - if: needs.changes.outputs.offline_jdbc == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.offline_jdbc == 'true' runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v7 @@ -1089,8 +1078,7 @@ jobs: nix-packaging: needs: changes - if: needs.changes.outputs.nix == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.nix == 'true' runs-on: ubuntu-24.04 continue-on-error: true steps: - uses: actions/checkout@v7 @@ -1130,9 +1118,6 @@ jobs: agent_rust_changed: ${{ steps.plan.outputs.agent_rust_changed }} agent_integration_changed: ${{ steps.plan.outputs.agent_integration_changed }} plan: ${{ steps.plan.outputs.plan }} - # True only for pull_request events on draft PRs; heavy jobs skip and - # ci-gate.mjs must not demand them until ready_for_review re-triggers. - draft: ${{ github.event_name == 'pull_request' && github.event.pull_request.draft == true }} steps: - uses: actions/checkout@v7 with: @@ -1346,8 +1331,7 @@ jobs: run: python3 scripts/validate_agents.py agent-java: needs: [changes, fast-checks, agent-checks] - if: needs.changes.outputs.agent_java == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.agent_java == 'true' runs-on: ubuntu-24.04 defaults: run: working-directory: agents @@ -1374,8 +1358,7 @@ jobs: run: python3 scripts/validate_agent_jars.py agent-rust: needs: [changes, fast-checks, agent-checks] - if: needs.changes.outputs.agent_rust_changed == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.agent_rust_changed == 'true' runs-on: ubuntu-24.04 env: # sccache cannot reuse Cargo incremental artifacts, so avoid generating them in CI. CARGO_INCREMENTAL: "0" @@ -1486,8 +1469,7 @@ jobs: matrix: ${{ fromJSON(needs.changes.outputs.agent_rust) }} agent-go: needs: [changes, fast-checks, agent-checks] - if: needs.changes.outputs.agent_go_changed == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.agent_go_changed == 'true' runs-on: ubuntu-24.04 defaults: run: working-directory: agents @@ -1510,8 +1492,7 @@ jobs: matrix: ${{ fromJSON(needs.changes.outputs.agent_go) }} agent-integration: needs: [changes, fast-checks, agent-checks] - if: needs.changes.outputs.agent_integration_changed == 'true' && needs.changes.outputs.draft != 'true' - runs-on: ubuntu-24.04 + if: needs.changes.outputs.agent_integration_changed == 'true' runs-on: ubuntu-24.04 defaults: run: working-directory: agents