Skip to content

Commit 79d04d3

Browse files
github-actions[bot]lforstQardclaudeStephen Belanger
authored
chore: Prepare for release (e2d66a3) (#2008)
Prepares a release by updating changelogs and package versions, and synchronizing everything to the release branch. --------- Co-authored-by: Luca Forstner <luca.forstner@gmail.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Stephen Belanger <admin@stephenbelanger.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Stephen Belanger <stephenbelanger@s-belanger.localdomain> Co-authored-by: Dan Lee <dan@braintrustdata.com> Co-authored-by: braintrust-bot[bot] <215900051+braintrust-bot[bot]@users.noreply.github.com> Co-authored-by: Cedric / ViaDézo1er <viadezo1er@viarezo.fr> Co-authored-by: Olmo Maldonado <olmo@braintrustdata.com> Co-authored-by: Abhijeet Prasad <abhijeet@braintrustdata.com> Co-authored-by: ekeith <55766816+evanmkeith@users.noreply.github.com> Co-authored-by: Ronald Koh <ronald9872@gmail.com>
1 parent ecaee2e commit 79d04d3

488 files changed

Lines changed: 100542 additions & 22715 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/e2e-tests/SKILL.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,33 @@ Run workspace scripts from the repo root when you want the standard e2e entrypoi
3131

3232
```bash
3333
pnpm run test:e2e
34-
pnpm run test:e2e:hermetic # only run tests that don't rely on external services or llm providers
35-
pnpm run test:e2e:update # updates snapshots
34+
pnpm run test:e2e:record # re-record provider cassettes and update snapshots
3635
```
3736

3837
Try not to use specific test narrowing commands unless hunting down a very nasty and specific bug.
3938

39+
## Cassettes
40+
41+
Cassettes mock provider HTTP responses (OpenAI, Anthropic, ...) so external-provider scenarios replay in CI without provider keys. The harness starts a local `@braintrust/seinfeld` cassette server and points provider SDK base URL env vars at that server, so subprocesses and SDK-launched binaries are covered too.
42+
43+
- External-provider tests should thread `runContext: { variantKey: "...", originalScenarioDir }` into the scenario runner. In normal replay mode, missing cassette entries fail loudly instead of skipping or falling back to live providers. In `record` / `record-missing` mode, they run so new cassettes can be authored.
44+
- Thread `runContext: { variantKey: "...", originalScenarioDir }` into `runScenarioDir`/`runNodeScenarioDir`. Cassettes live at `e2e/scenarios/<name>/__cassettes__/<variantKey>.cassette.json` (parallel to `__snapshots__/`). Only set `runContext.cassette` explicitly for unusual cases, such as `cassette: false` on a non-provider mode inside an otherwise provider-backed scenario.
45+
- To re-record after changing a scenario:
46+
47+
```bash
48+
ANTHROPIC_API_KEY=... OPENAI_API_KEY=... \
49+
pnpm --filter=@braintrust/js-e2e-tests run test:e2e:record -- scenarios/<name>/scenario.test.ts
50+
```
51+
52+
Then run again in `BRAINTRUST_E2E_CASSETTE_MODE=replay` with no provider keys to confirm the cassette is sufficient.
53+
54+
- Volatile fields in request bodies (e.g. AI-SDK `experimental_generateMessageId`) need a per-scenario filter. Add or update `<scenario-dir>/cassette-filter.mjs` with a named `filter` export. The cassette server loads that filter through `withScenarioHarness(...)`.
55+
- **After recording, always inspect the cassette for leaked API keys before committing.** The recorder redacts common patterns (`paranoid` preset), but confirm that no real keys appear in request headers, response bodies, or any URL query parameters. If a key slips through, remove the cassette, add a custom `redact` rule, and re-record.
56+
4057
## Preferred Patterns
4158

4259
- Keep the expensive setup at module scope with `prepareScenarioDir(...)`. Only call `installScenarioDependencies(...)` directly when you are testing installer behavior or need a nonstandard setup.
4360
- Run every scenario through `withScenarioHarness(...)`.
44-
- Tag every test with exactly one tag from `e2e/helpers/tags.ts`.
4561
- Keep reusable logic in `e2e/helpers/`. Keep one-off fixtures and scenario-specific files inside the scenario directory.
4662
- Snapshot stable contracts, not raw noise. Use `normalizeForSnapshot(...)` before inline snapshots and `formatJsonFileSnapshot(...)` plus file snapshots for larger payloads or version matrices.
4763
- When a scenario family already has `assertions.ts`, keep version- or provider-specific test setup in `scenario.test.ts` and reuse the shared assertions file.
@@ -73,5 +89,5 @@ pnpm install --dir e2e/scenarios/<name> --ignore-workspace --lockfile-only --str
7389

7490
- Flaky snapshot: normalize the changing field instead of snapshotting around it.
7591
- Request-flow assertions: grab `requestCursor()` before running the scenario, then inspect `requestsAfter(...)`.
76-
- If the scenario is external-provider backed, confirm the required provider env var is set before debugging the assertions.
92+
- If the scenario is external-provider backed, first confirm it has a cassette or run in `BRAINTRUST_E2E_CASSETTE_MODE=record` with the required provider env var set.
7793
- Deno/browser scenarios may intentionally differ from Node. Assert the real runtime contract instead of copying Node expectations blindly.

.github/workflows/checks.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ jobs:
143143
path: js/artifacts/*.tgz
144144
retention-days: 1
145145

146-
e2e-hermetic:
146+
e2e:
147147
runs-on: ubuntu-latest
148148
timeout-minutes: 30
149149
steps:
@@ -158,8 +158,8 @@ jobs:
158158
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
159159
- name: Install dependencies
160160
run: pnpm install --frozen-lockfile
161-
- name: Run hermetic e2e tests
162-
run: pnpm run test:e2e:hermetic
161+
- name: Run e2e tests
162+
run: pnpm run test:e2e
163163

164164
js-api-compatibility:
165165
runs-on: ubuntu-latest
@@ -458,7 +458,7 @@ jobs:
458458
- ensure-pinned-actions
459459
- js-test
460460
- js-build
461-
- e2e-hermetic
461+
- e2e
462462
- js-smoke-discover
463463
- js-smoke-test
464464
- temporal-js
@@ -490,7 +490,7 @@ jobs:
490490
check_result "ensure-pinned-actions" "${{ needs.ensure-pinned-actions.result }}"
491491
check_result "js-test" "${{ needs.js-test.result }}"
492492
check_result "js-build" "${{ needs.js-build.result }}"
493-
check_result "e2e-hermetic" "${{ needs.e2e-hermetic.result }}"
493+
check_result "e2e" "${{ needs.e2e.result }}"
494494
check_result "js-smoke-discover" "${{ needs.js-smoke-discover.result }}"
495495
check_result "js-smoke-test" "${{ needs.js-smoke-test.result }}"
496496
check_result "temporal-js" "${{ needs.temporal-js.result }}"

.github/workflows/e2e-canary.yaml

Lines changed: 0 additions & 84 deletions
This file was deleted.

.github/workflows/integration-tests.yaml

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ on:
44
pull_request:
55
paths:
66
- "js/**"
7-
- "e2e/**"
87
- ".github/workflows/integration-tests.yaml"
98
- "package.json"
109
- "pnpm-lock.yaml"
@@ -49,83 +48,3 @@ jobs:
4948
working-directory: js
5049
shell: bash
5150
run: pnpm run test:external
52-
53-
e2e:
54-
runs-on: ubuntu-latest
55-
timeout-minutes: 45
56-
env:
57-
BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }}
58-
BRAINTRUST_E2E_PROJECT_NAME: ${{ vars.BRAINTRUST_E2E_PROJECT_NAME }}
59-
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
60-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
61-
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
62-
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
63-
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
64-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
65-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
66-
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
67-
HUGGINGFACE_API_KEY: ${{ secrets.HUGGINGFACE_API_KEY }}
68-
steps:
69-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
70-
- uses: denoland/setup-deno@ff4860f9d7236f320afa0f82b7e6457384805d05 # v2.0.4
71-
with:
72-
deno-version-file: .tool-versions
73-
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
74-
with:
75-
node-version-file: .tool-versions
76-
- name: Setup pnpm
77-
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
78-
- name: Install dependencies
79-
run: pnpm install --frozen-lockfile
80-
- name: Prepare e2e run context directory
81-
id: run_context
82-
shell: bash
83-
run: |
84-
RUN_CONTEXT_DIR="$(mktemp -d)"
85-
echo "dir=$RUN_CONTEXT_DIR" >> "$GITHUB_OUTPUT"
86-
- name: Run e2e tests
87-
env:
88-
BRAINTRUST_E2E_RUN_CONTEXT_DIR: ${{ steps.run_context.outputs.dir }}
89-
run: pnpm test:e2e
90-
- name: Build e2e Braintrust links summary
91-
if: ${{ always() }}
92-
shell: bash
93-
env:
94-
BRAINTRUST_E2E_RUN_CONTEXT_DIR: ${{ steps.run_context.outputs.dir }}
95-
BRAINTRUST_ORG_NAME: ${{ vars.BRAINTRUST_ORG_NAME }}
96-
GITHUB_HEAD_REF: ${{ github.head_ref }}
97-
GITHUB_REF_NAME: ${{ github.ref_name }}
98-
GITHUB_REPOSITORY: ${{ github.repository }}
99-
GITHUB_RUN_ID: ${{ github.run_id }}
100-
GITHUB_SERVER_URL: ${{ github.server_url }}
101-
run: |
102-
SUMMARY_PATH="$RUNNER_TEMP/e2e-braintrust-links-summary.md"
103-
node e2e/scripts/build-pr-e2e-links-comment.mjs --output "$SUMMARY_PATH"
104-
cat "$SUMMARY_PATH" >> "$GITHUB_STEP_SUMMARY"
105-
106-
e2e-canary:
107-
runs-on: ubuntu-latest
108-
timeout-minutes: 45
109-
env:
110-
BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }}
111-
BRAINTRUST_E2E_PROJECT_NAME: ${{ vars.BRAINTRUST_E2E_PROJECT_NAME }}
112-
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
113-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
114-
COHERE_API_KEY: ${{ secrets.COHERE_API_KEY }}
115-
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
116-
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
117-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
118-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
119-
MISTRAL_API_KEY: ${{ secrets.MISTRAL_API_KEY }}
120-
HUGGINGFACE_API_KEY: ${{ secrets.HUGGINGFACE_API_KEY }}
121-
steps:
122-
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
123-
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
124-
with:
125-
node-version-file: .tool-versions
126-
- name: Setup pnpm
127-
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
128-
- name: Install dependencies
129-
run: pnpm install --frozen-lockfile
130-
- name: Run canary e2e tests
131-
run: pnpm test:e2e:canary

.gitleaks.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
title = "Braintrust SDK gitleaks config"
2+
3+
[extend]
4+
# Use the default gitleaks ruleset as the base
5+
useDefault = true
6+
7+
[[rules]]
8+
id = "braintrust-api-key"
9+
description = "Braintrust API key"
10+
regex = '''\bsk-[a-zA-Z0-9]{40,}\b'''
11+
tags = ["key", "braintrust"]

.husky/pre-commit

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
1+
# Check for secrets in staged files before committing
2+
if command -v gitleaks &> /dev/null; then
3+
gitleaks protect --staged --redact --no-banner
4+
else
5+
echo "WARNING: gitleaks not installed — skipping secret scan. Install via: brew install gitleaks"
6+
fi
7+
18
pnpm exec lint-staged

.prettierignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ deno.lock
1010

1111
# Template files with special formatting
1212
js/scripts/openapi_zod_client_output_template.hbs
13+
14+
.context

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ export ANTHROPIC_API_KEY="sk-ant-..."
5555

5656
**E2E tests (`e2e/`):**
5757

58-
Each scenario runs the SDK in a subprocess against a mock Braintrust server and snapshots the results. No API keys required.
58+
Each scenario runs the SDK in a subprocess against a mock Braintrust server and snapshots the results. No API keys required for replay; recording needs provider keys.
5959

6060
```bash
6161
pnpm run test:e2e # Run all e2e scenarios (from repo root)
62-
pnpm run test:e2e:update # Run and update snapshots
62+
pnpm run test:e2e:record # Re-record provider cassettes and update snapshots
6363
```
6464

6565
**From repo root:**

dev-packages/seinfeld/package.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@braintrust/seinfeld",
3+
"version": "0.0.0",
4+
"private": true,
5+
"description": "Internal cassette server for e2e provider tests.",
6+
"type": "module",
7+
"license": "MIT",
8+
"engines": {
9+
"node": ">=18"
10+
},
11+
"main": "./dist/index.cjs",
12+
"module": "./dist/index.js",
13+
"types": "./dist/index.d.ts",
14+
"exports": {
15+
".": {
16+
"types": "./dist/index.d.ts",
17+
"import": "./dist/index.js",
18+
"require": "./dist/index.cjs"
19+
}
20+
},
21+
"files": [
22+
"dist"
23+
],
24+
"scripts": {
25+
"build": "tsup",
26+
"dev": "tsup --watch",
27+
"typecheck": "tsc --noEmit"
28+
},
29+
"dependencies": {
30+
"zod": "^3.23.8"
31+
},
32+
"devDependencies": {
33+
"@types/node": "^22.10.0",
34+
"tsup": "^8.5.1",
35+
"typescript": "^5.7.2"
36+
}
37+
}

0 commit comments

Comments
 (0)