Repository navigation
Speed up Windows app installs and foundation checks #14896
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| workflow_dispatch: | |
| env: | |
| PRIMARY_NODE_VERSION: "22.x" | |
| PNPM_VERSION: "9.15.0" | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.ref }}-${{ github.ref == 'refs/heads/main' && github.sha || 'latest' }} | |
| cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} | |
| jobs: | |
| windows-foundation: | |
| name: Windows host packages (Node 22.x) | |
| runs-on: blacksmith-4vcpu-windows-2025 | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@${{ env.PNPM_VERSION }} --ignore-scripts | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: windows-foundation | |
| turbo-cache: "true" | |
| turbo-cache-max-size-mb: "256" | |
| - name: Install foundation dependencies | |
| timeout-minutes: 5 | |
| shell: bash | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh --ignore-scripts --filter bb --filter "@bb/process-utils..." --filter "@bb/host-workspace..." --filter "@bb/host-watcher..." --filter "@bb/agent-runtime..." --filter "@bb/provider-bridge-protocol..." --filter "@bb/provider-bridge-acp..." --filter "@bb/host-daemon-contract..." --filter "@bb/config..." --filter "@bb/db..." --filter "bb-plugin-provider-acp..." --filter "bb-plugin-provider-codex..." --filter "bb-plugin-provider-claude-code..." --filter "bb-plugin-echo-provider..." --filter "@bb/app..." | |
| - name: Typecheck and test foundation packages | |
| shell: bash | |
| run: pnpm exec turbo run lint typecheck test --filter=@bb/process-utils --filter=@bb/host-workspace --filter=@bb/host-watcher --filter=@bb/agent-runtime --filter=@bb/provider-bridge-protocol --filter=@bb/provider-bridge-acp --filter=@bb/host-daemon-contract --filter=@bb/config --filter=@bb/db --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --continue --concurrency=2 --output-logs=new-only --summarize | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 256 --keep-run-summaries .turbo/runs | |
| windows-app-smoke: | |
| name: Windows app smoke (Node 22.x) | |
| runs-on: blacksmith-4vcpu-windows-2025 | |
| timeout-minutes: 40 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@${{ env.PNPM_VERSION }} --ignore-scripts | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: windows-app-smoke | |
| turbo-cache: "true" | |
| turbo-cache-max-size-mb: "256" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| shell: bash | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh --ignore-scripts | |
| - name: Build bb-app and boot it | |
| shell: bash | |
| run: pnpm exec turbo run smoke:boot --filter=bb-app --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Smoke test the bb-app tarball | |
| run: pnpm exec turbo run smoke:tarball --filter=bb-app --output-logs=new-only | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 256 | |
| windows-desktop-smoke: | |
| name: Windows desktop smoke (Node 22.x) | |
| runs-on: blacksmith-4vcpu-windows-2025 | |
| timeout-minutes: 40 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@${{ env.PNPM_VERSION }} --ignore-scripts | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: windows-desktop-smoke | |
| turbo-cache: "true" | |
| turbo-cache-max-size-mb: "256" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| shell: bash | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh --ignore-scripts | |
| - name: Package the desktop app | |
| env: | |
| CSC_IDENTITY_AUTO_DISCOVERY: "false" | |
| shell: bash | |
| run: pnpm exec turbo run package:win --filter=@bb/desktop --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Smoke test the packaged desktop app | |
| shell: bash | |
| run: pnpm exec turbo run smoke:packaged --filter=@bb/desktop --force --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 256 | |
| windows-tests: | |
| name: Windows tests (${{ matrix.shard }}, Node 22.x) | |
| runs-on: blacksmith-4vcpu-windows-2025 | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - shard: server-1 | |
| filter: --filter=@bb/server | |
| concurrency: 4 | |
| args: -- --shard=1/3 | |
| - shard: server-2 | |
| filter: --filter=@bb/server | |
| concurrency: 4 | |
| args: -- --shard=2/3 | |
| - shard: server-3 | |
| filter: --filter=@bb/server | |
| concurrency: 4 | |
| args: -- --shard=3/3 | |
| - shard: app-1 | |
| filter: --filter=@bb/app | |
| concurrency: 4 | |
| args: -- --shard=1/4 | |
| - shard: app-2 | |
| filter: --filter=@bb/app | |
| concurrency: 4 | |
| args: -- --shard=2/4 | |
| - shard: app-3 | |
| filter: --filter=@bb/app | |
| concurrency: 4 | |
| args: -- --shard=3/4 | |
| - shard: app-4 | |
| filter: --filter=@bb/app | |
| concurrency: 4 | |
| args: -- --shard=4/4 | |
| - shard: plugins-1 | |
| filter: --filter=bb-plugin-provider-* --filter=bb-plugin-tasks --filter=bb-plugin-connect --filter=bb-plugin-thread-list | |
| concurrency: 2 | |
| args: "" | |
| - shard: plugins-2 | |
| filter: --filter=bb-plugin-* --filter=!bb-plugin-provider-* --filter=!bb-plugin-tasks --filter=!bb-plugin-connect --filter=!bb-plugin-thread-list | |
| concurrency: 2 | |
| args: "" | |
| - shard: packages-host | |
| filter: --filter=@bb/host-daemon --filter=@bb/cli | |
| concurrency: 1 | |
| args: "" | |
| - shard: integration | |
| filter: --filter=@bb/integration-tests | |
| concurrency: 1 | |
| args: "" | |
| - shard: packages-build | |
| filter: --filter=@bb/templates --filter=bb-app --filter=@bb/demo-server --filter=@bb/desktop --filter=@bb/plugin-build | |
| concurrency: 2 | |
| args: "" | |
| - shard: packages-other | |
| filter: --filter=!@bb/server --filter=!@bb/app --filter=!bb-plugin-* --filter=!@bb/host-daemon --filter=!@bb/cli --filter=!@bb/integration-tests --filter=!@bb/templates --filter=!bb-app --filter=!@bb/demo-server --filter=!@bb/desktop --filter=!@bb/plugin-build --filter=!@bb/process-utils --filter=!@bb/host-workspace --filter=!@bb/host-watcher --filter=!@bb/agent-runtime --filter=!@bb/provider-bridge-protocol --filter=!@bb/provider-bridge-acp --filter=!@bb/host-daemon-contract --filter=!@bb/config --filter=!@bb/db | |
| concurrency: 2 | |
| args: "" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@${{ env.PNPM_VERSION }} --ignore-scripts | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: windows-test-${{ matrix.shard }} | |
| turbo-cache: "true" | |
| turbo-cache-max-size-mb: "256" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| shell: bash | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| APP_SHARD: ${{ startsWith(matrix.shard, 'app-') }} | |
| run: | | |
| filters=() | |
| if [[ "$APP_SHARD" == "true" ]]; then | |
| filters=(--filter bb --filter '@bb/app...' --filter '@bb/db...') | |
| fi | |
| bash .github/actions/setup-workspace/install-dependencies.sh --ignore-scripts "${filters[@]}" | |
| - name: Setup Bun | |
| if: ${{ matrix.shard == 'plugins-1' }} | |
| uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 | |
| with: | |
| bun-version: "1.3.14" | |
| no-cache: true | |
| - name: Test on Windows | |
| shell: cmd | |
| env: | |
| TEMP: ${{ runner.temp }} | |
| TMP: ${{ runner.temp }} | |
| run: | | |
| if not defined TURBO_CACHE_DIR set TURBO_CACHE_DIR=.turbo/cache | |
| pnpm exec turbo run test ${{ matrix.filter }} --cache-dir="%TURBO_CACHE_DIR%" --continue --output-logs=new-only --summarize --concurrency=${{ matrix.concurrency }} ${{ matrix.args }} | |
| - name: Upload test timings | |
| if: ${{ !cancelled() }} | |
| continue-on-error: true | |
| timeout-minutes: 1 | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: test-timings-windows-${{ matrix.shard }}-${{ github.run_attempt }} | |
| path: .turbo/runs/*.json | |
| include-hidden-files: true | |
| retention-days: 7 | |
| if-no-files-found: ignore | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 256 --keep-run-summaries .turbo/runs | |
| checks: | |
| name: Checks (ubuntu-latest, Node 22.x) | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| timeout-minutes: 30 | |
| # `actions: read` is what lets the cache-usage check call the Actions API; | |
| # checkout needs `contents: read`. The check degrades to a skip without | |
| # them, so this only makes the reporting reliable. | |
| permissions: | |
| contents: read | |
| actions: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Check source files for literal NUL bytes | |
| run: node scripts/check-source-nul.mjs | |
| - name: Setup workspace tools | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: checks | |
| turbo-cache: "true" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| # Four tasks for four vCPUs: TypeScript 7 and esbuild are multi-threaded, | |
| # so turbo's default of ten concurrent tasks only adds contention here. | |
| # Measured pinned to 4 CPUs, two rounds each: 96 s / 110 s at the | |
| # default vs 90 s / 58 s at four. | |
| - name: Build, typecheck, and lint | |
| run: pnpm exec turbo run build typecheck lint --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only --summarize --concurrency=4 | |
| # Runs after build and typecheck, so the guard's own turbo build is a | |
| # cache hit and the package it packs is the one this commit really ships. | |
| # A published version whose packed files or consumer-facing manifest | |
| # fields changed is a hard failure; an unreachable registry or a failed | |
| # local pack (exit 2) is infrastructure, not a finding. | |
| - name: Check plugin SDK npm version guard | |
| run: | | |
| # +e so the exit code can be inspected: GitHub's default shell runs | |
| # with -e, which would abort the step before the exit-2 check. | |
| set +e | |
| node packages/plugin-sdk/scripts/check-npm-version-guard.mjs | |
| guard_exit=$? | |
| set -e | |
| if [[ "$guard_exit" -eq 2 ]]; then | |
| echo "::warning::Skipping the plugin SDK npm version guard: the npm registry was unreachable." | |
| exit 0 | |
| fi | |
| exit "$guard_exit" | |
| # Guards the JavaScript that blocks first paint in the web app, and the | |
| # thread route's static closure that blocks first thread paint. Heavy | |
| # editor, diff and math code reaches those paths through barrel | |
| # re-exports, which typecheck and lint cannot see. | |
| - name: Check app bundle budgets | |
| run: node apps/app/scripts/check-bundle-budget.mjs | |
| # Provider-literal ratchet (G1 of the provider-plugin migration): | |
| # core must never gain a new provider-id carve-out; the per-file | |
| # baseline may only shrink. See docs/provider-plugin-api.md. | |
| - name: Check provider-literal ratchet | |
| run: | | |
| git fetch --depth=1 origin "${{ github.base_ref || github.event.repository.default_branch }}" || true | |
| node scripts/check-provider-literal-ratchet.mjs --base "origin/${{ github.base_ref || github.event.repository.default_branch }}" | |
| # Exceeding the Actions cache quota is silent: GitHub evicts entries | |
| # without failing or warning anything, so the only symptom is caches | |
| # quietly ceasing to hit. Warn while there is still headroom. | |
| - name: Check Actions cache usage | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| run: node scripts/check-actions-cache-usage.mjs | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 | |
| # Tests run on their own runners instead of inside the checks job: the big | |
| # suites are CPU-bound and previously fought each other (and the builds) for | |
| # the same 4 vCPUs, which made tests the critical path of every run. | |
| tests: | |
| name: Tests (${{ matrix.shard }}, ubuntu-latest, Node 22.x) | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - shard: server-1 | |
| filter: --filter=@bb/server | |
| args: --shard=1/2 | |
| - shard: server-2 | |
| filter: --filter=@bb/server | |
| args: --shard=2/2 | |
| # @bb/app is by far the largest suite (365 files) and was the critical | |
| # path once the macOS smoke leg was fixed. Vitest splits by file, and | |
| # Turbo hashes passthrough args, so each leg is a distinct cache entry | |
| # rather than three jobs racing to reuse one. | |
| - shard: app-1 | |
| filter: --filter=@bb/app | |
| args: --shard=1/3 | |
| - shard: app-2 | |
| filter: --filter=@bb/app | |
| args: --shard=2/3 | |
| - shard: app-3 | |
| filter: --filter=@bb/app | |
| args: --shard=3/3 | |
| - shard: integration | |
| filter: --filter=@bb/integration-tests | |
| args: "" | |
| - shard: plugins | |
| filter: --filter='bb-plugin-*' | |
| args: "" | |
| - shard: packages-host | |
| filter: --filter=@bb/host-daemon --filter=@bb/cli --filter=@bb/agent-runtime --filter=@bb/provider-parity --filter=@bb/db | |
| args: "" | |
| - shard: packages-build | |
| filter: --filter=@bb/templates --filter=bb-app --filter=@bb/demo-server --filter=@bb/desktop --filter=@bb/plugin-build | |
| args: "" | |
| - shard: packages-other | |
| filter: --filter='!@bb/server' --filter='!@bb/app' --filter='!@bb/integration-tests' --filter='!bb-plugin-*' --filter='!@bb/host-daemon' --filter='!@bb/cli' --filter='!@bb/agent-runtime' --filter='!@bb/provider-parity' --filter='!@bb/db' --filter='!@bb/templates' --filter='!bb-app' --filter='!@bb/demo-server' --filter='!@bb/desktop' --filter='!@bb/plugin-build' | |
| args: "" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup workspace tools | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: test-${{ matrix.shard }} | |
| turbo-cache: "true" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| - name: Setup Bun | |
| if: ${{ startsWith(matrix.shard, 'packages-') || matrix.shard == 'plugins' }} | |
| uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 | |
| with: | |
| bun-version: "1.3.14" | |
| no-cache: true | |
| - name: Install Electron runtime libraries | |
| if: ${{ matrix.shard == 'packages-build' }} | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y xvfb libgtk-3-0t64 libnss3 libatk1.0-0t64 libatk-bridge2.0-0t64 libcups2t64 libdrm2 libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2t64 | |
| ELECTRON_RUN_AS_NODE=1 pnpm --filter @bb/desktop exec electron --version | |
| - name: Test | |
| run: ${{ matrix.shard == 'packages-build' && 'xvfb-run -a' || '' }} pnpm exec turbo run test ${{ matrix.filter }} --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only --summarize --concurrency=4 -- --maxWorkers=2 ${{ matrix.args }} | |
| - name: Upload test timings | |
| if: ${{ !cancelled() }} | |
| continue-on-error: true | |
| timeout-minutes: 1 | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a | |
| with: | |
| name: test-timings-${{ matrix.shard }}-${{ github.run_attempt }} | |
| path: .turbo/runs/*.json | |
| include-hidden-files: true | |
| retention-days: 7 | |
| if-no-files-found: ignore | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 | |
| # Every other suite mocks the Agent SDK, so an upstream CLI release that | |
| # breaks the model probe passes CI silently. This runs it against a real, | |
| # unpinned CLI. | |
| # TODO: cover the npm build, macOS, and the full `test:integration` suite. | |
| plugin-forks: | |
| name: Plugin Fork Check (${{ matrix.shard }}, ubuntu-latest, Node 22.x) | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| timeout-minutes: 20 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard: [1, 2, 3] | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Select forkable plugins | |
| id: selection | |
| continue-on-error: true | |
| timeout-minutes: 2 | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: | | |
| if [[ -n "$BASE_SHA" ]]; then | |
| git fetch --no-tags --depth=1 origin "$BASE_SHA" || true | |
| fi | |
| selection=$(node scripts/check-plugin-forks.mjs --changed-from="$BASE_SHA" --shard=${{ matrix.shard }}/3 --list) | |
| echo "count=$(node -e 'console.log(JSON.parse(process.argv[1]).length)' "$selection")" >> "$GITHUB_OUTPUT" | |
| echo "Forkable plugins: $selection" >> "$GITHUB_STEP_SUMMARY" | |
| - name: Setup workspace tools | |
| if: steps.selection.outputs.count != '0' | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| if: steps.selection.outputs.count != '0' | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: plugin-forks-${{ matrix.shard }} | |
| turbo-cache: "true" | |
| - name: Install dependencies | |
| if: steps.selection.outputs.count != '0' | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| - name: Setup Bun | |
| if: steps.selection.outputs.count != '0' | |
| uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 | |
| with: | |
| bun-version: "1.3.14" | |
| no-cache: true | |
| - name: Build, typecheck, and test forkable plugins outside the workspace | |
| if: steps.selection.outputs.count != '0' | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha }} | |
| run: node scripts/check-plugin-forks.mjs --changed-from="$BASE_SHA" --shard=${{ matrix.shard }}/3 | |
| - name: Bound saved Turbo cache | |
| if: steps.selection.outputs.count != '0' | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 | |
| provider-model-listing: | |
| name: Provider Model Listing | |
| runs-on: blacksmith-4vcpu-ubuntu-2404 | |
| timeout-minutes: 20 | |
| # Fork pull requests cannot read secrets, so the probe would fail | |
| # unauthenticated for reasons unrelated to bb. | |
| if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup workspace tools | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ env.PRIMARY_NODE_VERSION }} | |
| cache-prefix: test-provider-model-listing | |
| turbo-cache: "true" | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| # The native build: bb resolves `claude` from PATH and `~/.local/bin`, | |
| # so this is the binary most users run. | |
| - name: Install Claude Code CLI | |
| run: | | |
| curl -fsSL https://claude.ai/install.sh | bash | |
| echo "$HOME/.local/bin" >> "$GITHUB_PATH" | |
| - name: Show Claude Code version | |
| run: claude --version | |
| # Fails here, where the cause is obvious, rather than inside the probe. | |
| - name: Check Claude Code credential | |
| env: | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| run: | | |
| if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then | |
| echo "CLAUDE_CODE_OAUTH_TOKEN is unset; mint one with 'claude setup-token'." >&2 | |
| exit 1 | |
| fi | |
| # `--force`: the input that moves here is the upstream CLI, which Turbo | |
| # does not hash. | |
| - name: Probe Claude Code model listing | |
| env: | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| run: pnpm exec turbo run test:integration --filter=@bb/agent-runtime --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only --force -- -t "claude-code provider lists models" | |
| - name: Bound saved Turbo cache | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 | |
| # The macOS legs run without the Turbo cache. Blacksmith's transparent cache | |
| # only backs their Linux runners, so on macOS the cache moves over GitHub's | |
| # own service at ~50 MB/s: restoring and saving the ~2 GB directory cost about | |
| # two minutes per run and returned 0 of 8 task hits, because the six ~2 GB | |
| # entries it wrote also blew past the repository's 10 GB cache quota and | |
| # evicted each other. `smoke:tarball` is itself `"cache": false`, so only its | |
| # build dependencies could ever have been reused. | |
| package-smoke: | |
| name: Package Smoke (${{ matrix.os }}, Node ${{ matrix.node-version }}) | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: blacksmith-4vcpu-ubuntu-2404 | |
| node-version: "22.x" | |
| turbo-cache: "true" | |
| - os: blacksmith-6vcpu-macos-15 | |
| node-version: "22.x" | |
| turbo-cache: "false" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup workspace tools | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| cache-prefix: package-smoke | |
| turbo-cache: ${{ matrix.turbo-cache }} | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| - name: Smoke bb-app tarball | |
| run: pnpm exec turbo run smoke:tarball --filter=bb-app --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Install AppImage FUSE runtime | |
| if: ${{ runner.os == 'Linux' }} | |
| uses: ./.github/actions/install-appimage-fuse | |
| timeout-minutes: 5 | |
| with: | |
| package: libfuse2t64 | |
| - name: Package Linux AppImage | |
| if: ${{ runner.os == 'Linux' }} | |
| run: pnpm exec turbo run desktop:build:linux --filter=@bb/desktop --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Smoke Linux AppImage mount lifecycle | |
| if: ${{ runner.os == 'Linux' }} | |
| run: xvfb-run -a pnpm exec turbo run smoke:appimage-lifecycle --filter=@bb/desktop --force --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Bound saved Turbo cache | |
| if: matrix.turbo-cache == 'true' | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 | |
| node-compat-smoke: | |
| name: Node Compatibility Smoke (${{ matrix.os }}, Node ${{ matrix.node-version }}) | |
| if: ${{ github.event_name != 'pull_request' }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: blacksmith-4vcpu-ubuntu-2404 | |
| node-version: "24.x" | |
| turbo-cache: "true" | |
| - os: blacksmith-4vcpu-ubuntu-2404 | |
| node-version: "26.x" | |
| turbo-cache: "true" | |
| - os: blacksmith-6vcpu-macos-15 | |
| node-version: "24.x" | |
| turbo-cache: "false" | |
| - os: blacksmith-6vcpu-macos-15 | |
| node-version: "26.x" | |
| turbo-cache: "false" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Setup workspace tools | |
| uses: ./.github/actions/setup-workspace-tools | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| pnpm-version: ${{ env.PNPM_VERSION }} | |
| - name: Restore workspace caches | |
| id: cache | |
| timeout-minutes: 1 | |
| continue-on-error: true | |
| uses: ./.github/actions/cache-workspace | |
| with: | |
| node-version: ${{ matrix.node-version }} | |
| cache-prefix: compat-smoke | |
| turbo-cache: ${{ matrix.turbo-cache }} | |
| - name: Install dependencies | |
| timeout-minutes: 5 | |
| env: | |
| CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }} | |
| run: bash .github/actions/setup-workspace/install-dependencies.sh | |
| - name: Smoke bb-app tarball | |
| run: pnpm exec turbo run smoke:tarball --filter=bb-app --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only | |
| - name: Bound saved Turbo cache | |
| if: matrix.turbo-cache == 'true' | |
| run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 |