From 6cea84968b7ad6acd1da535841a808e274a2ec6b Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Wed, 1 Apr 2026 18:45:24 +0800 Subject: [PATCH 1/9] ci: add Windows to test matrix --- .github/workflows/ci.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a347f9da..d0fed852f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,10 +23,12 @@ jobs: - run: pnpm check test: - runs-on: blacksmith-4vcpu-ubuntu-2404 + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: [blacksmith-4vcpu-ubuntu-2404, windows-latest] + suite: [unit, core-markdown, metaframeworks, pages-react-vue, pages-svelte-solid] include: - suite: unit script: test:unit @@ -52,6 +54,9 @@ jobs: - run: pnpm build - run: pnpm exec playwright install --with-deps chromium - if: matrix.suite == 'core-markdown' || matrix.suite == 'metaframeworks' || startsWith(matrix.suite, 'pages-') + if: matrix.suite != 'unit' && !contains(matrix.os, 'windows') + + - run: pnpm exec playwright install chromium + if: matrix.suite != 'unit' && contains(matrix.os, 'windows') - run: pnpm ${{ matrix.script }}${{ matrix.retry && format(' --retry {0}', matrix.retry) || '' }} From ede45d4e9d106807d242b85923a62fce68c1255c Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 15:26:30 +0800 Subject: [PATCH 2/9] fix(test): use cross-spawn for Windows .cmd resolution --- package.json | 2 ++ packages/md/test/integration/markdown-blog.test.ts | 3 ++- .../test/integration/react-pages-client.test.ts | 3 ++- .../test/integration/solid-pages-playground.test.ts | 3 ++- .../test/integration/svelte-pages-client.test.ts | 3 ++- packages/void/test/integration/astro.test.ts | 3 ++- packages/void/test/integration/kitchen-sink.test.ts | 3 ++- .../void/test/integration/named-layouts.test.ts | 2 +- packages/void/test/integration/node-target.test.ts | 3 ++- packages/void/test/integration/nuxt.test.ts | 3 ++- packages/void/test/integration/pg-test.test.ts | 2 +- packages/void/test/integration/react-router.test.ts | 3 ++- .../void/test/integration/ssr-playground.test.ts | 3 ++- packages/void/test/integration/sveltekit.test.ts | 3 ++- .../void/test/integration/tanstack-start.test.ts | 3 ++- packages/void/test/integration/vinext-app.test.ts | 3 ++- packages/void/test/integration/vinext-pages.test.ts | 3 ++- .../test/integration/websockets-playground.test.ts | 2 +- .../vue/test/integration/vue-pages-client.test.ts | 3 ++- pnpm-lock.yaml | 13 +++++++++++++ 20 files changed, 48 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index d2e62c12e..6f093b41d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ "test": "vitest --run" }, "devDependencies": { + "@types/cross-spawn": "^6.0.6", "@typescript/native-preview": "catalog:", + "cross-spawn": "^7.0.6", "husky": "^9.1.7", "lint-staged": "^16.4.0", "oxfmt": "^0.42.0", diff --git a/packages/md/test/integration/markdown-blog.test.ts b/packages/md/test/integration/markdown-blog.test.ts index 5e26a2f54..e34300363 100644 --- a/packages/md/test/integration/markdown-blog.test.ts +++ b/packages/md/test/integration/markdown-blog.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { chromium, type Browser, type Page } from "playwright"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/react/test/integration/react-pages-client.test.ts b/packages/react/test/integration/react-pages-client.test.ts index f72261523..820a6f3ea 100644 --- a/packages/react/test/integration/react-pages-client.test.ts +++ b/packages/react/test/integration/react-pages-client.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; import { chromium, type Browser, type Page } from "playwright"; diff --git a/packages/solid/test/integration/solid-pages-playground.test.ts b/packages/solid/test/integration/solid-pages-playground.test.ts index 5f5ebb150..df2177541 100644 --- a/packages/solid/test/integration/solid-pages-playground.test.ts +++ b/packages/solid/test/integration/solid-pages-playground.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; import { chromium, type Browser, type Page } from "playwright"; diff --git a/packages/svelte/test/integration/svelte-pages-client.test.ts b/packages/svelte/test/integration/svelte-pages-client.test.ts index a207401ba..e128c9807 100644 --- a/packages/svelte/test/integration/svelte-pages-client.test.ts +++ b/packages/svelte/test/integration/svelte-pages-client.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; import { chromium, type Browser, type Page } from "playwright"; diff --git a/packages/void/test/integration/astro.test.ts b/packages/void/test/integration/astro.test.ts index 1989ea024..4fb4858d7 100644 --- a/packages/void/test/integration/astro.test.ts +++ b/packages/void/test/integration/astro.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/kitchen-sink.test.ts b/packages/void/test/integration/kitchen-sink.test.ts index 2b9619fb4..351095e31 100644 --- a/packages/void/test/integration/kitchen-sink.test.ts +++ b/packages/void/test/integration/kitchen-sink.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { rmSync } from "node:fs"; import { chromium, type Browser, type Page } from "playwright"; diff --git a/packages/void/test/integration/named-layouts.test.ts b/packages/void/test/integration/named-layouts.test.ts index a7ab1c76e..b9a802402 100644 --- a/packages/void/test/integration/named-layouts.test.ts +++ b/packages/void/test/integration/named-layouts.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { spawn } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/node-target.test.ts b/packages/void/test/integration/node-target.test.ts index fec409d8e..1e9d4df7d 100644 --- a/packages/void/test/integration/node-target.test.ts +++ b/packages/void/test/integration/node-target.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/nuxt.test.ts b/packages/void/test/integration/nuxt.test.ts index 408aa127b..409aa7b72 100644 --- a/packages/void/test/integration/nuxt.test.ts +++ b/packages/void/test/integration/nuxt.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/pg-test.test.ts b/packages/void/test/integration/pg-test.test.ts index 1f8c571a3..a9999ced4 100644 --- a/packages/void/test/integration/pg-test.test.ts +++ b/packages/void/test/integration/pg-test.test.ts @@ -1,6 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; import { readFileSync, writeFileSync, unlinkSync } from "node:fs"; -import { spawn } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { once } from "node:events"; import { PGlite } from "@electric-sql/pglite"; diff --git a/packages/void/test/integration/react-router.test.ts b/packages/void/test/integration/react-router.test.ts index 41cf9561d..0b0b22384 100644 --- a/packages/void/test/integration/react-router.test.ts +++ b/packages/void/test/integration/react-router.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/ssr-playground.test.ts b/packages/void/test/integration/ssr-playground.test.ts index e0355d3e2..23570e219 100644 --- a/packages/void/test/integration/ssr-playground.test.ts +++ b/packages/void/test/integration/ssr-playground.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/sveltekit.test.ts b/packages/void/test/integration/sveltekit.test.ts index 14276e368..f77840987 100644 --- a/packages/void/test/integration/sveltekit.test.ts +++ b/packages/void/test/integration/sveltekit.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/tanstack-start.test.ts b/packages/void/test/integration/tanstack-start.test.ts index c3df6298e..db17784df 100644 --- a/packages/void/test/integration/tanstack-start.test.ts +++ b/packages/void/test/integration/tanstack-start.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/vinext-app.test.ts b/packages/void/test/integration/vinext-app.test.ts index 57c6e317a..e59d3c2aa 100644 --- a/packages/void/test/integration/vinext-app.test.ts +++ b/packages/void/test/integration/vinext-app.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/vinext-pages.test.ts b/packages/void/test/integration/vinext-pages.test.ts index a63fe7bc1..e05ca8f40 100644 --- a/packages/void/test/integration/vinext-pages.test.ts +++ b/packages/void/test/integration/vinext-pages.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; diff --git a/packages/void/test/integration/websockets-playground.test.ts b/packages/void/test/integration/websockets-playground.test.ts index 0c0007864..d3bc5cc30 100644 --- a/packages/void/test/integration/websockets-playground.test.ts +++ b/packages/void/test/integration/websockets-playground.test.ts @@ -1,5 +1,5 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { spawn } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { chromium, type Browser, type Page } from "playwright"; import { getPort, killChild, waitForServer } from "../../../../test/integration-helpers"; diff --git a/packages/vue/test/integration/vue-pages-client.test.ts b/packages/vue/test/integration/vue-pages-client.test.ts index d0c30a7e7..bffdd1d94 100644 --- a/packages/vue/test/integration/vue-pages-client.test.ts +++ b/packages/vue/test/integration/vue-pages-client.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it, beforeAll, afterAll } from "vitest"; -import { execSync, spawn } from "node:child_process"; +import { execSync } from "node:child_process"; +import spawn from "cross-spawn"; import { join } from "node:path"; import { readFileSync, writeFileSync } from "node:fs"; import { chromium, type Browser, type Page } from "playwright"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b2617e90..9b83c10e5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,9 +33,15 @@ importers: .: devDependencies: + '@types/cross-spawn': + specifier: ^6.0.6 + version: 6.0.6 '@typescript/native-preview': specifier: 'catalog:' version: 7.0.0-dev.20260325.1 + cross-spawn: + specifier: ^7.0.6 + version: 7.0.6 husky: specifier: ^9.1.7 version: 9.1.7 @@ -3673,6 +3679,9 @@ packages: '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/cross-spawn@6.0.6': + resolution: {integrity: sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==} + '@types/debug@4.1.13': resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} @@ -10689,6 +10698,10 @@ snapshots: '@types/cookie@0.6.0': {} + '@types/cross-spawn@6.0.6': + dependencies: + '@types/node': 25.5.0 + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 From bd7b47705895f3eb5fecc78da7c135b680de00ce Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:11:31 +0800 Subject: [PATCH 3/9] fix(test): use taskkill to kill process tree on Windows --- test/integration-helpers.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/integration-helpers.ts b/test/integration-helpers.ts index 725f33ac9..916c39eb0 100644 --- a/test/integration-helpers.ts +++ b/test/integration-helpers.ts @@ -1,6 +1,6 @@ import { createServer, type Server } from "node:net"; import { once } from "node:events"; -import type { spawn } from "node:child_process"; +import { execSync, type spawn } from "node:child_process"; /** * Ports held by getPort() until waitForServer() releases them. @@ -63,7 +63,18 @@ export async function waitForServer( export async function killChild(child: ReturnType): Promise { if (child.exitCode === null && child.signalCode === null) { - child.kill("SIGTERM"); + if (process.platform === "win32" && child.pid) { + // On Windows, SIGTERM doesn't propagate to child processes. + // Use taskkill /T to kill the entire process tree (e.g. workerd.exe). + // See: https://github.com/voidzero-dev/void/actions/runs/23939152784/job/69826006981?pr=63 + try { + execSync(`taskkill /pid ${child.pid} /T /F`, { stdio: "ignore" }); + } catch { + // Process may have already exited + } + } else { + child.kill("SIGTERM"); + } await Promise.race([once(child, "exit"), new Promise((resolve) => setTimeout(resolve, 5_000))]); if (child.exitCode === null && child.signalCode === null) { child.kill("SIGKILL"); From e6889b3fb8a5cabd4e56f3252d6982ab50e48588 Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:20:48 +0800 Subject: [PATCH 4/9] fix(test): use import.meta.dirname for root path on Windows --- packages/void/test/integration/node-target.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/void/test/integration/node-target.test.ts b/packages/void/test/integration/node-target.test.ts index 1e9d4df7d..d7645fd3b 100644 --- a/packages/void/test/integration/node-target.test.ts +++ b/packages/void/test/integration/node-target.test.ts @@ -5,7 +5,7 @@ import { existsSync, readFileSync, rmSync } from "node:fs"; import { join } from "node:path"; import { getPort, waitForServer, killChild } from "../../../../test/integration-helpers"; -const ROOT = new URL("../../../..", import.meta.url).pathname; +const ROOT = join(import.meta.dirname, "..", "..", "..", ".."); let DEV_PORT: number; let DEV_BASE: string; let PROD_PORT: number; From dc31379d1761176e873ad8b310fc6803afad93b1 Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:21:35 +0800 Subject: [PATCH 5/9] fix(test): normalize collected file paths in kitchen-sink-build test for Windows --- packages/void/test/integration/kitchen-sink-build.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/void/test/integration/kitchen-sink-build.test.ts b/packages/void/test/integration/kitchen-sink-build.test.ts index 00a15db39..bc1b9cf06 100644 --- a/packages/void/test/integration/kitchen-sink-build.test.ts +++ b/packages/void/test/integration/kitchen-sink-build.test.ts @@ -2,6 +2,7 @@ import { beforeAll, describe, expect, it } from "vitest"; import { spawnSync } from "node:child_process"; import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs"; import { join } from "node:path"; +import { toSlash } from "../../src/shared/utils"; const ROOT = join(import.meta.dirname, "..", "..", "..", ".."); const PLAYGROUND = "playground/kitchen-sink"; @@ -51,7 +52,7 @@ describe("playground/kitchen-sink build", () => { function collectFiles(dir: string): string[] { const files: string[] = []; for (const entry of readdirSync(dir, { withFileTypes: true })) { - const entryPath = join(dir, entry.name); + const entryPath = toSlash(join(dir, entry.name)); if (entry.isDirectory()) { files.push(...collectFiles(entryPath)); } else { From 3ffaff7a89c59e8c4f33e6d5d594cb31f6298f80 Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:29:12 +0800 Subject: [PATCH 6/9] fix(test): use cross-spawn for kitchen-sink-build to resolve pnpm on Windows --- packages/void/test/integration/kitchen-sink-build.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/void/test/integration/kitchen-sink-build.test.ts b/packages/void/test/integration/kitchen-sink-build.test.ts index bc1b9cf06..60e6d6821 100644 --- a/packages/void/test/integration/kitchen-sink-build.test.ts +++ b/packages/void/test/integration/kitchen-sink-build.test.ts @@ -1,5 +1,5 @@ import { beforeAll, describe, expect, it } from "vitest"; -import { spawnSync } from "node:child_process"; +import spawn from "cross-spawn"; import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs"; import { join } from "node:path"; import { toSlash } from "../../src/shared/utils"; @@ -16,7 +16,7 @@ describe("playground/kitchen-sink build", () => { rmSync(join(pg, "dist"), { recursive: true, force: true }); rmSync(join(pg, ".void"), { recursive: true, force: true }); - const result = spawnSync("pnpm", ["--dir", PLAYGROUND, "build"], { + const result = spawn.sync("pnpm", ["--dir", PLAYGROUND, "build"], { cwd: ROOT, encoding: "utf8", maxBuffer: 10 * 1024 * 1024, From 90db415f592ed83d099e6e5127825861f35aa37e Mon Sep 17 00:00:00 2001 From: shulaoda <165626830+shulaoda@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:50:41 +0800 Subject: [PATCH 7/9] ci: run Windows tests only on main pushes and PRs labeled --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d0fed852f..9a1c976a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,7 @@ on: branches: [main] pull_request: branches: [main] + types: [opened, synchronize, reopened, labeled] workflow_call: jobs: @@ -27,7 +28,8 @@ jobs: strategy: fail-fast: false matrix: - os: [blacksmith-4vcpu-ubuntu-2404, windows-latest] + # Windows runs on main pushes and PRs labeled "test: windows" + os: '${{ (github.event_name == ''push'' || contains(github.event.pull_request.labels.*.name, ''test: windows'')) && fromJSON(''["blacksmith-4vcpu-ubuntu-2404","windows-latest"]'') || fromJSON(''["blacksmith-4vcpu-ubuntu-2404"]'') }}' suite: [unit, core-markdown, metaframeworks, pages-react-vue, pages-svelte-solid] include: - suite: unit From 0577a83ceb14580869c99a82dcaadbc06ca08e5b Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Mon, 6 Apr 2026 08:38:43 +0000 Subject: [PATCH 8/9] ci: add done job for simplified branch protection Agent-Logs-Url: https://github.com/voidzero-dev/void/sessions/2c4f242a-32f1-4498-ada5-6dba1d9d9803 Co-authored-by: Brooooooklyn <3468483+Brooooooklyn@users.noreply.github.com> --- .github/workflows/ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9a1c976a7..0e65c386a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,3 +62,13 @@ jobs: if: matrix.suite != 'unit' && contains(matrix.os, 'windows') - run: pnpm ${{ matrix.script }}${{ matrix.retry && format(' --retry {0}', matrix.retry) || '' }} + + done: + runs-on: ubuntu-latest + if: always() + needs: + - lint-and-check + - test + steps: + - run: exit 1 + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} From 9d9ecf42a53ed17a0b1c64e18b90a600cbfaa498 Mon Sep 17 00:00:00 2001 From: "anthropic-code-agent[bot]" <242468646+Claude@users.noreply.github.com> Date: Mon, 6 Apr 2026 14:16:18 +0000 Subject: [PATCH 9/9] fix(test): add stabilization delay before HMR in Vue Pages test for Windows Agent-Logs-Url: https://github.com/voidzero-dev/void/sessions/04814680-5700-497a-b8b6-1620646356e2 Co-authored-by: Brooooooklyn <3468483+Brooooooklyn@users.noreply.github.com> --- packages/vue/test/integration/vue-pages-client.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/vue/test/integration/vue-pages-client.test.ts b/packages/vue/test/integration/vue-pages-client.test.ts index bffdd1d94..8d17a53b0 100644 --- a/packages/vue/test/integration/vue-pages-client.test.ts +++ b/packages/vue/test/integration/vue-pages-client.test.ts @@ -765,6 +765,9 @@ describe("vue-pages client (dev)", () => { () => document.querySelector('[data-testid="count"]')?.textContent === "Count: 1", ); + // Wait a bit for reactive state to stabilize before HMR (Windows can be slower) + await new Promise((r) => setTimeout(r, 200)); + // Set a window marker to detect full page reload await page.evaluate(() => { (window as any).__hmr_marker = true;