mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-10-26 16:55:08 +00:00
# Conflicts: # .github/workflows/ci-windows.yml # apps/desktop/windows-signing/README.i18n.yaml
265 lines
13 KiB
YAML
265 lines
13 KiB
YAML
name: CI Windows
|
|
|
|
# Native Windows pull-request lanes run in their own workflow so a slow Windows
|
|
# job does not keep the CI run in progress: GitHub re-runs failed jobs only
|
|
# after every job of a run finishes, so each workflow can be re-run without
|
|
# waiting for the others. Branch protection requires this workflow's
|
|
# "windows checks passed" verdict beside CI's "all checks passed" and CI
|
|
# Python's "python checks passed".
|
|
on:
|
|
pull_request:
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
PRIMARY_NODE_VERSION: '24'
|
|
# CI runs must never report to the production telemetry endpoint baked
|
|
# into apps/cli/cordis.yml (AppCLIEntry disables the row when set).
|
|
DSH_TELEMETRY_DISABLED: '1'
|
|
|
|
# Cancel a superseded pull-request run on a new push, as in ci.yml.
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
# Native builds and process tests block pull requests independently of coverage.
|
|
# Observational checks reuse the successful build and remain non-blocking.
|
|
# Dependabot PRs are excluded from the self-hosted pool and stay queued for
|
|
# the hosted runner.
|
|
# Blacksmith uses 2 vCPU for file-serial native tests and 16 for coverage
|
|
# and the shared build/observational workspace.
|
|
windows-build:
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: >-
|
|
${{ vars.DSH_CI_FAILOVER_WINDOWS == 'blacksmith' && 'blacksmith-16vcpu-windows-2025'
|
|
|| vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted'
|
|
&& github.event.pull_request.user.login != 'dependabot[bot]'
|
|
&& fromJSON('["self-hosted", "dsh-win-ci", "windows"]')
|
|
|| 'dsh-windows-2025-16core' }}
|
|
name: windows node 24 / build & observational
|
|
timeout-minutes: 60
|
|
env:
|
|
# A failing build or site aborts the sibling gate on the same runner.
|
|
DSH_GATE_FAIL_FAST: '1'
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Enable Developer Mode (symlink support)
|
|
shell: pwsh
|
|
run: >-
|
|
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
|
/t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
|
|
- uses: pnpm/action-setup@v5.0.0
|
|
with:
|
|
dest: ${{ runner.temp }}/setup-pnpm-js-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}
|
|
- uses: actions/setup-node@v7.0.0
|
|
with:
|
|
node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
- name: Install (immutable)
|
|
shell: pwsh
|
|
# See 2026-08-30-windows-refs-store-block-clone-install for the
|
|
# ReFS block-clone rationale; detect the workspace filesystem and
|
|
# pass --package-import-method=clone only on ReFS.
|
|
run: >-
|
|
$drive = (Split-Path -Qualifier $env:GITHUB_WORKSPACE).TrimEnd(':');
|
|
$fs = (Get-Volume -DriveLetter $drive).FileSystem;
|
|
if ($fs -eq 'ReFS') {
|
|
corepack pnpm install --frozen-lockfile --package-import-method=clone
|
|
} else {
|
|
pnpm install --frozen-lockfile
|
|
}
|
|
- name: Run blocking Windows builds
|
|
shell: pwsh
|
|
run: pnpm run check:ci:windows-blocking
|
|
- name: Parse Windows runner supervision scripts
|
|
shell: pwsh
|
|
run: |
|
|
foreach ($path in @('apps/desktop/scripts/windows-runner-task.ps1', 'apps/desktop/scripts/run-windows-runner-task.ps1', 'apps/desktop/scripts/start-windows-packaging-runner.ps1', 'apps/desktop/scripts/windows-runner-network.ps1', 'apps/desktop/scripts/run-windows-runner-network-process.ps1', 'apps/desktop/tests/windows-runner-task.ps1', 'apps/desktop/tests/windows-runner-launcher.ps1', 'apps/desktop/tests/windows-runner-network.ps1', 'apps/desktop/tests/windows-runner-network-process.ps1')) {
|
|
$tokens = $null
|
|
$parseErrors = $null
|
|
$null = [Management.Automation.Language.Parser]::ParseFile((Join-Path $env:GITHUB_WORKSPACE $path), [ref]$tokens, [ref]$parseErrors)
|
|
if ($parseErrors.Count) { throw ($parseErrors -join "`n") }
|
|
}
|
|
- name: Verify windowless Windows runner launcher
|
|
shell: pwsh
|
|
run: ./apps/desktop/tests/windows-runner-launcher.ps1
|
|
- name: Verify Windows packaging priority inheritance
|
|
shell: pwsh
|
|
run: ./apps/desktop/tests/windows-packaging-priority.ps1
|
|
- name: Verify Windows runner network supervision
|
|
shell: pwsh
|
|
run: |
|
|
./apps/desktop/tests/windows-runner-network.ps1
|
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
|
./apps/desktop/tests/windows-runner-network-process.ps1
|
|
- name: Run Windows observational gates on built artifacts
|
|
id: observational
|
|
continue-on-error: true
|
|
timeout-minutes: 15
|
|
shell: pwsh
|
|
env:
|
|
DSH_GATE_FAIL_FAST: ''
|
|
DSH_PUBLINT_CONCURRENCY: ${{ vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '8' || '' }}
|
|
run: pnpm run check:ci:windows-observational-ready
|
|
- name: Report Windows observational failures
|
|
continue-on-error: true
|
|
if: steps.observational.outcome == 'failure'
|
|
shell: pwsh
|
|
run: |
|
|
$message = 'Windows observational checks failed; see the observational step for diagnostics.'
|
|
Write-Output "::warning::$message"
|
|
$message | Out-File -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8 -Append
|
|
|
|
windows-coverage:
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: >-
|
|
${{ vars.DSH_CI_FAILOVER_WINDOWS == 'blacksmith' && 'blacksmith-16vcpu-windows-2025'
|
|
|| vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted'
|
|
&& github.event.pull_request.user.login != 'dependabot[bot]'
|
|
&& fromJSON('["self-hosted", "dsh-win-ci", "windows"]')
|
|
|| 'dsh-windows-2025-16core' }}
|
|
name: windows node 24 / coverage
|
|
timeout-minutes: 120
|
|
env:
|
|
# Shared hosts expose host CPUs, not an isolated allocation.
|
|
DSH_COVERAGE_MAX_WORKERS: ${{ vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '6' || '' }}
|
|
DSH_COVERAGE_PARTITIONS: ${{ vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '4' || '' }}
|
|
DSH_GATE_CONCURRENCY: ${{ vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted' && github.event.pull_request.user.login != 'dependabot[bot]' && '3' || '' }}
|
|
DSH_COVERAGE_TEST_TIMEOUT_MS: '90000'
|
|
# A gate failure aborts the sibling gate instead of waiting out its
|
|
# multi-minute instrumented run.
|
|
DSH_GATE_FAIL_FAST: '1'
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
# Checkout removes the gitignored duration history, so restore it from
|
|
# the GitHub cache before coverage and save the updated one afterwards.
|
|
# The coordinator then weights partitions by measured durations on the
|
|
# second run instead of degrading to a file-count split. GitHub cache
|
|
# entries are immutable, so the save key is unique per run and the
|
|
# restore matches the newest entry through the stable prefix.
|
|
- name: Restore coverage duration history
|
|
uses: actions/cache/restore@v6.1.0
|
|
with:
|
|
path: .coverage-times.json
|
|
key: coverage-times-Windows-${{ runner.environment }}-${{ vars.DSH_CI_FAILOVER_WINDOWS || 'enterprise' }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
restore-keys: |
|
|
coverage-times-Windows-${{ runner.environment }}-${{ vars.DSH_CI_FAILOVER_WINDOWS || 'enterprise' }}-
|
|
- name: Enable Developer Mode (symlink support)
|
|
shell: pwsh
|
|
run: >-
|
|
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
|
/t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
|
|
- uses: pnpm/action-setup@v5.0.0
|
|
with:
|
|
dest: ${{ runner.temp }}/setup-pnpm-js-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}
|
|
- uses: actions/setup-node@v7.0.0
|
|
with:
|
|
node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
- name: Install (immutable)
|
|
shell: pwsh
|
|
# See 2026-08-30-windows-refs-store-block-clone-install for the
|
|
# ReFS block-clone rationale; detect the workspace filesystem and
|
|
# pass --package-import-method=clone only on ReFS.
|
|
run: >-
|
|
$drive = (Split-Path -Qualifier $env:GITHUB_WORKSPACE).TrimEnd(':');
|
|
$fs = (Get-Volume -DriveLetter $drive).FileSystem;
|
|
if ($fs -eq 'ReFS') {
|
|
corepack pnpm install --frozen-lockfile --package-import-method=clone
|
|
} else {
|
|
pnpm install --frozen-lockfile
|
|
}
|
|
# No build before coverage, matching the Linux lane: workspace imports
|
|
# resolve to src through the tsconfig paths map, and the lib-consuming
|
|
# suites (webworker-packer image-loadable, webworker-runtime
|
|
# transform-corpus, client ui-trajectory client-bundle) self-skip on
|
|
# unbuilt checkouts.
|
|
- name: Run Windows coverage
|
|
shell: pwsh
|
|
run: pnpm run check:ci:coverage
|
|
- name: Save coverage duration history
|
|
# Coverage flakes must not prevent the cache from building; the
|
|
# measured durations remain useful even when a partition failed. The
|
|
# per-run key keeps every save a fresh immutable cache entry.
|
|
if: ${{ !cancelled() }}
|
|
uses: actions/cache/save@v6.1.0
|
|
with:
|
|
path: .coverage-times.json
|
|
key: coverage-times-Windows-${{ runner.environment }}-${{ vars.DSH_CI_FAILOVER_WINDOWS || 'enterprise' }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
|
|
windows-native-tests:
|
|
if: github.event_name == 'pull_request'
|
|
runs-on: >-
|
|
${{ vars.DSH_CI_FAILOVER_WINDOWS == 'blacksmith' && 'blacksmith-2vcpu-windows-2025'
|
|
|| vars.DSH_CI_FAILOVER_WINDOWS == 'selfhosted'
|
|
&& github.event.pull_request.user.login != 'dependabot[bot]'
|
|
&& fromJSON('["self-hosted", "dsh-win-ci", "windows"]')
|
|
|| 'dsh-windows-2025-16core' }}
|
|
name: windows node 24 / native tests
|
|
timeout-minutes: 60
|
|
steps:
|
|
- uses: actions/checkout@v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Enable Developer Mode (symlink support)
|
|
shell: pwsh
|
|
run: >-
|
|
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
|
|
/t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
|
|
- uses: pnpm/action-setup@v5.0.0
|
|
with:
|
|
dest: ${{ runner.temp }}/setup-pnpm-js-${{ github.run_id }}-${{ github.run_attempt }}-${{ github.job }}
|
|
- uses: actions/setup-node@v7.0.0
|
|
with:
|
|
node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
- name: Install (immutable)
|
|
shell: pwsh
|
|
# See 2026-08-30-windows-refs-store-block-clone-install for the
|
|
# ReFS block-clone rationale; detect the workspace filesystem and
|
|
# pass --package-import-method=clone only on ReFS.
|
|
run: >-
|
|
$drive = (Split-Path -Qualifier $env:GITHUB_WORKSPACE).TrimEnd(':');
|
|
$fs = (Get-Volume -DriveLetter $drive).FileSystem;
|
|
if ($fs -eq 'ReFS') {
|
|
corepack pnpm install --frozen-lockfile --package-import-method=clone
|
|
} else {
|
|
pnpm install --frozen-lockfile
|
|
}
|
|
- name: Run Windows-specific native tests
|
|
shell: pwsh
|
|
run: >-
|
|
pnpm exec vitest run
|
|
--no-file-parallelism
|
|
--testTimeout 90000
|
|
packages/shell/tool-pwsh/tests/loader.spec.ts
|
|
packages/workflow/workflow-ptc/tests/workflow-ptc.spec.ts
|
|
packages/experimental/tool-ralph/tests/integration.spec.ts
|
|
packages/subprocess/subprocess-local/tests/process-exit.spec.ts
|
|
|
|
# Stable required check for the Windows lanes, with the same semantics as
|
|
# ci.yml's "all checks passed": every blocking job in THIS workflow is
|
|
# listed in `needs`. windows-coverage stays outside the verdict, so its
|
|
# per-file result remains visible without blocking. The bookkeeping job
|
|
# follows the Linux failover switch like the CI verdict.
|
|
windows-checks-passed:
|
|
name: windows checks passed
|
|
runs-on: >-
|
|
${{ vars.DSH_CI_FAILOVER_LINUX == 'blacksmith' && 'blacksmith-4vcpu-ubuntu-2404'
|
|
|| vars.DSH_CI_FAILOVER_LINUX == 'selfhosted'
|
|
&& github.event.pull_request.user.login != 'dependabot[bot]'
|
|
&& fromJSON('["self-hosted", "linux", "x64", "vm-backup"]')
|
|
|| 'ubuntu-latest' }}
|
|
needs: [windows-build, windows-native-tests]
|
|
if: ${{ !cancelled() && github.event_name == 'pull_request' }}
|
|
steps:
|
|
- name: Fail if any needed job did not succeed
|
|
if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'skipped')
|
|
run: |
|
|
echo "::error::Needed job results: ${{ join(needs.*.result, ', ') }}"
|
|
exit 1
|
|
- name: Windows checks passed
|
|
run: echo "All needed jobs succeeded (${{ join(needs.*.result, ', ') }})"
|