From 03348aa382c5775fbe92eadc0854079e2d277121 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Wed, 22 Jul 2026 14:53:46 +0800 Subject: [PATCH] ci: parallelize aggregate lint --- .github/workflows/ci.yml | 1 + scripts/run-gates.ts | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a41eb480d5..719e2f8e9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -849,6 +849,7 @@ jobs: env: DSH_COVERAGE_MAX_WORKERS: ${{ matrix.workers }} DSH_ESLINT_CACHE: '1' + DSH_ESLINT_CONCURRENCY: ${{ matrix.workers }} DSH_GATE_CONCURRENCY: ${{ matrix.workers }} DSH_PUBLINT_CONCURRENCY: ${{ matrix.workers }} DSH_SNAPSHOT_MAX_CONCURRENCY: ${{ matrix.workers }} diff --git a/scripts/run-gates.ts b/scripts/run-gates.ts index b117c62d11..98326d6db9 100644 --- a/scripts/run-gates.ts +++ b/scripts/run-gates.ts @@ -306,10 +306,12 @@ function ciWindowsObservationalGates(): Gate[] { } function lintGate(eslintTargets: readonly string[] = ['.']): Gate { + const concurrencyArgs = eslintConcurrencyArgs() if (process.env.DSH_ESLINT_CACHE === '1') { return pnpmExec('lint', [ 'eslint', ...eslintTargets, + ...concurrencyArgs, '--cache', '--cache-location', '.cache/eslint/', @@ -320,11 +322,28 @@ function lintGate(eslintTargets: readonly string[] = ['.']): Gate { env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') }, }) } + if (concurrencyArgs.length > 0) { + return pnpmExec('lint', ['eslint', ...eslintTargets, ...concurrencyArgs], { + label: 'lint', + env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') }, + }) + } return pnpmScript('lint', 'lint', { env: { NODE_OPTIONS: nodeOptions('--max-old-space-size=8192') }, }) } +function eslintConcurrencyArgs(): string[] { + const raw = process.env.DSH_ESLINT_CONCURRENCY + if (raw === undefined || raw === '') return [] + if (raw === 'auto') return ['--concurrency=auto'] + const parsed = Number.parseInt(raw, 10) + if (!Number.isSafeInteger(parsed) || parsed < 1 || String(parsed) !== raw) { + throw new Error(`run-gates: DSH_ESLINT_CONCURRENCY must be a positive integer or auto, got ${JSON.stringify(raw)}.`) + } + return [`--concurrency=${raw}`] +} + function coverageGate(): Gate { const shard = process.env.DSH_COVERAGE_SHARD return pnpmExec('coverage', [