Repository navigation
Remove surface gate; fix Anthropic/OpenAI capability, AgentTask retry/budget, FetchUrl error leak #3663
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
| # Every `setup-bun` here takes `latest`, deliberately. The suites are what this | |
| # repository ships against a moving runtime: `bunfig.toml`'s compatibility shim | |
| # is written against the gaps in Bun's own `vitest` shim and each of its guards | |
| # is meant to stand down once Bun ships its own, which only running a new Bun | |
| # can ever reveal. `engines` already states the floor (`bun >= 1.4.0`, where | |
| # `node:sqlite` arrives) and `latest` is always above it. | |
| # | |
| # The cost is real and accepted: a Bun regression can redden every PR on a day | |
| # nobody touched the code. That is the trade — finding out on the day Bun ships | |
| # it, rather than at the next manual bump. One spelling in every job, so there | |
| # is no version to keep in sync; `packageManager` still pins local installs. | |
| # | |
| # Coverage is NOT collected here. Every vitest job below runs one slice of the | |
| # suite, so a per-job number only means something once the fragments are merged | |
| # — an artifact per job, a merge job and a cleanup job, paid for on every push. | |
| # The nightly workflow runs the suite in one job and reports it instead. | |
| name: Build & Test | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.head.ref || (github.event_name == 'workflow_dispatch' && github.run_id || github.ref_name) }} | |
| cancel-in-progress: true | |
| env: | |
| CI: "true" | |
| DO_NOT_TRACK: "1" | |
| TURBO_TELEMETRY_DISABLED: "1" | |
| # PRs: only packages the change can reach. Push/dispatch: full suite. | |
| TEST_CHANGED: ${{ github.event_name == 'pull_request' && format('--changed {0}', github.event.pull_request.base.sha) || '' }} | |
| jobs: | |
| typecheck-budget: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| # Fails the PR if any package's type-instantiation count grows past its | |
| # committed budget (scripts/typecheck-budget.json). Re-baseline intentional | |
| # growth with: bun run typecheck:budget --update | |
| - name: Typecheck budget guard | |
| run: bun run typecheck:budget | |
| # Co-located `__tests__` are excluded from each package's build program so | |
| # they never reach `dist`, which also takes them out of every tsc run. | |
| # `tsconfig.test.json` is the program that still checks them; without this | |
| # step a type error in a test file is invisible until someone runs it. | |
| # Must follow the budget guard, which is what emits the `dist/*.d.ts` these | |
| # programs resolve their own package against. | |
| - name: Typecheck co-located tests | |
| run: bun run typecheck:tests | |
| test-discovery: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| # Fails if any test file is unreachable by section+kind selection. Every | |
| # other job passes a kind, so an unreachable file silently never runs. | |
| - name: Test discovery guard | |
| run: bun scripts/test.ts --check-sections | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| # The only thing that runs oxlint under CI. `prepare` skips husky when $CI | |
| # is set, so the pre-commit hook -- which `--no-verify` bypasses anyway -- | |
| # is otherwise oxlint's sole invoker, and the `error`-level rules in | |
| # .oxlintrc.json can never fail a build. | |
| # | |
| # Still not `needs: build`, but no longer because nothing reads types: the | |
| # `lint` script builds them itself (turbo-cached `build:types`), because | |
| # `--type-aware` resolves cross-package imports through `dist/*.d.ts` and | |
| # types every one of them as `any` when they are missing -- so tsgolint | |
| # silently finds nothing rather than failing. | |
| - name: Lint | |
| run: bun run lint | |
| # `format-check` had no CI invoker at all -- `prepare` skips husky when | |
| # $CI is set, so the pre-commit hook was its only one, and `--no-verify` | |
| # walks around that. Cheap, and the tree is clean today. | |
| - name: Format check | |
| run: bun run format-check | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - run: bun run build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: build-output | |
| path: | | |
| packages/*/dist/** | |
| providers/*/dist/** | |
| examples/*/dist/** | |
| retention-days: 1 | |
| # Sharded, and it is the only job here that is. The unit slice is ~700 files | |
| # and ran four times the wall clock of every other job in this workflow, so | |
| # the run finished when this job did and nothing else on the board mattered. | |
| # Most of that is not test execution: vitest accounts the slice as ~51% setup | |
| # (a fresh module registry per file, `vitest.setup.ts` bootstrapping the task | |
| # registry into each), ~21% transform, ~5% import and ~22% tests — so ~78% is | |
| # paid per FILE, and dividing the file list divides it. Measured 2.9x across | |
| # four shards rather than 4x because transform is the part that does not | |
| # shrink: it is mostly the shared module graph, which every shard still pays | |
| # in full. `scripts/lib/testShards.ts` does the partition and says why it is | |
| # dealt from a sorted list rather than sliced. | |
| # | |
| # `fail-fast: false` because the shards are one job's worth of tests split up: | |
| # cancelling the rest on the first red one would report a fraction of the | |
| # failures and send someone back for a second full run to see the others. | |
| test-vitest-unit: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # `i/N` verbatim, so the count lives in one place and the job name | |
| # reads as the shard it ran. | |
| shard: ["1/4", "2/4", "3/4", "4/4"] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| # An empty shard passes: `--changed` narrows a pull request to a handful | |
| # of files, and the shards past the first then hold none of them. | |
| - name: Run unit tests via vitest (shard ${{ matrix.shard }}) | |
| run: bun run test:vitest:unit -- --shard ${{ matrix.shard }} ${{ env.TEST_CHANGED }} | |
| test-vitest-integration: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| - name: Run integration tests via vitest | |
| env: | |
| WORKGLOW_SECRETS_PASSPHRASE: ${{ secrets.WORKGLOW_SECRETS_PASSPHRASE }} | |
| run: bun run test:vitest:integration -- ${{ env.TEST_CHANGED }} | |
| test-vitest-rag: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| timeout-minutes: 25 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Cache Hugging Face model downloads | |
| uses: actions/cache@v4 | |
| with: | |
| path: models | |
| key: hf-models-rag-${{ runner.os }}-${{ hashFiles('packages/test/src/samples/**') }} | |
| restore-keys: | | |
| hf-models-rag-${{ runner.os }}- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| - name: Run rag tests via vitest | |
| env: | |
| WORKGLOW_SECRETS_PASSPHRASE: ${{ secrets.WORKGLOW_SECRETS_PASSPHRASE }} | |
| run: bun run test:vitest:rag -- ${{ env.TEST_CHANGED }} | |
| test-vitest-ai-provider-hft: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Cache Hugging Face model downloads | |
| uses: actions/cache@v4 | |
| with: | |
| path: models | |
| key: hf-models-hft-${{ runner.os }}-${{ hashFiles('packages/test/src/samples/**') }} | |
| restore-keys: | | |
| hf-models-hft-${{ runner.os }}- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| - name: Run HuggingFace Transformers provider tests via vitest | |
| env: | |
| WORKGLOW_SECRETS_PASSPHRASE: ${{ secrets.WORKGLOW_SECRETS_PASSPHRASE }} | |
| run: bun run test:vitest:ai-provider-hft -- ${{ env.TEST_CHANGED }} | |
| test-vitest-ai-provider-nodellama: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Cache Hugging Face / GGUF model downloads | |
| uses: actions/cache@v4 | |
| with: | |
| path: models | |
| key: hf-models-nodellama-${{ runner.os }}-${{ hashFiles('packages/test/src/samples/**') }} | |
| restore-keys: | | |
| hf-models-nodellama-${{ runner.os }}- | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| - name: Run LlamaCpp provider tests via vitest | |
| env: | |
| WORKGLOW_SECRETS_PASSPHRASE: ${{ secrets.WORKGLOW_SECRETS_PASSPHRASE }} | |
| run: bun run test:vitest:ai-provider-nodellama -- ${{ env.TEST_CHANGED }} | |
| test-vitest-ai-provider-api: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - run: bun i | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: build-output | |
| path: . | |
| - name: Run API provider tests via vitest | |
| env: | |
| WORKGLOW_SECRETS_PASSPHRASE: ${{ secrets.WORKGLOW_SECRETS_PASSPHRASE }} | |
| run: bun run test:vitest:ai-provider-api -- ${{ env.TEST_CHANGED }} | |
| cleanup: | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| test-vitest-unit, | |
| test-vitest-integration, | |
| test-vitest-rag, | |
| test-vitest-ai-provider-hft, | |
| test-vitest-ai-provider-nodellama, | |
| test-vitest-ai-provider-api, | |
| ] | |
| steps: | |
| - name: Delete build artifacts | |
| uses: geekyeggo/delete-artifact@v6 | |
| with: | |
| name: build-output |