Files
cc-switch/.github/workflows/wsl2-nightly.yml
T
Jason 5ae6ad3888 ci(wsl): retry flaky lib tests in the WSL2 nightly
The 9P share sometimes aborts a write mid-test with os error 995
(ERROR_OPERATION_ABORTED): a Claude Desktop config test passed in 1.3s
on one run and failed after 17s on the next with no code change.

Retry up to twice in the nightly only. The ci profile used by PRs keeps
failing on the first error, and nextest still lists retried passes as
FLAKY so repeat offenders stay visible.
2026-10-08 11:25:51 +08:00

124 lines
5.9 KiB
YAML

name: WSL2 Nightly
# Runs the backend library tests with HOME and TEMP on a \\wsl.localhost (9P)
# share, nightly rather than per PR. The per-PR gate in ci.yml only runs the
# atomic-write contract test against the same WSL2-backed environment.
#
# Windows cannot lock SQLite files on a 9P share. The app's database lives in
# the Windows home unless the user explicitly overrides the app config dir, and
# CC Switch skips Codex state DBs on WSL paths. So here
# `database::` tests are skipped by name, tests that build SQLite fixtures skip
# themselves (config::sqlite_unsupported_in_temp_dir), and integration tests,
# which all create the app database, are not run. Tests run under cargo-nextest
# one at a time, so a hung test is killed by the per-test timeout in
# src-tauri/.config/nextest.toml instead of eating the whole job.
#
# The tests are built once into a nextest archive with the native TEMP, and the
# run steps execute that archive. Invoking cargo with TEMP on \\wsl.localhost
# can re-link the crate, and link.exe/mt.exe cannot create manifest temp files
# there (LNK1327).
on:
schedule:
- cron: "23 18 * * *" # 02:23 Beijing time
workflow_dispatch:
jobs:
backend-windows-wsl2-full:
name: Backend Lib Suite (Windows + WSL2 home)
runs-on: windows-2025
timeout-minutes: 30
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v6
# rust-toolchain.toml 是编译器版本的唯一来源:直接装它,免得先装 stable 再被 rustup 换掉
- name: Read pinned Rust toolchain
id: rust-toolchain
shell: bash
run: |
channel=$(sed -nE 's/^channel *= *"([^"]+)".*/\1/p' rust-toolchain.toml)
test -n "$channel"
echo "channel=$channel" >> "$GITHUB_OUTPUT"
- name: Setup Rust
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
with:
toolchain: ${{ steps.rust-toolchain.outputs.channel }}
- name: Setup WSL2
uses: Vampire/setup-wsl@d1da7f2c0322a5ee4f24975344f67fc0f5baf364 # v7
with:
distribution: Ubuntu-24.04
wsl-version: 2
# 只恢复不保存:夜间只编 lib 测试,若由它存进 main 的缓存,PR 的 Windows job 会精确命中
# 这份不完整的缓存。完整缓存由 ci.yml backend 矩阵的 Windows job 保存(同一个 shared-key)。
- name: Restore Rust dependencies
uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
workspaces: src-tauri -> target
shared-key: backend
save-if: false
- name: Install cargo-nextest
uses: taiki-e/install-action@e407f7bafb71fd004bc5c2da3032e5470cbb6ef0 # v2.87.24
with:
tool: cargo-nextest
- name: Create frontend dist placeholder
shell: bash
run: mkdir -p dist
- name: Prepare WSL2-backed test environment
shell: pwsh
run: |
wsl.exe -d Ubuntu-24.04 -- bash -lc "rm -rf /tmp/cc-switch-windows-test-root && mkdir -p /tmp/cc-switch-windows-test-root/{home,temp} && chmod -R 0777 /tmp/cc-switch-windows-test-root"
$testRoot = "\\wsl.localhost\Ubuntu-24.04\tmp\cc-switch-windows-test-root"
$testHome = Join-Path $testRoot "home"
$testTemp = Join-Path $testRoot "temp"
foreach ($path in @($testRoot, $testHome, $testTemp)) {
if (-not (Test-Path -LiteralPath $path)) {
throw "WSL2-backed test path is unavailable: $path"
}
}
"CC_SWITCH_TEST_HOME=$testHome" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"CC_SWITCH_WSL_TEST_DIR=$testRoot" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"CC_SWITCH_WSL_TEST_TEMP=$testTemp" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# link.exe/mt.exe cannot create manifests when TEMP points at a WSL UNC path,
# so build here with the native TEMP and only run the archive below.
- name: Archive backend lib tests with native temp
shell: pwsh
run: |
$archive = Join-Path $env:RUNNER_TEMP "cc-switch-lib-tests.tar.zst"
$extractDir = Join-Path $env:RUNNER_TEMP "cc-switch-lib-tests"
# --extract-to requires an existing directory
New-Item -ItemType Directory -Force -Path $extractDir | Out-Null
cargo nextest archive --lib --manifest-path src-tauri/Cargo.toml --archive-file $archive
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
"NEXTEST_ARCHIVE=$archive" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
"NEXTEST_EXTRACT_DIR=$extractDir" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
# Running from the archive never invokes the build. The binaries are
# extracted to the native runner temp, not to TEMP on \\wsl.localhost.
# --no-tests fail turns a renamed or cfg'd-out contract test into a failure.
- name: Run Windows-to-WSL2 filesystem contract
shell: pwsh
run: |
$env:TEMP = $env:CC_SWITCH_WSL_TEST_TEMP
$env:TMP = $env:CC_SWITCH_WSL_TEST_TEMP
cargo nextest run --archive-file $env:NEXTEST_ARCHIVE --extract-to $env:NEXTEST_EXTRACT_DIR --extract-overwrite --profile ci --no-tests fail --no-capture --run-ignored only -E 'test(=config::tests::atomic_write_replaces_existing_wsl_unc_file)'
# The 9P share sometimes aborts a write mid-test (os error 995). Retry here
# only, not in the ci profile; nextest still reports such tests as FLAKY.
- name: Run lib tests against WSL2-backed home
shell: pwsh
run: |
$env:TEMP = $env:CC_SWITCH_WSL_TEST_TEMP
$env:TMP = $env:CC_SWITCH_WSL_TEST_TEMP
cargo nextest run --archive-file $env:NEXTEST_ARCHIVE --extract-to $env:NEXTEST_EXTRACT_DIR --extract-overwrite --profile ci --test-threads 1 --retries 2 -E 'not test(/database::/)'