perf(ci): parallelize and cache Windows compatibility checks (#9587)

* perf(ci): parallelize and cache Windows compatibility checks

* test(ci-plan): require both Windows jobs when bundle routing is selected
This commit is contained in:
luo jiyin
2026-09-19 15:23:52 +08:00
committed by GitHub
parent c71c35624b
commit ba6b74beea
4 changed files with 76 additions and 13 deletions
+2 -2
View File
@@ -9,8 +9,8 @@ export function gateFailures(needs, mode) {
const flags = ["rust", "agents", "fast", "agent_java", "agent_go_changed", "agent_rust_changed", "agent_integration_changed"];
if (!flags.every((flag) => typeof plan[flag] === "boolean")) return ["incomplete CI plan"];
const routedJobs = { frontend: "frontend", packages: "packages", "github-scripts": "github_scripts",
"windows-win7-bundle": "windows_win7_bundle", "duckdb-windows-driver": "duckdb_windows",
jdbc: "jdbc", "offline-jdbc-release": "offline_jdbc", "nix-packaging": "nix" };
"windows-standard-check": "windows_win7_bundle", "windows-win7-bundle": "windows_win7_bundle",
"duckdb-windows-driver": "duckdb_windows", jdbc: "jdbc", "offline-jdbc-release": "offline_jdbc", "nix-packaging": "nix" };
if (mode === "all" && !Object.values(routedJobs).every((output) => ["true", "false"].includes(needs.changes.outputs[output]))) {
return ["missing or invalid job selection outputs"];
}
+28 -4
View File
@@ -27,6 +27,11 @@ const metadata = {
};
const plan = (files, options = {}) => planCi({ files, metadata, root, ...options });
const groups = (result) => result.rust_matrix.include.map((entry) => entry.group);
// Keep the gate fixtures in sync with ci-gate.mjs routedJobs. Both Windows jobs
// share the windows_win7_bundle routing output.
const routedJobs = { frontend: "frontend", packages: "packages", "github-scripts": "github_scripts",
"windows-standard-check": "windows_win7_bundle", "windows-win7-bundle": "windows_win7_bundle",
"duckdb-windows-driver": "duckdb_windows", jdbc: "jdbc", "offline-jdbc-release": "offline_jdbc", "nix-packaging": "nix" };
test("foundation changes select transitive consumers and standalone DuckDB", () => {
const result = plan(["crates/dbx-types/src/lib.rs"]);
@@ -214,15 +219,15 @@ test("git diff routing includes both sides of renames, deleted files, and unusua
test("the final gate rejects absent routing outputs and skipped selected jobs", () => {
const needs = results(["docs/README.md"]);
const routed = { frontend: "frontend", packages: "packages", "github-scripts": "github_scripts",
"windows-win7-bundle": "windows_win7_bundle", "duckdb-windows-driver": "duckdb_windows", jdbc: "jdbc",
"offline-jdbc-release": "offline_jdbc", "nix-packaging": "nix" };
needs.rust = needs.agents = { result: "success" };
for (const [job, output] of Object.entries(routed)) {
for (const [job, output] of Object.entries(routedJobs)) {
needs[job] = { result: "skipped" };
needs.changes.outputs[output] = "false";
}
assert.deepEqual(gateFailures(needs, "all"), []);
needs["windows-standard-check"].result = "failure";
assert.ok(gateFailures(needs, "all").length);
needs["windows-standard-check"].result = "skipped";
needs.changes.outputs.frontend = "true";
assert.ok(gateFailures(needs, "all").length);
needs.frontend.result = "success";
@@ -231,6 +236,25 @@ test("the final gate rejects absent routing outputs and skipped selected jobs",
assert.ok(gateFailures(needs, "all").length);
});
test("the final gate requires both Windows jobs when the bundle routing is selected", () => {
const needs = results(["docs/README.md"]);
needs.rust = needs.agents = { result: "success" };
for (const [job, output] of Object.entries(routedJobs)) {
needs[job] = { result: "skipped" };
needs.changes.outputs[output] = "false";
}
needs.changes.outputs.windows_win7_bundle = "true";
needs["windows-standard-check"].result = "success";
needs["windows-win7-bundle"].result = "success";
assert.deepEqual(gateFailures(needs, "all"), []);
needs["windows-standard-check"].result = "skipped";
assert.ok(gateFailures(needs, "all").length);
needs["windows-standard-check"].result = "success";
needs["windows-win7-bundle"].result = "skipped";
assert.ok(gateFailures(needs, "all").length);
});
test("coverage audit rejects lost features, omitted packages, and overlapping group selection", () => {
const coverage = { workspace: Object.fromEntries(Object.keys(graph).map((name) => [name, ["fixture"]])),
...Object.fromEntries(Object.entries(rustGroups).map(([group, packages]) => [group, Object.fromEntries(packages.map((name) => [name, ["fixture"]]))])) };
+16 -1
View File
@@ -37,7 +37,7 @@ test("stable Rust, Agent and overall gates always inspect selected upstream resu
for (const [name, mode, dependencies] of [["rust", "rust", ["fast-checks", "rust-fmt-clippy", "rust-test"]],
["agents", "agents", ["fast-checks", "agent-checks", "agent-rust", "agent-go", "agent-integration", "agent-java"]],
["frontend", "frontend", ["frontend-checks", "frontend-typecheck", "frontend-test"]],
["ci", "all", ["rust", "agents", "frontend", "packages", "windows-win7-bundle", "duckdb-windows-driver", "nix-packaging"]]]) {
["ci", "all", ["rust", "agents", "frontend", "packages", "windows-standard-check", "windows-win7-bundle", "duckdb-windows-driver", "nix-packaging"]]]) {
const content = job(name);
assert.match(content, /if: always\(\)/);
assert.ok(content.includes(`node .github/scripts/ci-gate.mjs ${mode}`));
@@ -88,6 +88,21 @@ test("DuckDB Windows builds persist Rust and C++ compiler results", () => {
assert.ok(content.includes('version: "v0.16.0"'));
});
test("standard Windows compatibility checks run separately with sccache", () => {
const standard = job("windows-standard-check");
assert.ok(standard.includes("needs.changes.outputs.windows_win7_bundle == 'true'"));
assert.ok(standard.includes("RUSTC_WRAPPER: sccache"));
assert.ok(standard.includes('SCCACHE_GHA_ENABLED: "true"'));
assert.ok(standard.includes("SCCACHE_GHA_VERSION: windows-standard-v1"));
assert.ok(standard.includes("fc920bf0ec8de6ee65d409111f7ec508035751ba"));
assert.ok(standard.includes('version: "v0.16.0"'));
assert.ok(standard.includes("cargo check --locked --package dbx --no-default-features --target x86_64-pc-windows-msvc"));
assert.ok(standard.includes("sccache --show-stats"));
const win7 = job("windows-win7-bundle");
assert.doesNotMatch(win7, /x86_64-pc-windows-msvc|Setup Rust for standard Windows|RUSTC_WRAPPER: sccache/);
});
test("the planner uses the exact event base and preserves a single workflow cancellation scope", () => {
const changes = job("changes");
assert.ok(changes.includes("github.event.pull_request.base.sha || github.event.before"));
+30 -6
View File
@@ -269,6 +269,35 @@ jobs:
continue-on-error: true
run: ${SCCACHE_PATH} --show-stats
windows-standard-check:
needs: changes
if: needs.changes.outputs.windows_win7_bundle == 'true'
runs-on: windows-2022
timeout-minutes: 45
env:
CARGO_INCREMENTAL: "0"
RUSTFLAGS: -C debuginfo=line-tables-only -C target-feature=+crt-static
RUSTC_WRAPPER: sccache
SCCACHE_GHA_ENABLED: "true"
SCCACHE_GHA_VERSION: windows-standard-v1
steps:
- uses: actions/checkout@v5
- name: Setup Rust for standard Windows
uses: dtolnay/rust-toolchain@1.97.1
- uses: mozilla-actions/sccache-action@fc920bf0ec8de6ee65d409111f7ec508035751ba # v0.0.11
with:
version: "v0.16.0"
- name: Check standard Windows dependency path
run: cargo check --locked --package dbx --no-default-features --target x86_64-pc-windows-msvc
- name: Show sccache stats
if: always()
continue-on-error: true
run: sccache --show-stats
windows-win7-bundle:
needs: changes
if: needs.changes.outputs.windows_win7_bundle == 'true'
@@ -294,12 +323,6 @@ jobs:
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile
- name: Setup Rust for standard Windows
uses: dtolnay/rust-toolchain@1.97.1
- name: Check standard Windows dependency path
run: cargo check --locked --package dbx --no-default-features --target x86_64-pc-windows-msvc
- name: Setup Rust for Windows 7
uses: dtolnay/rust-toolchain@nightly
with:
@@ -1116,6 +1139,7 @@ jobs:
- frontend
- github-scripts
- packages
- windows-standard-check
- windows-win7-bundle
- duckdb-windows-driver
- jdbc