Skip to content

Add opt-in Storage & retention with durable cleanup #14941

Add opt-in Storage & retention with durable cleanup

Add opt-in Storage & retention with durable cleanup #14941

Workflow file for this run

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:
plan:
name: Select CI checks
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 5
permissions:
contents: read
outputs:
selection: ${{ steps.select.outputs.selection }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
fetch-depth: 2
- name: Check source files for literal NUL bytes
run: node scripts/check-source-nul.mjs
- name: Select affected checks
id: select
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
selection=$(node scripts/plan-ci.mjs --full)
if [[ -n "$BASE_SHA" ]]; then
if git fetch --no-tags --depth=1 origin "$BASE_SHA" && npx --yes turbo@2.10.12 query affected --base "$BASE_SHA" --head HEAD > "$RUNNER_TEMP/ci-affected.json"; then
selection=$(node scripts/plan-ci.mjs --base "$BASE_SHA" --affected "$RUNNER_TEMP/ci-affected.json")
else
echo "::warning::Change detection failed; running full CI."
fi
fi
echo "selection=$selection" >> "$GITHUB_OUTPUT"
echo "$selection" >> "$GITHUB_STEP_SUMMARY"
- name: Check provider-literal ratchet
env:
BASE_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }}
run: |
git fetch --no-tags --depth=1 origin "$BASE_BRANCH" || true
node scripts/check-provider-literal-ratchet.mjs --base "origin/$BASE_BRANCH"
windows-foundation:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).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:
TURBO_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:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).packaging }}
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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
shell: bash
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).packaging }}
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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
shell: bash
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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)
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection)['windows-tests'].include[0] != null }}
runs-on: blacksmith-4vcpu-windows-2025
timeout-minutes: 30
permissions:
contents: read
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.plan.outputs.selection)['windows-tests'] }}
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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
shell: bash
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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
static-checks:
name: Lint and typecheck (ubuntu-latest, Node 22.x)
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).staticNeeded }}
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 20
permissions:
contents: read
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: static-checks
turbo-cache: "true"
- name: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-cache.outcome }}
run: bash .github/actions/setup-workspace/install-dependencies.sh
- name: Lint and typecheck
run: pnpm exec turbo run lint typecheck ${{ fromJSON(needs.plan.outputs.selection).staticFilters }} --cache-dir="${TURBO_CACHE_DIR:-.turbo/cache}" --output-logs=new-only --summarize --concurrency=4
- name: Bound saved Turbo cache
run: node scripts/prune-turbo-cache.mjs --dir .turbo/cache --max-size-mb 1024 --keep-run-summaries .turbo/runs
checks:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).buildNeeded }}
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: 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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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
run: pnpm exec turbo run build ${{ fromJSON(needs.plan.outputs.selection).buildFilters }} --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
if: ${{ fromJSON(needs.plan.outputs.selection).sdkBuild }}
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
if: ${{ fromJSON(needs.plan.outputs.selection).appBuild }}
run: node apps/app/scripts/check-bundle-budget.mjs
# 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)
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection)['tests'].include[0] != null }}
runs-on: blacksmith-4vcpu-ubuntu-2404
timeout-minutes: 30
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.plan.outputs.selection)['tests'] }}
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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-cache.outcome }}
APP_SHARD: ${{ startsWith(matrix.shard, 'app-') }}
DEMO_ONLY: ${{ matrix.filter == '--filter=@bb/demo-server' }}
run: |
filters=()
if [[ "$APP_SHARD" == "true" ]]; then
filters=(--ignore-scripts --filter bb --filter '@bb/app...' --filter '@bb/db...')
elif [[ "$DEMO_ONLY" == "true" ]]; then
filters=(--ignore-scripts --filter bb --filter '@bb/demo-server...' --filter '@bb/db...')
fi
bash .github/actions/setup-workspace/install-dependencies.sh "${filters[@]}"
- 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: ${{ contains(matrix.filter, '--filter=@bb/desktop') }}
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: ${{ contains(matrix.filter, '--filter=@bb/desktop') && '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:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
if: steps.selection.outputs.count != '0'
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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:
needs: plan
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: ${{ fromJSON(needs.plan.outputs.selection).providers && (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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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:
needs: plan
if: ${{ fromJSON(needs.plan.outputs.selection).packaging }}
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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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: Restore pnpm cache
if: runner.os == 'macOS'
id: pnpm-cache
timeout-minutes: 1
continue-on-error: true
uses: ./.github/actions/cache-pnpm
- name: Install dependencies
timeout-minutes: 5
env:
TURBO_CACHE_RESTORE_OUTCOME: ${{ steps.cache.outcome }}
PNPM_CACHE_RESTORE_OUTCOME: ${{ steps.pnpm-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