Преглед изворни кода

ci(windows): split the Windows lane to mirror Linux's lane structure

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).
Huanqi Cao пре 3 месеци
родитељ
комит
007001677d
1 измењених фајлова са 39 додато и 22 уклоњено
  1. 39 22
      .github/workflows/ci.yml

+ 39 - 22
.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
-        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
+      - name: Run 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