From 007001677d1e0ba817d10d59ee35e85c073757d8 Mon Sep 17 00:00:00 2001 From: Huanqi Cao Date: Wed, 8 Jul 2026 12:45:45 +0800 Subject: [PATCH] ci(windows): split the Windows lane to mirror Linux's lane structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Windows CI was a single job running the full ci-windows inventory (check:ci:windows), while Linux splits into 5 lanes (static/lint/coverage/ snapshot/artifacts) per the parallel-gates RFC. The single-job shape was a transitional artifact from when Windows CI was added as a non-required observation lane; its rationale ('keep gate parallelism modest so coverage is not starved') conflated run-gates intra-job concurrency (DSH_GATE_CONCURRENCY) with GitHub job fan-out — orthogonal concerns. Split Windows into 4 lanes mirroring Linux (snapshot absent: its goldens are Linux-recorded and self-skip on Windows). Each lane is a separate GitHub job so a Windows regression is attributable to one lane, not buried in one job's log. Concurrency is NOT throttled versus Linux: the lane is non-blocking (continue-on-error), and the observational stance is to actively expose Windows-arm issues rather than hide them behind reduced parallelism. - scripts/run-gates.ts: add ci-windows:static/lint/coverage/artifacts modes; ci-windows (full inventory) is retained as the local one-process entry, symmetric with Linux's ci-primary. - .github/workflows/ci.yml: windows job becomes a matrix over the 4 lanes. - package.json: check:ci:windows:{static,lint,coverage,artifacts} scripts. - AGENTS.md + windows-support RFC: document the per-lane, non-blocking, unthrottled stance. Verified: scripts/caohuanqi-private/run-ci.py --windows (full check:ci:windows) — all gates green except the known hooks-claude bridge.spec waitFor timeout (pre-existing Windows subprocess-timing flake, unrelated). --- .github/workflows/ci.yml | 61 +++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 399d517d29..88abf56a3f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -182,17 +182,45 @@ jobs: - name: Build (tsc -b + tsdown) run: pnpm run build - # Observational Windows mirror of the Linux gates. Snapshot stays Linux-only - # while its replay goldens remain platform-specific. This job intentionally - # stays out of all-checks-passed.needs. + # Observational Windows mirror of the Linux gate lanes. Snapshot stays + # Linux-only while its replay goldens remain platform-specific. Splitting the + # lanes makes failures attributable without changing their non-gating role. windows-gates: runs-on: windows-2025 - name: windows node 24 + name: windows node 24 / ${{ matrix.lane }} env: - DSH_GATE_CONCURRENCY: '2' - DSH_PUBLINT_CONCURRENCY: '8' - DSH_COVERAGE_MAX_WORKERS: '4' - DSH_ESLINT_CACHE: '1' + DSH_GATE_CONCURRENCY: ${{ matrix.gate_concurrency }} + DSH_PUBLINT_CONCURRENCY: ${{ matrix.publint_concurrency }} + DSH_COVERAGE_MAX_WORKERS: ${{ matrix.coverage_max_workers }} + DSH_ESLINT_CACHE: ${{ matrix.eslint_cache }} + strategy: + fail-fast: false + matrix: + include: + - lane: static + command: pnpm run check:ci:static + gate_concurrency: '4' + publint_concurrency: '8' + coverage_max_workers: '' + eslint_cache: '' + - lane: lint + command: pnpm run check:ci:lint + gate_concurrency: '1' + publint_concurrency: '8' + coverage_max_workers: '' + eslint_cache: '1' + - lane: coverage + command: pnpm run check:ci:coverage + gate_concurrency: '1' + publint_concurrency: '8' + coverage_max_workers: '4' + eslint_cache: '' + - lane: artifacts + command: pnpm run check:ci:artifacts + gate_concurrency: '3' + publint_concurrency: '8' + coverage_max_workers: '' + eslint_cache: '' steps: - uses: actions/checkout@v6 @@ -216,6 +244,7 @@ jobs: run: '"path=$(pnpm store path --silent)" >> $env:GITHUB_OUTPUT' - uses: actions/cache@v4 + if: matrix.lane == 'lint' with: path: ${{ steps.pnpm-store.outputs.path }} key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }} @@ -233,21 +262,9 @@ jobs: restore-keys: | ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint- - - name: Run static gates + - name: Run gates shell: powershell - run: pnpm run check:ci:static - - - name: Run lint gates - shell: powershell - run: pnpm run check:ci:lint - - - name: Run coverage gates - shell: powershell - run: pnpm run check:ci:coverage - - - name: Run artifact gates - shell: powershell - run: pnpm run check:ci:artifacts + run: ${{ matrix.command }} # Single stable required check for branch protection: require "all checks # passed" instead of enumerating matrix legs whose names change as lanes and