| author | |
| committer | |
| log | f96a220b5b154ea44c94bf43929c6362cd511699 |
| tree | 49018363d85c498cd2c11dd6cdb0233b6ab54b46 |
| parent | 4e547318b60031eb546d8cf2b84ad9fa0785a87a |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Code <noreply@anthropic.com>3 files changed, 92 insertions(+), 1 deletions(-)
.github/workflows/windows-tests.yml created+81| ... | @@ -0,0 +1,81 @@ | ||
| 1 | # On-demand Windows test lane. Manual only: nothing in the suite passes on | ||
| 2 | # Windows yet, so this exists to give contributors (and agents) a cloud Windows | ||
| 3 | # box to iterate against. Once the suite is green here, fold it into ci.yml. | ||
| 4 | # | ||
| 5 | # gh workflow run windows-tests.yml --ref <branch> -f package=packages/shared | ||
| 6 | # gh workflow run windows-tests.yml --ref <branch> -f package=apps/server \ | ||
| 7 | # -f files="src/process/externalLauncher.test.ts src/cli/theme.test.ts" | ||
| 8 | # gh run watch && gh run view --log-failed | ||
| 9 | name: Windows Tests | ||
| 10 | |||
| 11 | on: | ||
| 12 | workflow_dispatch: | ||
| 13 | inputs: | ||
| 14 | package: | ||
| 15 | description: "Workspace directory to test, e.g. apps/server or packages/shared. Empty runs every package except apps/server." | ||
| 16 | type: string | ||
| 17 | default: "" | ||
| 18 | files: | ||
| 19 | description: "Space-separated test files relative to the package directory. Empty runs the package's whole suite. Requires package." | ||
| 20 | type: string | ||
| 21 | default: "" | ||
| 22 | |||
| 23 | permissions: | ||
| 24 | contents: read | ||
| 25 | |||
| 26 | jobs: | ||
| 27 | test: | ||
| 28 | name: Test (${{ inputs.package || 'all non-server' }}) | ||
| 29 | runs-on: blacksmith-8vcpu-windows-2025 | ||
| 30 | timeout-minutes: 45 | ||
| 31 | steps: | ||
| 32 | - name: Checkout | ||
| 33 | uses: actions/checkout@v6 | ||
| 34 | with: | ||
| 35 | sparse-checkout: | | ||
| 36 | /* | ||
| 37 | !/.repos/ | ||
| 38 | sparse-checkout-cone-mode: false | ||
| 39 | |||
| 40 | # setup-vp's own cache restores a Linux-shaped store on Windows, which is | ||
| 41 | # slower than no cache (see #7975). Cache pnpm's Windows store directly. | ||
| 42 | - name: Setup Vite+ | ||
| 43 | uses: voidzero-dev/setup-vp@v1 | ||
| 44 | with: | ||
| 45 | node-version-file: package.json | ||
| 46 | cache: false | ||
| 47 | run-install: false | ||
| 48 | |||
| 49 | - name: Resolve package cache path | ||
| 50 | id: package_cache_path | ||
| 51 | shell: pwsh | ||
| 52 | run: '"path=$(vp pm cache dir)" >> $env:GITHUB_OUTPUT' | ||
| 53 | |||
| 54 | - name: Cache packages | ||
| 55 | uses: actions/cache@v6 | ||
| 56 | with: | ||
| 57 | path: ${{ steps.package_cache_path.outputs.path }} | ||
| 58 | key: windows-tests-packages-v1-${{ hashFiles('pnpm-lock.yaml') }} | ||
| 59 | |||
| 60 | - name: Install | ||
| 61 | run: vp install | ||
| 62 | |||
| 63 | - name: Ensure Electron runtime is installed | ||
| 64 | if: inputs.package == '' || inputs.package == 'apps/desktop' | ||
| 65 | run: vp run --filter "@t3tools/desktop" ensure:electron | ||
| 66 | |||
| 67 | # `vp run ... test -- <files>` does not forward positional args to vitest, | ||
| 68 | # so file-scoped runs call `vp test run` inside the package instead. | ||
| 69 | - name: Test | ||
| 70 | shell: pwsh | ||
| 71 | run: | | ||
| 72 | $package = '${{ inputs.package }}' | ||
| 73 | $files = '${{ inputs.files }}' | ||
| 74 | if ($package -eq '') { | ||
| 75 | vp run --parallel --concurrency-limit 4 --filter '!t3' --filter '!@t3tools/monorepo' test | ||
| 76 | } elseif ($files -eq '') { | ||
| 77 | vp run --filter "./$package" test | ||
| 78 | } else { | ||
| 79 | Set-Location $package | ||
| 80 | vp test run $files.Split(' ') | ||
| 81 | } | ||
apps/desktop/scripts/ensure-electron-runtime.mjs+3-1| ... | @@ -2,6 +2,7 @@ import * as NodeFS from "node:fs"; | ... | @@ -2,6 +2,7 @@ import * as NodeFS from "node:fs"; |
| 2 | import * as NodeModule from "node:module"; | 2 | import * as NodeModule from "node:module"; |
| 3 | import * as NodeOS from "node:os"; | 3 | import * as NodeOS from "node:os"; |
| 4 | import * as NodePath from "node:path"; | 4 | import * as NodePath from "node:path"; |
| 5 | import * as NodeURL from "node:url"; | ||
| 5 | import * as NodeChildProcess from "node:child_process"; | 6 | import * as NodeChildProcess from "node:child_process"; |
| 6 | 7 | ||
| 7 | const require = NodeModule.createRequire(import.meta.url); | 8 | const require = NodeModule.createRequire(import.meta.url); |
| ... | @@ -176,7 +177,8 @@ export function ensureElectronRuntime() { | ... | @@ -176,7 +177,8 @@ export function ensureElectronRuntime() { |
| 176 | return electronPath; | 177 | return electronPath; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | if (import.meta.url === `file://${process.argv[1]}`) { | 180 | // `file://${argv[1]}` never matches on Windows (drive letters need `file:///C:/`). |
| 181 | if (process.argv[1] && NodeURL.pathToFileURL(process.argv[1]).href === import.meta.url) { | ||
| 180 | const electronPath = ensureElectronRuntime(); | 182 | const electronPath = ensureElectronRuntime(); |
| 181 | process.stdout.write(`${electronPath}\n`); | 183 | process.stdout.write(`${electronPath}\n`); |
| 182 | } | 184 | } |
docs/internals/ci.md+8| ... | @@ -22,6 +22,14 @@ and pushes to `main`: | ... | @@ -22,6 +22,14 @@ and pushes to `main`: |
| 22 | - **Release Smoke**: exercises release-only workflow steps through `scripts/release-smoke.ts`, so | 22 | - **Release Smoke**: exercises release-only workflow steps through `scripts/release-smoke.ts`, so |
| 23 | release breakage surfaces on PRs rather than at tag time. | 23 | release breakage surfaces on PRs rather than at tag time. |
| 24 | 24 | ||
| 25 | [`.github/workflows/windows-tests.yml`](../../.github/workflows/windows-tests.yml) is a manual | ||
| 26 | Windows lane (`workflow_dispatch` only) on a Blacksmith Windows 2025 runner. The suite does not | ||
| 27 | pass on Windows yet, so it is not a required check; it exists so the work to get there can be | ||
| 28 | iterated against a real Windows box without one on hand. Dispatch it with `gh workflow run | ||
| 29 | windows-tests.yml --ref <branch>`, optionally with `-f package=<dir>` to run one workspace package | ||
| 30 | and `-f files="<paths>"` to run specific test files inside it. Once it is green, fold it into | ||
| 31 | `ci.yml`. | ||
| 32 | |||
| 25 | `.github/workflows/release.yml` builds macOS (`arm64` and `x64`), Linux (`x64`), and Windows (`x64`) | 33 | `.github/workflows/release.yml` builds macOS (`arm64` and `x64`), Linux (`x64`), and Windows (`x64`) |
| 26 | desktop artifacts from a single `v*.*.*` tag and publishes one GitHub release. It auto-enables | 34 | desktop artifacts from a single `v*.*.*` tag and publishes one GitHub release. It auto-enables |
| 27 | signing only when platform credentials are present. macOS passkey builds additionally require | 35 | signing only when platform credentials are present. macOS passkey builds additionally require |