mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 09:37:33 +00:00
* ci: move secondary, scheduled and contract workflows to GitHub-hosted runners Public-repo standard hosted runners are free under Enterprise. Release, build, benchmark, e2e and unit workflows stay on Blacksmith. ci-xterm-cache seeds both cache stores since its PR consumer's pool is undecided. * test(pi): resolve the smoke bundle's external packages from the repo #34148 pulled zod into the commit-message planner graph; the bundle in the OS temp dir could not resolve it on any runner. * ci(unit): use four workers on the hosted four-core x64 runner --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
405 lines
21 KiB
YAML
405 lines
21 KiB
YAML
name: WSL orcad E2E
|
|
|
|
# WSL via orcad (step C10) on real WSL2 distros: a GitHub-hosted windows-2025 runner imports a
|
|
# pinned Ubuntu 24.04 rootfs twice (systemd off and on), plus Debian 12 and Fedora 41 (systemd off,
|
|
# rootfs exported from their container images), and runs
|
|
# src/main/wsl/wsl-orcad-real-distro-lane.test.ts against both: deploy and launch, the wsl.exe
|
|
# stdio bridge, runtime RPC, liveness recovery, holder survival, structured chat and teardown. Not a required check.
|
|
# Hosted WSL2 was proven in #27783: WSL 2.7.14, import 13-18 s, cold boot 8-14 s.
|
|
on:
|
|
pull_request:
|
|
types: [opened, synchronize, reopened, ready_for_review, converted_to_draft]
|
|
# This lane drives host RPC, not UI; pr.yml owns mobile bundle/render checks.
|
|
paths:
|
|
- 'src/main/wsl/**'
|
|
- 'src/main/runtime/**'
|
|
- 'src/main/native-chat/**'
|
|
- 'src/main/claude/**'
|
|
- 'src/main/claude-accounts/**'
|
|
- 'src/main/codex/**'
|
|
- 'src/main/acp/**'
|
|
- 'src/main/pi/**'
|
|
- 'src/main/orcad/**'
|
|
- 'src/main/server/**'
|
|
- 'src/main/persistence/**'
|
|
- 'src/main/ipc/*wsl*'
|
|
- 'src/shared/**'
|
|
- 'config/scripts/*orcad*'
|
|
- 'package.json'
|
|
- 'pnpm-lock.yaml'
|
|
- 'src/main/ssh/orcad-*'
|
|
- 'src/main/managed-server/**'
|
|
- 'src/packages/process-host/**'
|
|
# Unit tests never run in this lane; only the real distro test below does.
|
|
- '!**/*.test.ts'
|
|
- '!**/*.test.tsx'
|
|
- 'src/main/wsl/wsl-orcad-real-distro-lane.test.ts'
|
|
- 'src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts'
|
|
- '.github/workflows/wsl-orcad-e2e.yml'
|
|
- 'config/ci/wsl-lifecycle/**'
|
|
- 'config/ci/windows-lifecycle-receipt.ps1'
|
|
workflow_dispatch:
|
|
inputs:
|
|
qualification:
|
|
description: Distribution coverage (Ubuntu canary validates the CI policy)
|
|
type: choice
|
|
options: [full, ubuntu-canary]
|
|
default: full
|
|
schedule:
|
|
- cron: '45 11 * * *'
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: wsl-orcad-e2e-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
# wsl.exe prints UTF-16LE to pipes unless told otherwise.
|
|
WSL_UTF8: '1'
|
|
ROOTFS_URL: https://releases.ubuntu.com/24.04.4/ubuntu-24.04.4-wsl-amd64.wsl
|
|
ROOTFS_SHA256: 9b2f7730dc68227dd04a9f3e5eab86ad85caf556b8606ad94f1f29ff5c4fd3f5
|
|
WSL_MSI_URL: https://github.com/microsoft/WSL/releases/download/3.0.1/wsl.3.0.1.0.x64.msi
|
|
WSL_MSI_SHA256: 28b1a0d013640a2ac95898ea705fa186e5b4ff767a1c1b49257161bc106599c6
|
|
PLAIN_DISTRO: orca-lane-plain
|
|
|
|
jobs:
|
|
# The distro is linux-x64-glibc; its node-pty slot only builds on Linux, and nothing else is needed.
|
|
template:
|
|
if: github.event_name != 'pull_request' || github.event.pull_request.draft != true
|
|
name: Build the linux-x64-glibc orcad template
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 20
|
|
outputs:
|
|
families: ${{ steps.scope.outcome == 'success' && steps.scope.outputs.families || '' }}
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
fetch-depth: 2
|
|
persist-credentials: false
|
|
- uses: ./.github/actions/install-node-dependencies
|
|
with:
|
|
native-runtime: node
|
|
- name: Select WSL distribution qualification
|
|
id: scope
|
|
continue-on-error: true
|
|
shell: bash
|
|
env:
|
|
MANUAL_QUALIFICATION: ${{ inputs.qualification }}
|
|
run: |
|
|
if [ "$GITHUB_EVENT_NAME" = workflow_dispatch ] && [ "$MANUAL_QUALIFICATION" = ubuntu-canary ]; then
|
|
echo 'families=["ubuntu-24.04"]' >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
if [ "$GITHUB_EVENT_NAME" != pull_request ]; then
|
|
echo 'Full WSL distribution reference' >> "$GITHUB_STEP_SUMMARY"
|
|
exit 0
|
|
fi
|
|
git diff --name-only --no-renames -z HEAD^1 HEAD > "$RUNNER_TEMP/wsl-changed"
|
|
git diff --name-only --no-renames --diff-filter=M -z HEAD^1 HEAD > "$RUNNER_TEMP/wsl-modified"
|
|
node config/scripts/wsl-orcad-qualification.mjs "$RUNNER_TEMP/wsl-changed" "$RUNNER_TEMP/wsl-modified"
|
|
|
|
- uses: ./.github/actions/build-mobile-web-bundle
|
|
- name: Build the template
|
|
run: |
|
|
pnpm build:orcad-prebuilds
|
|
pnpm build:orcad-prebuilds --require-slots linux-x64-glibc
|
|
node config/scripts/build-orcad-template.mjs --targets linux-x64-glibc
|
|
- uses: actions/upload-artifact@v7
|
|
with:
|
|
name: wsl-orcad-template
|
|
path: out/orcad-template/
|
|
# The template carries dot-directories (`.claude-plugin`) its manifest checksums.
|
|
include-hidden-files: true
|
|
retention-days: 1
|
|
if-no-files-found: error
|
|
|
|
# Container images ship no systemd, so these families run the systemd-off distro only.
|
|
container-rootfs:
|
|
if: github.event_name != 'pull_request' || github.event.pull_request.draft != true
|
|
name: Export ${{ matrix.family }} rootfs
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 10
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- family: debian-12
|
|
image: debian:12
|
|
- family: fedora-41
|
|
image: fedora:41
|
|
steps:
|
|
- name: Export the image filesystem
|
|
run: |
|
|
docker pull --platform linux/amd64 '${{ matrix.image }}'
|
|
echo "digest: $(docker image inspect --format '{{index .RepoDigests 0}}' '${{ matrix.image }}')"
|
|
id="$(docker create --platform linux/amd64 '${{ matrix.image }}')"
|
|
mkdir -p rootfs
|
|
docker export "$id" > rootfs/rootfs.tar
|
|
docker rm "$id" >/dev/null
|
|
ls -l rootfs/rootfs.tar
|
|
- uses: actions/upload-artifact@v7
|
|
with:
|
|
name: wsl-orcad-rootfs-${{ matrix.family }}
|
|
path: rootfs/rootfs.tar
|
|
retention-days: 1
|
|
if-no-files-found: error
|
|
|
|
wsl2:
|
|
name: WSL2 distro (${{ matrix.family }})
|
|
needs: [template, container-rootfs]
|
|
runs-on: windows-2025
|
|
# Healthy runs take 4-11 min; a runner frozen during WSL2 setup is only reaped here (retried by wsl-orcad-e2e-frozen-runner-retry.yml).
|
|
timeout-minutes: 30
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
family: ${{ fromJSON(needs.template.outputs.families || '["ubuntu-24.04","debian-12","fedora-41"]') }}
|
|
env:
|
|
ORCA_BACKGROUND_LAUNCH: '1'
|
|
ORCA_WSL_ORCAD_LANE_RECEIPTS: ${{ github.workspace }}\test-results\wsl-orcad-lane
|
|
SYSTEMD_DISTRO: ${{ matrix.family == 'ubuntu-24.04' && 'orca-lane-systemd' || '' }}
|
|
ORCA_WSL_ORCAD_LANE_SYSTEMD_DISTRO: ${{ matrix.family == 'ubuntu-24.04' && 'orca-lane-systemd' || '' }}
|
|
defaults:
|
|
run:
|
|
shell: pwsh
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
with:
|
|
persist-credentials: false
|
|
# WSL before 3.0.1 drops the VM-wide WSLInterop entry when a systemd distro stops
|
|
# (microsoft/WSL#13885). Images from 20261007 ship 3.0.1, where reinstalling the MSI fails
|
|
# with 1603, so install only when older; `wsl --update` gets rate-limited by the GitHub API.
|
|
- name: Check the installed WSL version
|
|
id: wsl-version
|
|
run: |
|
|
"ImageOS=$env:ImageOS ImageVersion=$env:ImageVersion"
|
|
$details = (wsl.exe --version) -join "`n"
|
|
$details
|
|
$match = [regex]::Match($details, '(?m)^WSL version:\s*(\d+(?:\.\d+){2,3})\s*$')
|
|
# Inbox WSL has no --version, so an unreadable version means the package is needed.
|
|
$installed = if ($LASTEXITCODE -eq 0 -and $match.Success) { [version]$match.Groups[1].Value } else { [version]'0.0.0' }
|
|
$needsInstall = $installed -lt [version]'3.0.1'
|
|
"Installed WSL $installed; minimum 3.0.1; install needed: $needsInstall"
|
|
"needs-install=$($needsInstall.ToString().ToLowerInvariant())" >> $env:GITHUB_OUTPUT
|
|
- name: Restore the pinned WSL package
|
|
id: wsl-msi-cache
|
|
if: steps.wsl-version.outputs.needs-install == 'true'
|
|
uses: actions/cache/restore@v5
|
|
with:
|
|
path: ${{ runner.temp }}/wsl-msi
|
|
key: wsl-orcad-msi-${{ env.WSL_MSI_SHA256 }}
|
|
- name: Install WSL 3.0.1
|
|
if: steps.wsl-version.outputs.needs-install == 'true'
|
|
timeout-minutes: 8
|
|
run: |
|
|
$dir = Join-Path $env:RUNNER_TEMP 'wsl-msi'
|
|
New-Item -ItemType Directory -Force $dir | Out-Null
|
|
$msi = Join-Path $dir 'wsl.msi'
|
|
if (-not (Test-Path $msi)) { & "$env:WINDIR\System32\curl.exe" --fail --location --silent --show-error --output $msi $env:WSL_MSI_URL }
|
|
if ((Get-FileHash $msi -Algorithm SHA256).Hash.ToLowerInvariant() -ne $env:WSL_MSI_SHA256) {
|
|
Remove-Item $msi; throw 'WSL package checksum mismatch'
|
|
}
|
|
# Kept beside the receipts so the always() upload carries it.
|
|
New-Item -ItemType Directory -Force $env:ORCA_WSL_ORCAD_LANE_RECEIPTS | Out-Null
|
|
$log = Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'wsl-msi-install.log'
|
|
$install = Start-Process msiexec.exe -ArgumentList @('/i', $msi, '/qn', '/norestart', '/l*v', $log) -Wait -PassThru
|
|
if ($install.ExitCode -notin 0, 3010) {
|
|
if (Test-Path $log) {
|
|
$lines = @(Get-Content $log)
|
|
$failed = ($lines | Select-String -SimpleMatch 'Return value 3' | Select-Object -First 1).LineNumber
|
|
if ($failed) { '--- msiexec log before the failing action'; $lines[[math]::Max(0, $failed - 40)..($failed - 1)] }
|
|
'--- msiexec log tail'; $lines | Select-Object -Last 60
|
|
}
|
|
throw "WSL install failed: $($install.ExitCode)"
|
|
}
|
|
wsl.exe --shutdown
|
|
- name: Save the pinned WSL package
|
|
if: steps.wsl-version.outputs.needs-install == 'true' && steps.wsl-msi-cache.outputs.cache-hit != 'true'
|
|
uses: actions/cache/save@v5
|
|
with:
|
|
path: ${{ runner.temp }}/wsl-msi
|
|
key: wsl-orcad-msi-${{ env.WSL_MSI_SHA256 }}
|
|
- name: Verify WSL is at least 3.0.1
|
|
run: |
|
|
$details = (wsl.exe --version) -join "`n"
|
|
if ($LASTEXITCODE -ne 0) { throw "Could not read the WSL version: $details" }
|
|
$details
|
|
$match = [regex]::Match($details, '(?m)^WSL version:\s*(\d+(?:\.\d+){2,3})\s*$')
|
|
if (-not $match.Success) { throw 'Could not parse the WSL version' }
|
|
if ([version]$match.Groups[1].Value -lt [version]'3.0.1') { throw "WSL $($match.Groups[1].Value) is older than 3.0.1" }
|
|
- name: Restore the pinned rootfs
|
|
id: rootfs-cache
|
|
if: ${{ matrix.family == 'ubuntu-24.04' }}
|
|
uses: actions/cache/restore@v5
|
|
with:
|
|
path: ${{ runner.temp }}/wsl-rootfs
|
|
key: wsl-orcad-rootfs-${{ env.ROOTFS_SHA256 }}
|
|
- uses: actions/download-artifact@v8
|
|
if: ${{ matrix.family != 'ubuntu-24.04' }}
|
|
with:
|
|
name: wsl-orcad-rootfs-${{ matrix.family }}
|
|
path: ${{ runner.temp }}/wsl-rootfs
|
|
- name: Verify WSL lifecycle receipts
|
|
run: ./config/ci/wsl-lifecycle/test-wsl-lifecycle-command.ps1
|
|
# Runs beside the dependency install; the lane waits for it below.
|
|
- name: Import the distros as WSL2
|
|
id: import
|
|
background: true
|
|
timeout-minutes: 10
|
|
run: |
|
|
. config/ci/wsl-lifecycle/invoke-wsl-lifecycle-command.ps1
|
|
New-Item -ItemType Directory -Force $env:ORCA_WSL_ORCAD_LANE_RECEIPTS | Out-Null
|
|
$lifecycle = Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'import-lifecycle.json'
|
|
$cache = Join-Path $env:RUNNER_TEMP 'wsl-rootfs'
|
|
New-Item -ItemType Directory -Force $cache | Out-Null
|
|
if ('${{ matrix.family != 'ubuntu-24.04' }}' -eq 'true') {
|
|
$rootfs = Join-Path $cache 'rootfs.tar'
|
|
} else {
|
|
$rootfs = Join-Path $cache 'ubuntu.wsl'
|
|
if (-not (Test-Path $rootfs)) { Invoke-WebRequest $env:ROOTFS_URL -OutFile $rootfs }
|
|
if ((Get-FileHash $rootfs -Algorithm SHA256).Hash.ToLowerInvariant() -ne $env:ROOTFS_SHA256) {
|
|
Remove-Item $rootfs; throw 'rootfs checksum mismatch'
|
|
}
|
|
}
|
|
$install = switch ('${{ matrix.family }}') {
|
|
'ubuntu-24.04' { 'command -v git >/dev/null || (apt-get update -qq && apt-get install -y -qq git)' }
|
|
'debian-12' { 'apt-get update -qq && apt-get install -y -qq git procps' }
|
|
'fedora-41' { 'dnf -y -q install git procps-ng shadow-utils util-linux findutils tar gzip' }
|
|
default { throw 'Unknown WSL distribution family' }
|
|
}
|
|
$distros = @(@{ Name = $env:PLAIN_DISTRO; Systemd = 'false' })
|
|
if ($env:SYSTEMD_DISTRO) { $distros += @{ Name = $env:SYSTEMD_DISTRO; Systemd = 'true' } }
|
|
foreach ($d in $distros) {
|
|
$sw = [Diagnostics.Stopwatch]::StartNew()
|
|
# No WSL1 fallback: the lane exists to prove WSL2.
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage import -Distro $d.Name -Arguments @('--import', $d.Name, (Join-Path $env:RUNNER_TEMP $d.Name), $rootfs, '--version', '2')
|
|
"$($d.Name) import_ms=$($sw.ElapsedMilliseconds)"
|
|
if (-not ((Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage verify-version -Distro $d.Name -Arguments @('--list', '--verbose')) -match "$($d.Name)\s+\S+\s+2\s*$")) { throw "$($d.Name) is not a WSL2 distro" }
|
|
# A non-root default user, as on a real install; git for the lane's repo.
|
|
# The env exports go to the file a login bash reads first; Fedora's skel ships .bash_profile.
|
|
$setup = "set -e; $install; id orca >/dev/null 2>&1 || useradd -m -s /bin/bash orca; " +
|
|
"printf '[boot]\nsystemd=$($d.Systemd)\n[user]\ndefault=orca\n' > /etc/wsl.conf; " +
|
|
"rc=/home/orca/.profile; for f in /home/orca/.bash_profile /home/orca/.bash_login; do " +
|
|
"if [ -f `$f ]; then rc=`$f; break; fi; done; " +
|
|
"printf 'export ORCA_BACKGROUND_LAUNCH=1\nexport USERPROFILE=`$HOME\nexport APPDATA=`$HOME/.config\nexport LOCALAPPDATA=`$HOME/.local/share\nexport XDG_CONFIG_HOME=`$HOME/.config\nexport XDG_DATA_HOME=`$HOME/.local/share\nexport XDG_CACHE_HOME=`$HOME/.cache\nexport XDG_STATE_HOME=`$HOME/.local/state\nexport CLAUDE_CONFIG_DIR=`$HOME/.claude\nexport CODEX_HOME=`$HOME/.codex\n' >> `$rc"
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage provision -Distro $d.Name -Arguments @('-d', $d.Name, '-u', 'root', '--exec', 'sh', '-c', $setup)
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage terminate -Distro $d.Name -Arguments @('--terminate', $d.Name)
|
|
$sw.Restart()
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage first-boot -Distro $d.Name -Arguments @('-d', $d.Name, '--exec', 'sh', '-c', 'echo "user=$(id -un) pid1=$(ps -p 1 -o comm=) kernel=$(uname -r)"')
|
|
"$($d.Name) boot_ms=$($sw.ElapsedMilliseconds)"
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage terminate -Distro $d.Name -Arguments @('--terminate', $d.Name)
|
|
}
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage list -Arguments @('--list', '--verbose')
|
|
- uses: ./.github/actions/install-node-dependencies
|
|
with:
|
|
native-runtime: node
|
|
- uses: actions/download-artifact@v8
|
|
with:
|
|
name: wsl-orcad-template
|
|
path: ${{ runner.temp }}/orcad-template
|
|
- wait: import
|
|
# Saved even when the lane fails; the import step verified its checksum.
|
|
- name: Save the pinned rootfs
|
|
if: ${{ matrix.family == 'ubuntu-24.04' && steps.rootfs-cache.outputs.cache-hit != 'true' }}
|
|
uses: actions/cache/save@v5
|
|
with:
|
|
path: ${{ runner.temp }}/wsl-rootfs
|
|
key: wsl-orcad-rootfs-${{ env.ROOTFS_SHA256 }}
|
|
- name: Isolate the desktop test home
|
|
run: |
|
|
New-Item -ItemType Directory -Force $env:ORCA_WSL_ORCAD_LANE_RECEIPTS | Out-Null
|
|
$files = @('.claude/settings.json', '.claude.json', '.codex/hooks.json', '.codex/config.toml') | ForEach-Object { Join-Path $env:USERPROFILE $_ }
|
|
$hashes = @($files | ForEach-Object {
|
|
@{ Path = $_; Hash = $(if (Test-Path $_) { (Get-FileHash $_ -Algorithm SHA256).Hash } else { 'absent' }) }
|
|
})
|
|
$hashes | ConvertTo-Json | Set-Content (Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'real-home-hashes.json')
|
|
$homeDir = Join-Path $env:RUNNER_TEMP 'wsl-orcad-desktop-home'
|
|
foreach ($name in @('HOME', 'USERPROFILE', 'APPDATA', 'LOCALAPPDATA', 'XDG_CONFIG_HOME', 'XDG_DATA_HOME', 'XDG_CACHE_HOME', 'XDG_STATE_HOME', 'CLAUDE_CONFIG_DIR', 'CODEX_HOME')) {
|
|
$path = Join-Path $homeDir $name
|
|
New-Item -ItemType Directory -Force $path | Out-Null
|
|
"$name=$path" >> $env:GITHUB_ENV
|
|
}
|
|
- name: 'Phase 1: deploy, RPC, kill orcad, terminate distro'
|
|
timeout-minutes: 10
|
|
env:
|
|
ORCA_RUN_WSL_ORCAD_LANE: '1'
|
|
ORCA_WSL_ORCAD_LANE_PHASE: launch
|
|
ORCA_ORCAD_TEMPLATE_PATH: ${{ runner.temp }}/orcad-template
|
|
run: |
|
|
New-Item -ItemType Directory -Force $env:ORCA_WSL_ORCAD_LANE_RECEIPTS | Out-Null
|
|
node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts src/main/wsl/wsl-orcad-real-distro-lane.test.ts --reporter=verbose 2>&1 | Tee-Object (Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'launch.log')
|
|
if ($global:LASTEXITCODE -ne 0) { throw "launch phase failed: $global:LASTEXITCODE" }
|
|
# A new process: the holders must have kept both distros Running since phase 1 exited.
|
|
- name: 'Phase 2: holders survive, chat, reconnect, teardown'
|
|
timeout-minutes: 8
|
|
env:
|
|
ORCA_RUN_WSL_ORCAD_LANE: '1'
|
|
ORCA_WSL_ORCAD_LANE_PHASE: survive
|
|
ORCA_ORCAD_TEMPLATE_PATH: ${{ runner.temp }}/orcad-template
|
|
run: |
|
|
node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts src/main/wsl/wsl-orcad-real-distro-lane.test.ts --reporter=verbose 2>&1 | Tee-Object (Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'survive.log')
|
|
if ($global:LASTEXITCODE -ne 0) { throw "survive phase failed: $global:LASTEXITCODE" }
|
|
# R40: with no terminal left, orcad idle-exits and the holder lets the distro stop on its own.
|
|
- name: 'Phase 3: idle orcad releases the distro'
|
|
timeout-minutes: 15
|
|
env:
|
|
ORCA_RUN_WSL_ORCAD_LANE: '1'
|
|
ORCA_WSL_ORCAD_LANE_PHASE: idle-release
|
|
ORCA_ORCAD_TEMPLATE_PATH: ${{ runner.temp }}/orcad-template
|
|
run: |
|
|
node node_modules/vitest/vitest.mjs run --config config/vitest.config.ts src/main/wsl/wsl-orcad-real-distro-idle-release-lane.test.ts --reporter=verbose 2>&1 | Tee-Object (Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'idle-release.log')
|
|
if ($global:LASTEXITCODE -ne 0) { throw "idle-release phase failed: $global:LASTEXITCODE" }
|
|
- name: Real desktop agent configuration is unchanged
|
|
if: always()
|
|
run: |
|
|
$baseline = Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'real-home-hashes.json'
|
|
if (Test-Path $baseline) {
|
|
foreach ($file in (Get-Content $baseline -Raw | ConvertFrom-Json)) {
|
|
$hash = if (Test-Path $file.Path) { (Get-FileHash $file.Path -Algorithm SHA256).Hash } else { 'absent' }
|
|
if ($hash -ne $file.Hash) { throw "Real agent configuration changed: $($file.Path)" }
|
|
}
|
|
}
|
|
# Belt and braces for the runner: a missing VM-wide interop entry is restored, then fails.
|
|
- name: WSLInterop is intact
|
|
if: ${{ !cancelled() && steps.import.outcome == 'success' }}
|
|
timeout-minutes: 3
|
|
run: |
|
|
. config/ci/wsl-lifecycle/invoke-wsl-lifecycle-command.ps1
|
|
$lifecycle = Join-Path $env:ORCA_WSL_ORCAD_LANE_RECEIPTS 'interop-lifecycle.json'
|
|
try {
|
|
$state = Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage interop-check -Distro $env:PLAIN_DISTRO -Arguments @('-d', $env:PLAIN_DISTRO, '-u', 'root', '--exec', 'sh', '-c', 'if [ -e /proc/sys/fs/binfmt_misc/WSLInterop ]; then echo present; else echo :WSLInterop:M::MZ::/init:P > /proc/sys/fs/binfmt_misc/register && echo restored; fi')
|
|
"WSLInterop: $state"
|
|
} finally {
|
|
Invoke-WslLifecycleCommand -Receipt $lifecycle -Stage terminate -Distro $env:PLAIN_DISTRO -Arguments @('--terminate', $env:PLAIN_DISTRO)
|
|
}
|
|
if ("$state".Trim() -ne 'present') { throw "WSLInterop was missing ($state)" }
|
|
- name: Collect orcad logs
|
|
if: failure()
|
|
timeout-minutes: 3
|
|
run: |
|
|
$out = $env:ORCA_WSL_ORCAD_LANE_RECEIPTS
|
|
New-Item -ItemType Directory -Force $out | Out-Null
|
|
foreach ($d in @($env:PLAIN_DISTRO, $env:SYSTEMD_DISTRO) | Where-Object { $_ }) {
|
|
wsl.exe -d $d --exec sh -c 'for f in $(find "$HOME/.orca-remote" -name "*.log*" -type f 2>/dev/null); do echo "=== $f"; tail -n 400 "$f"; done' > (Join-Path $out "$d-orcad-logs.txt") 2>&1
|
|
}
|
|
wsl.exe --list --verbose
|
|
- name: Summary
|
|
if: always()
|
|
run: |
|
|
$dir = $env:ORCA_WSL_ORCAD_LANE_RECEIPTS
|
|
$lines = @("### WSL orcad lane (${{ matrix.family }}) — $env:ImageOS $env:ImageVersion", '')
|
|
foreach ($phase in 'launch', 'survive', 'idle-release') {
|
|
$file = Join-Path $dir "$phase.json"
|
|
if (Test-Path $file) { $lines += "#### $phase", '```json', (Get-Content $file -Raw), '```' }
|
|
}
|
|
$lines | Add-Content $env:GITHUB_STEP_SUMMARY
|
|
- uses: actions/upload-artifact@v7
|
|
if: always()
|
|
with:
|
|
name: wsl-orcad-lane-receipts-${{ matrix.family }}
|
|
path: test-results/wsl-orcad-lane/
|
|
retention-days: 7
|
|
if-no-files-found: ignore
|