|
|
@@ -2,8 +2,18 @@ name: CI
|
|
|
|
|
|
on:
|
|
|
push:
|
|
|
- branches: [main, master]
|
|
|
+ branches: [master]
|
|
|
pull_request:
|
|
|
+ workflow_dispatch:
|
|
|
+ inputs:
|
|
|
+ suite:
|
|
|
+ description: Manual CI suite to run
|
|
|
+ required: true
|
|
|
+ default: larger-runner-benchmark
|
|
|
+ type: choice
|
|
|
+ options:
|
|
|
+ - larger-runner-benchmark
|
|
|
+ - consolidated-runner-benchmark
|
|
|
|
|
|
concurrency:
|
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
|
@@ -16,106 +26,89 @@ env:
|
|
|
PRIMARY_NODE_VERSION: '24'
|
|
|
|
|
|
jobs:
|
|
|
+
|
|
|
+ # One large runner pays hosted setup once, then the repository scheduler
|
|
|
+ # overlaps the complete unsharded primary Node inventory. Build starts eagerly;
|
|
|
+ # only consumers of emitted output wait for it.
|
|
|
node-24:
|
|
|
- runs-on: ubuntu-latest
|
|
|
- name: node 24 / ${{ matrix.lane }}
|
|
|
+ if: github.event_name == 'pull_request'
|
|
|
+ runs-on: dsh-ubuntu-24-04-96core
|
|
|
+ name: node 24 / complete
|
|
|
env:
|
|
|
- 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: snapshot
|
|
|
- command: pnpm run check:ci:snapshot
|
|
|
- gate_concurrency: '1'
|
|
|
- publint_concurrency: '8'
|
|
|
- coverage_max_workers: ''
|
|
|
- eslint_cache: ''
|
|
|
- - lane: artifacts
|
|
|
- command: pnpm run check:ci:artifacts
|
|
|
- gate_concurrency: '3'
|
|
|
- publint_concurrency: '8'
|
|
|
- coverage_max_workers: ''
|
|
|
- eslint_cache: ''
|
|
|
+ DSH_COVERAGE_MAX_WORKERS: '16'
|
|
|
+ DSH_ESLINT_CACHE: '1'
|
|
|
+ DSH_ESLINT_CONCURRENCY: '16'
|
|
|
+ DSH_GATE_CONCURRENCY: '10'
|
|
|
+ DSH_PUBLINT_CONCURRENCY: '16'
|
|
|
+ DSH_SNAPSHOT_MAX_CONCURRENCY: '8'
|
|
|
steps:
|
|
|
- uses: actions/checkout@v6
|
|
|
-
|
|
|
- - uses: actions/setup-node@v6
|
|
|
with:
|
|
|
- node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
|
+ persist-credentials: false
|
|
|
|
|
|
- - name: Enable corepack (pnpm)
|
|
|
- run: corepack enable
|
|
|
-
|
|
|
- - name: Resolve pnpm store path
|
|
|
- id: pnpm-store
|
|
|
- run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
-
|
|
|
- - uses: actions/cache@v4
|
|
|
+ # Pull requests consume the default-branch cache but do not put cache
|
|
|
+ # compression and upload on the paid latency-critical path.
|
|
|
+ - uses: actions/cache/restore@v4
|
|
|
with:
|
|
|
- path: ${{ steps.pnpm-store.outputs.path }}
|
|
|
+ path: /home/runner/.local/share/pnpm/store/v11
|
|
|
key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
|
restore-keys: |
|
|
|
${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-
|
|
|
|
|
|
- - name: Install (immutable)
|
|
|
- run: pnpm install --frozen-lockfile
|
|
|
-
|
|
|
- # The snapshot lane REPLAYS the sandbox example's recorded scenarios,
|
|
|
- # re-executing their bash calls under a real runner. ubuntu-latest has
|
|
|
- # no bubblewrap preinstalled and no built Landlock launcher, so without
|
|
|
- # this the confined executions fail closed (SANDBOX_UNAVAILABLE). Same
|
|
|
- # install as sandbox.yml's bwrap leg (incl. the Ubuntu 24.04 AppArmor
|
|
|
- # userns knob).
|
|
|
- - name: Install bubblewrap (unrestrict userns)
|
|
|
- if: matrix.lane == 'snapshot'
|
|
|
- run: |
|
|
|
- sudo apt-get update -q
|
|
|
- sudo apt-get install -yq bubblewrap
|
|
|
- sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 \
|
|
|
- || echo "apparmor userns knob absent — the functional probe decides"
|
|
|
-
|
|
|
- - uses: actions/cache@v4
|
|
|
- if: matrix.lane == 'lint'
|
|
|
+ - uses: actions/cache/restore@v4
|
|
|
with:
|
|
|
path: .cache/eslint
|
|
|
- key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
restore-keys: |
|
|
|
- ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-
|
|
|
+
|
|
|
+ - name: Select preinstalled Node, install dependencies, and prepare bubblewrap
|
|
|
+ run: |
|
|
|
+ node_root="$(printf '%s\n' "$RUNNER_TOOL_CACHE"/node/"${PRIMARY_NODE_VERSION}".*/x64 | sort -V | tail -n 1)"
|
|
|
+ if [[ ! -d "$node_root" ]]; then
|
|
|
+ echo "preinstalled Node ${PRIMARY_NODE_VERSION}.x not found in $RUNNER_TOOL_CACHE" >&2
|
|
|
+ exit 1
|
|
|
+ fi
|
|
|
+ echo "$node_root/bin" >> "$GITHUB_PATH"
|
|
|
+ export PATH="$node_root/bin:$PATH"
|
|
|
+ [[ "$(node --version)" == "v${PRIMARY_NODE_VERSION}."* ]]
|
|
|
+ corepack enable
|
|
|
+ pnpm install --frozen-lockfile &
|
|
|
+ install_pid=$!
|
|
|
+ bash scripts/prepare-ci-bubblewrap.sh &
|
|
|
+ sandbox_pid=$!
|
|
|
+ install_status=0
|
|
|
+ wait "$install_pid" || install_status=$?
|
|
|
+ sandbox_status=0
|
|
|
+ wait "$sandbox_pid" || sandbox_status=$?
|
|
|
+ if (( install_status != 0 )); then exit "$install_status"; fi
|
|
|
+ exit "$sandbox_status"
|
|
|
+
|
|
|
+ - name: Run complete unsharded primary Node CI concurrently
|
|
|
+ run: pnpm run check:ci
|
|
|
|
|
|
- - name: Run gates
|
|
|
- run: ${{ matrix.command }}
|
|
|
|
|
|
node-compat:
|
|
|
- runs-on: ubuntu-latest
|
|
|
- name: node ${{ matrix.node }}
|
|
|
+ if: github.event_name == 'pull_request'
|
|
|
+ # Distinct larger-runner pools avoid both standard-runner setup outliers and
|
|
|
+ # delayed allocation when independent environment contracts share one pool.
|
|
|
+ runs-on: ${{ matrix.runner }}
|
|
|
+ name: ${{ matrix.name }}
|
|
|
env:
|
|
|
- DSH_GATE_CONCURRENCY: '2'
|
|
|
+ DSH_GATE_CONCURRENCY: ${{ matrix.gate_concurrency }}
|
|
|
+ DSH_NODE_COMPAT_SKIP_TYPECHECK: '1'
|
|
|
strategy:
|
|
|
fail-fast: false
|
|
|
matrix:
|
|
|
- node: ['22.19', 24, 26]
|
|
|
+ include:
|
|
|
+ - node: '22.19'
|
|
|
+ name: node 22.19
|
|
|
+ runner: dsh-ubuntu-24-04-4core
|
|
|
+ gate_concurrency: '2'
|
|
|
+ - node: 26
|
|
|
+ name: node 26
|
|
|
+ runner: dsh-ubuntu-24-04-32core
|
|
|
+ gate_concurrency: '2'
|
|
|
steps:
|
|
|
- uses: actions/checkout@v6
|
|
|
|
|
|
@@ -123,12 +116,11 @@ jobs:
|
|
|
with:
|
|
|
node-version: ${{ matrix.node }}
|
|
|
|
|
|
- - name: Enable corepack (pnpm)
|
|
|
- run: corepack enable
|
|
|
-
|
|
|
- - name: Resolve pnpm store path
|
|
|
+ - name: Enable corepack and resolve pnpm store path
|
|
|
id: pnpm-store
|
|
|
- run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
+ run: |
|
|
|
+ corepack enable
|
|
|
+ echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
|
|
|
- uses: actions/cache@v4
|
|
|
with:
|
|
|
@@ -140,11 +132,12 @@ jobs:
|
|
|
- name: Install (immutable)
|
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
|
|
- - name: Run compatibility gates
|
|
|
+ - name: Run compatibility smokes
|
|
|
run: pnpm run check:node-compat
|
|
|
|
|
|
python-sdk:
|
|
|
- runs-on: ubuntu-latest
|
|
|
+ if: github.event_name == 'pull_request'
|
|
|
+ runs-on: dsh-ubuntu-24-04-8core
|
|
|
name: python 3.10 / keyless SDK
|
|
|
steps:
|
|
|
- uses: actions/checkout@v6
|
|
|
@@ -160,12 +153,114 @@ jobs:
|
|
|
- name: Run complete keyless Python suite
|
|
|
run: uv run --python 3.10 --group test --project python/sdk pytest
|
|
|
|
|
|
- # Blocking Windows build lane: keep the already-green native build protected
|
|
|
- # while the broader observational gate matrix below exposes the remaining
|
|
|
- # portability work without blocking mainline merges.
|
|
|
- windows-build:
|
|
|
- runs-on: windows-2025
|
|
|
- name: windows / build
|
|
|
+ # One Windows box shares setup across the required build/site checks and the
|
|
|
+ # complete observational portability inventory. run-gates reports failures
|
|
|
+ # from observational gates without allowing them to fail the required job.
|
|
|
+ windows:
|
|
|
+ if: github.event_name == 'pull_request'
|
|
|
+ runs-on: dsh-windows-2025-32core
|
|
|
+ name: windows node 24 / complete
|
|
|
+ env:
|
|
|
+ # Keep ESLint itself single-threaded: 16 ESLint workers took 174 seconds on
|
|
|
+ # this image. The outer scheduler still overlaps lint with the other gates.
|
|
|
+ DSH_COVERAGE_MAX_WORKERS: '12'
|
|
|
+ DSH_ESLINT_CACHE: '1'
|
|
|
+ DSH_GATE_CONCURRENCY: '16'
|
|
|
+ DSH_PUBLINT_CONCURRENCY: '16'
|
|
|
+ steps:
|
|
|
+ - uses: actions/checkout@v6
|
|
|
+
|
|
|
+ - uses: actions/cache/restore@v4
|
|
|
+ with:
|
|
|
+ path: .cache/eslint
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
+ restore-keys: |
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-
|
|
|
+
|
|
|
+ # Extracting the many-file pnpm store cache is slower on this image than
|
|
|
+ # a clean parallel install, and saving it adds more latency after gates.
|
|
|
+ - name: Select preinstalled Node and install (immutable)
|
|
|
+ shell: pwsh
|
|
|
+ run: |
|
|
|
+ $nodeRoot = Get-ChildItem -Path "$env:RUNNER_TOOL_CACHE\node" -Directory |
|
|
|
+ Where-Object { $_.Name -like "$env:PRIMARY_NODE_VERSION.*" } |
|
|
|
+ Sort-Object { [version]$_.Name } |
|
|
|
+ Select-Object -Last 1
|
|
|
+ if ($null -eq $nodeRoot) {
|
|
|
+ throw "preinstalled Node $env:PRIMARY_NODE_VERSION.x not found in $env:RUNNER_TOOL_CACHE"
|
|
|
+ }
|
|
|
+ $nodeBin = Join-Path $nodeRoot.FullName 'x64'
|
|
|
+ if (-not (Test-Path $nodeBin -PathType Container)) {
|
|
|
+ throw "preinstalled Node x64 directory not found at $nodeBin"
|
|
|
+ }
|
|
|
+ Add-Content -Path $env:GITHUB_PATH -Value $nodeBin
|
|
|
+ $env:PATH = "$nodeBin;$env:PATH"
|
|
|
+ if ((node --version) -notlike "v$env:PRIMARY_NODE_VERSION.*") {
|
|
|
+ throw "selected unexpected Node version $(node --version)"
|
|
|
+ }
|
|
|
+ corepack enable
|
|
|
+ pnpm install --frozen-lockfile
|
|
|
+
|
|
|
+ - name: Run blocking and observational Windows gates concurrently
|
|
|
+ shell: pwsh
|
|
|
+ run: pnpm run check:ci:windows-complete
|
|
|
+
|
|
|
+ # Master pushes run only the serial reference jobs below.
|
|
|
+ # Each host executes the complete, unsharded primary Node aggregate with one
|
|
|
+ # gate worker, giving reviewers a simple cross-platform oracle for completeness
|
|
|
+ # and timing.
|
|
|
+ serial-linux:
|
|
|
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
|
+ name: serial / linux
|
|
|
+ runs-on: ubuntu-latest
|
|
|
+ steps:
|
|
|
+ - uses: actions/checkout@v6
|
|
|
+
|
|
|
+ - uses: actions/setup-node@v6
|
|
|
+ with:
|
|
|
+ node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
|
+
|
|
|
+ - name: Enable corepack and resolve pnpm store path
|
|
|
+ id: pnpm-store
|
|
|
+ run: |
|
|
|
+ corepack enable
|
|
|
+ echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
+
|
|
|
+ # Master refreshes the caches that pull requests restore without saving.
|
|
|
+ - uses: actions/cache@v4
|
|
|
+ with:
|
|
|
+ path: ${{ steps.pnpm-store.outputs.path }}
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
|
+ restore-keys: |
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-
|
|
|
+
|
|
|
+ - uses: actions/cache@v4
|
|
|
+ with:
|
|
|
+ path: .cache/eslint
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
+ restore-keys: |
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-
|
|
|
+
|
|
|
+ - name: Install (immutable)
|
|
|
+ run: pnpm install --frozen-lockfile
|
|
|
+
|
|
|
+ - name: Prepare bubblewrap (unrestrict userns)
|
|
|
+ run: bash scripts/prepare-ci-bubblewrap.sh
|
|
|
+
|
|
|
+ - name: Run complete unsharded primary Node CI serially
|
|
|
+ env:
|
|
|
+ DSH_COVERAGE_MAX_WORKERS: '1'
|
|
|
+ DSH_E2E_MAX_WORKERS: '1'
|
|
|
+ DSH_ESLINT_CACHE: '1'
|
|
|
+ DSH_GATE_CONCURRENCY: '1'
|
|
|
+ DSH_PUBLINT_CONCURRENCY: '1'
|
|
|
+ DSH_SNAPSHOT_MAX_CONCURRENCY: '1'
|
|
|
+ run: pnpm run check:ci
|
|
|
+
|
|
|
+ serial-macos:
|
|
|
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
|
+ name: serial / macos
|
|
|
+ runs-on: macos-latest
|
|
|
steps:
|
|
|
- uses: actions/checkout@v6
|
|
|
|
|
|
@@ -179,55 +274,19 @@ jobs:
|
|
|
- name: Install (immutable)
|
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
|
|
- - name: Build (tsc -b + tsdown)
|
|
|
- run: pnpm run build
|
|
|
-
|
|
|
- # Observational, non-blocking Windows mirror of the Linux gate lanes. Run the
|
|
|
- # gates from native PowerShell: an MSYS parent would change the environment
|
|
|
- # being measured. This job intentionally stays out of all-checks-passed.needs.
|
|
|
- windows-gates:
|
|
|
- continue-on-error: true
|
|
|
+ - name: Run complete unsharded primary Node CI serially
|
|
|
+ env:
|
|
|
+ DSH_COVERAGE_MAX_WORKERS: '1'
|
|
|
+ DSH_E2E_MAX_WORKERS: '1'
|
|
|
+ DSH_GATE_CONCURRENCY: '1'
|
|
|
+ DSH_PUBLINT_CONCURRENCY: '1'
|
|
|
+ DSH_SNAPSHOT_MAX_CONCURRENCY: '1'
|
|
|
+ run: pnpm run check:ci
|
|
|
+
|
|
|
+ serial-windows:
|
|
|
+ if: github.event_name == 'push' && github.ref == 'refs/heads/master'
|
|
|
+ name: serial / windows
|
|
|
runs-on: windows-2025
|
|
|
- name: windows node 24 / ${{ matrix.lane }}
|
|
|
- env:
|
|
|
- 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: snapshot
|
|
|
- command: pnpm run check:ci:snapshot
|
|
|
- gate_concurrency: '1'
|
|
|
- publint_concurrency: '8'
|
|
|
- coverage_max_workers: ''
|
|
|
- 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
|
|
|
|
|
|
@@ -245,12 +304,112 @@ jobs:
|
|
|
shell: pwsh
|
|
|
run: corepack enable
|
|
|
|
|
|
+ # Master refreshes the small cache that pull requests restore without
|
|
|
+ # putting package-store extraction back on the Windows critical path.
|
|
|
+ - uses: actions/cache@v4
|
|
|
+ with:
|
|
|
+ path: .cache/eslint
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
+ restore-keys: |
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-
|
|
|
+
|
|
|
+ - name: Install (immutable)
|
|
|
+ shell: pwsh
|
|
|
+ run: pnpm install --frozen-lockfile
|
|
|
+
|
|
|
+ - name: Run complete unsharded primary Node CI serially
|
|
|
+ shell: pwsh
|
|
|
+ env:
|
|
|
+ DSH_COVERAGE_MAX_WORKERS: '1'
|
|
|
+ DSH_E2E_MAX_WORKERS: '1'
|
|
|
+ DSH_ESLINT_CACHE: '1'
|
|
|
+ DSH_GATE_CONCURRENCY: '1'
|
|
|
+ DSH_PUBLINT_CONCURRENCY: '1'
|
|
|
+ DSH_SNAPSHOT_MAX_CONCURRENCY: '1'
|
|
|
+ run: pnpm run check:ci
|
|
|
+
|
|
|
+ # Manual, bounded comparison of the actual critical Linux and Windows lanes.
|
|
|
+ # The named pools are restricted at the organization level to this repository.
|
|
|
+ larger-runner-benchmark:
|
|
|
+ if: github.event_name == 'workflow_dispatch' && inputs.suite == 'larger-runner-benchmark'
|
|
|
+ runs-on: ${{ matrix.runner }}
|
|
|
+ timeout-minutes: 15
|
|
|
+ strategy:
|
|
|
+ fail-fast: false
|
|
|
+ max-parallel: 12
|
|
|
+ matrix:
|
|
|
+ include:
|
|
|
+ - platform: linux
|
|
|
+ cores: '4'
|
|
|
+ runner: dsh-ubuntu-24-04-4core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: linux
|
|
|
+ cores: '8'
|
|
|
+ runner: dsh-ubuntu-24-04-8core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: linux
|
|
|
+ cores: '16'
|
|
|
+ runner: dsh-ubuntu-24-04-16core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: linux
|
|
|
+ cores: '32'
|
|
|
+ runner: dsh-ubuntu-24-04-32core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: linux
|
|
|
+ cores: '64'
|
|
|
+ runner: dsh-ubuntu-24-04-64core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: linux
|
|
|
+ cores: '96'
|
|
|
+ runner: dsh-ubuntu-24-04-96core
|
|
|
+ workload: typecheck
|
|
|
+ - platform: windows
|
|
|
+ cores: '4'
|
|
|
+ runner: dsh-windows-2025-4core
|
|
|
+ workload: production-site
|
|
|
+ - platform: windows
|
|
|
+ cores: '8'
|
|
|
+ runner: dsh-windows-2025-8core
|
|
|
+ workload: production-site
|
|
|
+ - platform: windows
|
|
|
+ cores: '16'
|
|
|
+ runner: dsh-windows-2025-16core
|
|
|
+ workload: production-site
|
|
|
+ - platform: windows
|
|
|
+ cores: '32'
|
|
|
+ runner: dsh-windows-2025-32core
|
|
|
+ workload: production-site
|
|
|
+ - platform: windows
|
|
|
+ cores: '64'
|
|
|
+ runner: dsh-windows-2025-64core
|
|
|
+ workload: production-site
|
|
|
+ - platform: windows
|
|
|
+ cores: '96'
|
|
|
+ runner: dsh-windows-2025-96core
|
|
|
+ workload: production-site
|
|
|
+ steps:
|
|
|
+ - uses: actions/checkout@v6
|
|
|
+
|
|
|
+ - uses: actions/setup-node@v6
|
|
|
+ with:
|
|
|
+ node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
|
+
|
|
|
+ - name: Report runner capacity
|
|
|
+ run: >-
|
|
|
+ node -e "const os = require('node:os');
|
|
|
+ console.log(JSON.stringify({ arch: process.arch, cpus: os.cpus().length,
|
|
|
+ memoryGiB: Math.round(os.totalmem() / 2 ** 30) }))"
|
|
|
+
|
|
|
+ - name: Enable corepack (pnpm)
|
|
|
+ run: corepack enable
|
|
|
+
|
|
|
- name: Resolve pnpm store path
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
id: pnpm-store
|
|
|
- shell: pwsh
|
|
|
- run: '"path=$(pnpm store path --silent)" >> $env:GITHUB_OUTPUT'
|
|
|
+ run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
|
|
|
- uses: actions/cache@v4
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
with:
|
|
|
path: ${{ steps.pnpm-store.outputs.path }}
|
|
|
key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
|
@@ -258,26 +417,161 @@ jobs:
|
|
|
${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-
|
|
|
|
|
|
- name: Install (immutable)
|
|
|
- shell: pwsh
|
|
|
run: pnpm install --frozen-lockfile
|
|
|
|
|
|
+ - name: Run critical Linux typecheck lane
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
+ run: pnpm run typecheck
|
|
|
+
|
|
|
+ - name: Run critical Windows production-site lane
|
|
|
+ if: matrix.platform == 'windows'
|
|
|
+ run: pnpm run docs:build
|
|
|
+
|
|
|
+ # Manual comparison of the intended low-fanout topology. Linux runs the
|
|
|
+ # complete unsharded primary aggregate with bounded in-runner parallelism;
|
|
|
+ # Windows runs both blocking build surfaces concurrently through run-gates.
|
|
|
+ consolidated-runner-benchmark:
|
|
|
+ if: github.event_name == 'workflow_dispatch' && inputs.suite == 'consolidated-runner-benchmark'
|
|
|
+ runs-on: ${{ matrix.runner }}
|
|
|
+ timeout-minutes: 15
|
|
|
+ strategy:
|
|
|
+ fail-fast: false
|
|
|
+ max-parallel: 12
|
|
|
+ matrix:
|
|
|
+ include:
|
|
|
+ - platform: linux
|
|
|
+ cores: '4'
|
|
|
+ runner: dsh-ubuntu-24-04-4core
|
|
|
+ workers: '4'
|
|
|
+ - platform: linux
|
|
|
+ cores: '8'
|
|
|
+ runner: dsh-ubuntu-24-04-8core
|
|
|
+ workers: '8'
|
|
|
+ - platform: linux
|
|
|
+ cores: '16'
|
|
|
+ runner: dsh-ubuntu-24-04-16core
|
|
|
+ workers: '16'
|
|
|
+ - platform: linux
|
|
|
+ cores: '32'
|
|
|
+ runner: dsh-ubuntu-24-04-32core
|
|
|
+ workers: '32'
|
|
|
+ - platform: linux
|
|
|
+ cores: '64'
|
|
|
+ runner: dsh-ubuntu-24-04-64core
|
|
|
+ workers: '32'
|
|
|
+ - platform: linux
|
|
|
+ cores: '96'
|
|
|
+ runner: dsh-ubuntu-24-04-96core
|
|
|
+ workers: '32'
|
|
|
+ - platform: windows
|
|
|
+ cores: '4'
|
|
|
+ runner: dsh-windows-2025-4core
|
|
|
+ workers: '2'
|
|
|
+ - platform: windows
|
|
|
+ cores: '8'
|
|
|
+ runner: dsh-windows-2025-8core
|
|
|
+ workers: '2'
|
|
|
+ - platform: windows
|
|
|
+ cores: '16'
|
|
|
+ runner: dsh-windows-2025-16core
|
|
|
+ workers: '2'
|
|
|
+ - platform: windows
|
|
|
+ cores: '32'
|
|
|
+ runner: dsh-windows-2025-32core
|
|
|
+ workers: '2'
|
|
|
+ - platform: windows
|
|
|
+ cores: '64'
|
|
|
+ runner: dsh-windows-2025-64core
|
|
|
+ workers: '2'
|
|
|
+ - platform: windows
|
|
|
+ cores: '96'
|
|
|
+ runner: dsh-windows-2025-96core
|
|
|
+ workers: '2'
|
|
|
+ steps:
|
|
|
+ - uses: actions/checkout@v6
|
|
|
+
|
|
|
+ - uses: actions/setup-node@v6
|
|
|
+ with:
|
|
|
+ node-version: ${{ env.PRIMARY_NODE_VERSION }}
|
|
|
+
|
|
|
+ - name: Report runner capacity
|
|
|
+ run: >-
|
|
|
+ node -e "const os = require('node:os');
|
|
|
+ console.log(JSON.stringify({ arch: process.arch, cpus: os.cpus().length,
|
|
|
+ memoryGiB: Math.round(os.totalmem() / 2 ** 30) }))"
|
|
|
+
|
|
|
+ - name: Enable corepack (pnpm)
|
|
|
+ run: corepack enable
|
|
|
+
|
|
|
+ - name: Resolve pnpm store path (Linux)
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
+ id: pnpm-store-linux
|
|
|
+ run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"
|
|
|
+
|
|
|
+ - name: Resolve pnpm store path (Windows)
|
|
|
+ if: matrix.platform == 'windows'
|
|
|
+ id: pnpm-store-windows
|
|
|
+ shell: pwsh
|
|
|
+ run: '"path=$(pnpm store path --silent)" >> $env:GITHUB_OUTPUT'
|
|
|
+
|
|
|
+ - uses: actions/cache@v4
|
|
|
+ with:
|
|
|
+ path: ${{ steps.pnpm-store-linux.outputs.path || steps.pnpm-store-windows.outputs.path }}
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
|
|
|
+ restore-keys: |
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-
|
|
|
+
|
|
|
- uses: actions/cache@v4
|
|
|
- if: matrix.lane == 'lint'
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
with:
|
|
|
path: .cache/eslint
|
|
|
- key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
+ key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'tsconfig.json', 'packages/*/*/tsconfig.json', 'examples/*/tsconfig.json') }}
|
|
|
restore-keys: |
|
|
|
- ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-
|
|
|
+ ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-eslint-full-
|
|
|
+
|
|
|
+ - name: Install and prepare Linux
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
+ run: |
|
|
|
+ pnpm install --frozen-lockfile &
|
|
|
+ install_pid=$!
|
|
|
+ bash scripts/prepare-ci-bubblewrap.sh &
|
|
|
+ sandbox_pid=$!
|
|
|
+ install_status=0
|
|
|
+ wait "$install_pid" || install_status=$?
|
|
|
+ sandbox_status=0
|
|
|
+ wait "$sandbox_pid" || sandbox_status=$?
|
|
|
+ if (( install_status != 0 )); then exit "$install_status"; fi
|
|
|
+ exit "$sandbox_status"
|
|
|
+
|
|
|
+ - name: Install (immutable)
|
|
|
+ if: matrix.platform == 'windows'
|
|
|
+ shell: pwsh
|
|
|
+ run: pnpm install --frozen-lockfile
|
|
|
|
|
|
- - name: Run gates
|
|
|
+ - name: Run complete unsharded primary Node CI concurrently
|
|
|
+ if: matrix.platform == 'linux'
|
|
|
+ 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 }}
|
|
|
+ run: pnpm run check:ci
|
|
|
+
|
|
|
+ - name: Run blocking Windows builds concurrently
|
|
|
+ if: matrix.platform == 'windows'
|
|
|
shell: pwsh
|
|
|
- run: ${{ matrix.command }}
|
|
|
+ env:
|
|
|
+ DSH_GATE_CONCURRENCY: ${{ matrix.workers }}
|
|
|
+ run: pnpm run check:ci:windows-blocking
|
|
|
|
|
|
# Single stable required check for branch protection: require "all checks
|
|
|
# passed" instead of enumerating matrix legs whose names change as lanes and
|
|
|
# node versions evolve. Every blocking job in THIS workflow must be listed in
|
|
|
- # `needs`; explicitly observational jobs such as windows-gates stay out
|
|
|
- # (`needs` cannot reach across workflow files; e2e.yml stays its own check).
|
|
|
+ # `needs`; observational Windows gates share the required Windows job but are
|
|
|
+ # marked non-blocking inside run-gates. (`needs` cannot reach across workflow
|
|
|
+ # files; e2e.yml stays its own check.)
|
|
|
# `if: always()` is load-bearing: without it a failed dependency
|
|
|
# would SKIP this job, and GitHub counts a skipped required check as passing
|
|
|
# — so this job always runs and fails on any non-success result, including
|
|
|
@@ -285,8 +579,8 @@ jobs:
|
|
|
all-checks-passed:
|
|
|
name: all checks passed
|
|
|
runs-on: ubuntu-latest
|
|
|
- needs: [node-24, node-compat, python-sdk, windows-build]
|
|
|
- if: always()
|
|
|
+ needs: [node-24, node-compat, python-sdk, windows]
|
|
|
+ if: always() && 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')
|