Skip to content

Commit 25d25d5

Browse files
AbhiPrasadlforst
andauthored
chore: migrate to changesets for release management (#1738)
resolves #1576 Replace the custom tag-based release scripts with @changesets/cli for versioning and publishing across all workspace packages. Read through `PUBLISHING_JS.md` to see how this all works now! - Add @changesets/cli and @changesets/changelog-github to devDependencies - Add .changeset config and initial changeset entries - Add repository, homepage, and publishConfig to all integration package.json files - Fix repository.directory in js/package.json - Add centralized release scripts under scripts/release/ - Remove legacy js/scripts/ release and validation scripts - Remove publish:validate script from js/package.json - Remove workspaces field from root package.json (pnpm-workspace.yaml is sufficient) - Add changeset convenience scripts to root package.json - Update CI workflows for changeset-based publishing - Generate initial CHANGELOGs for all packages --------- Co-authored-by: Luca Forstner <luca.forstner@gmail.com>
1 parent df3434d commit 25d25d5

43 files changed

Lines changed: 2369 additions & 1046 deletions

Some content is hidden

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

.changeset/config.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://unpkg.com/@changesets/config/schema.json",
3+
"changelog": [
4+
"@changesets/changelog-github",
5+
{
6+
"repo": "braintrustdata/braintrust-sdk-javascript"
7+
}
8+
],
9+
"commit": false,
10+
"fixed": [],
11+
"linked": [],
12+
"access": "public",
13+
"baseBranch": "main",
14+
"updateInternalDependencies": "patch",
15+
"bumpVersionsWithWorkspaceProtocolOnly": true,
16+
"ignore": [],
17+
"snapshot": {
18+
"useCalculatedVersion": true,
19+
"prereleaseTemplate": "{tag}.{datetime}.{commit}"
20+
}
21+
}

.changeset/little-webs-hang.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
"braintrust": minor
3+
---
4+
5+
- feat: Add instrumentation for @huggingface/inference (#1807)
6+
- feat: Add cohere-ai instrumentation (#1781)
7+
- fix: Capture anthropic server tool use inputs for streaming APIs (#1776)
8+
- feat: Capture grounding metadata for Google GenAI (#1773)
9+
- fix(claude-agent-sdk): Don't drop tool spans for spawning subagents (#1779)
10+
- feat: Track server tool use metrics for anthropic SDK (#1772)
11+
- fix(openai): Collect logprob and refulsals output for streaming APIs (#1774)
12+
- perf: Remove zod from deepCopyEvent (#1796)
13+
- fix(test): Double timeout for slow OpenAI API tests (#1794)
14+
- feat(claude-agent-sdk): Improve task lifecycle and lifecycle details (#1777)
15+
- ci(deps): bump actions/github-script from 8.0.0 to 9.0.0 (#1783)
16+
- ci(deps): bump docker/setup-buildx-action from 3.12.0 to 4.0.0 (#1782)
17+
- chore: Don't use environment (ie. github deployments) for canary tests (#1775)
18+
- chore: Make dependabot less annoying (#1778)
19+
- fix(auto-instrumentation): Upgrade @apm-js-collab/code-transformer to v0.12.0 (#1708)
20+
- fix(auto-instrumentation): Use sync channel for AI SDK CJS streamText/streamObject in v4+ (#1768)
21+
- fix: Give AI SDK top-level api spans type function (#1769)
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
name: Run JS release mode
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
mode:
7+
required: true
8+
type: string
9+
checkout_ref:
10+
required: true
11+
type: string
12+
version_command:
13+
required: true
14+
type: string
15+
publish_enabled:
16+
required: false
17+
default: false
18+
type: boolean
19+
publish_command:
20+
required: false
21+
default: ""
22+
type: string
23+
artifact_dir:
24+
required: false
25+
default: ""
26+
type: string
27+
artifact_name:
28+
required: false
29+
default: ""
30+
type: string
31+
slack_text:
32+
required: false
33+
default: ""
34+
type: string
35+
slack_header:
36+
required: false
37+
default: ""
38+
type: string
39+
slack_details:
40+
required: false
41+
default: ""
42+
type: string
43+
run_canary_check:
44+
required: false
45+
default: false
46+
type: boolean
47+
48+
jobs:
49+
run:
50+
runs-on: ubuntu-latest
51+
timeout-minutes: 30
52+
permissions:
53+
actions: read
54+
contents: read
55+
id-token: write
56+
steps:
57+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
58+
with:
59+
fetch-depth: 0
60+
ref: ${{ inputs.checkout_ref }}
61+
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
62+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
63+
with:
64+
node-version-file: .tool-versions
65+
cache: pnpm
66+
registry-url: https://registry.npmjs.org
67+
- name: Install dependencies
68+
run: pnpm install --frozen-lockfile
69+
- name: Validate publishable package metadata
70+
run: node scripts/release/validate-publishable-packages.mjs
71+
- name: Compute changeset status
72+
run: pnpm exec changeset status --output=.changeset-status.json
73+
- name: Check release status
74+
id: status_check
75+
run: node scripts/release/check-changeset-status.mjs --mode ${{ inputs.mode }} --status-file .changeset-status.json
76+
- name: Check if canary already published for HEAD
77+
if: inputs.run_canary_check && steps.status_check.outputs.has_packages == 'true'
78+
id: canary_check
79+
env:
80+
GITHUB_TOKEN: ${{ github.token }}
81+
run: node scripts/release/should-publish-canary.mjs --status-file .changeset-status.json
82+
- name: Decide whether to continue
83+
id: plan
84+
env:
85+
HAS_PACKAGES: ${{ steps.status_check.outputs.has_packages }}
86+
RUN_CANARY_CHECK: ${{ inputs.run_canary_check && 'true' || 'false' }}
87+
CANARY_SHOULD_PUBLISH: ${{ steps.canary_check.outputs.should_publish }}
88+
run: |
89+
should_run="$HAS_PACKAGES"
90+
reason="Packages are available."
91+
92+
if [ "$HAS_PACKAGES" != "true" ]; then
93+
should_run=false
94+
reason="No publishable packages found."
95+
elif [ "$RUN_CANARY_CHECK" = "true" ] && [ "$CANARY_SHOULD_PUBLISH" != "true" ]; then
96+
should_run=false
97+
reason="Canary already published for HEAD."
98+
fi
99+
100+
echo "should_run=$should_run" >> "$GITHUB_OUTPUT"
101+
102+
{
103+
echo "## Release mode"
104+
echo
105+
echo '- Mode: `${{ inputs.mode }}`'
106+
echo '- Ref: `${{ inputs.checkout_ref }}`'
107+
echo "- Decision: $reason"
108+
} >> "$GITHUB_STEP_SUMMARY"
109+
- name: Version packages
110+
if: steps.plan.outputs.should_run == 'true'
111+
run: ${{ inputs.version_command }}
112+
- name: Prepare release manifest
113+
if: steps.plan.outputs.should_run == 'true'
114+
run: node scripts/release/prepare-release-manifest.mjs --mode ${{ inputs.mode }} --status-file .changeset-status.json --output .release-manifest.json
115+
- name: Build publishable packages
116+
if: steps.plan.outputs.should_run == 'true'
117+
run: bash scripts/release/build-publishable-packages.sh .release-manifest.json
118+
- name: Publish packages
119+
if: steps.plan.outputs.should_run == 'true' && inputs.publish_enabled
120+
run: ${{ inputs.publish_command }}
121+
env:
122+
NPM_TOKEN: ""
123+
- name: Summarize release
124+
if: steps.plan.outputs.should_run == 'true'
125+
id: summary
126+
run: node scripts/release/summarize-release.mjs --mode ${{ inputs.mode }} --manifest .release-manifest.json
127+
- name: Pack publishable packages
128+
if: steps.plan.outputs.should_run == 'true' && inputs.artifact_dir != ''
129+
run: node scripts/release/pack-publishable-packages.mjs --manifest .release-manifest.json --output-dir ${{ inputs.artifact_dir }}
130+
- name: Upload dry-run artifacts
131+
if: steps.plan.outputs.should_run == 'true' && inputs.artifact_dir != '' && inputs.artifact_name != ''
132+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
133+
with:
134+
name: ${{ inputs.artifact_name }}
135+
path: ${{ inputs.artifact_dir }}
136+
retention-days: 5
137+
- name: Post release to Slack
138+
if: steps.plan.outputs.should_run == 'true' && inputs.slack_text != '' && inputs.slack_header != ''
139+
uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
140+
with:
141+
method: chat.postMessage
142+
token: ${{ secrets.SLACK_BOT_TOKEN }}
143+
payload: |
144+
channel: C0ABHT0SWA2
145+
text: "${{ inputs.slack_text }}"
146+
blocks:
147+
- type: "header"
148+
text:
149+
type: "plain_text"
150+
text: "${{ inputs.slack_header }}"
151+
- type: "section"
152+
text:
153+
type: "mrkdwn"
154+
text: |
155+
${{ inputs.slack_details }}
156+
*Packages:*
157+
${{ steps.summary.outputs.markdown }}
158+
159+
<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>

.github/workflows/checks.yaml

Lines changed: 23 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ jobs:
8181
- name: Ensure SHA pinned actions
8282
uses: zgosalvez/github-actions-ensure-sha-pinned-actions@ca46236c6ce584ae24bc6283ba8dcf4b3ec8a066 # v5.0.4
8383

84+
changeset-required:
85+
if: github.event_name == 'pull_request'
86+
runs-on: ubuntu-latest
87+
timeout-minutes: 10
88+
steps:
89+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
90+
with:
91+
fetch-depth: 0
92+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
93+
with:
94+
node-version-file: .tool-versions
95+
- name: Fetch pull request base ref
96+
run: git fetch origin "${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}"
97+
- name: Enforce changeset requirement for publishable package changes
98+
run: node scripts/release/enforce-changeset.mjs
99+
84100
js-test:
85101
runs-on: ${{ matrix.os }}
86102
timeout-minutes: 30
@@ -131,72 +147,16 @@ jobs:
131147
run: |
132148
echo "Artifact: $ARTIFACT_NAME"
133149
echo "name=$ARTIFACT_NAME" >> "$GITHUB_OUTPUT"
134-
- name: Prepare artifact
135-
id: prepare_artifact
136-
working-directory: js
137-
shell: bash
138-
run: |
139-
mkdir -p artifacts
140-
PACKED_TARBALL=$(npm pack --pack-destination artifacts)
141-
echo "packed_tarball=$PACKED_TARBALL" >> "$GITHUB_OUTPUT"
142-
- name: Pack @braintrust/browser
143-
id: prepare_browser_artifact
144-
working-directory: integrations/browser-js
145-
shell: bash
146-
run: |
147-
PACKED_BROWSER_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
148-
echo "packed_browser_tarball=$PACKED_BROWSER_TARBALL" >> "$GITHUB_OUTPUT"
149-
- name: Build and pack @braintrust/otel
150-
id: prepare_otel_artifact
151-
shell: bash
152-
run: |
153-
BRAINTRUST_TARBALL=$(ls js/artifacts/braintrust-*.tgz | head -n 1)
154-
if [ -z "$BRAINTRUST_TARBALL" ]; then
155-
echo "Error: braintrust tarball not found"
156-
exit 1
157-
fi
158-
echo "Using braintrust tarball: $BRAINTRUST_TARBALL"
159-
160-
cd integrations/otel-js
161-
if ! npm_config_save=false npm_config_lockfile=false pnpm add \
162-
file:../../$BRAINTRUST_TARBALL \
163-
@opentelemetry/api@^1.9.0 \
164-
@opentelemetry/core@^1.9.0 \
165-
@opentelemetry/exporter-trace-otlp-http@^0.35.0 \
166-
@opentelemetry/sdk-trace-base@^1.9.0; then
167-
echo "Error: Failed to install dependencies"
168-
exit 1
169-
fi
170-
171-
pnpm run build
172-
173-
PACKED_OTEL_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
174-
echo "packed_otel_tarball=$PACKED_OTEL_TARBALL" >> "$GITHUB_OUTPUT"
175-
- name: Build and pack @braintrust/templates-nunjucks
176-
id: prepare_templates_nunjucks_artifact
177-
shell: bash
178-
run: |
179-
cd integrations/templates-nunjucks
180-
pnpm run build
181-
PACKED_NUNJUCKS_TARBALL=$(npm pack --pack-destination ../../js/artifacts)
182-
echo "packed_nunjucks_tarball=$PACKED_NUNJUCKS_TARBALL" >> "$GITHUB_OUTPUT"
150+
- name: Pack publishable packages
151+
run: node scripts/release/pack-publishable-packages.mjs --output-dir js/artifacts
183152
- name: List artifacts before upload
184153
shell: bash
185-
run: |
186-
echo "Braintrust tarball: ${{ steps.prepare_artifact.outputs.packed_tarball }}"
187-
echo "Browser tarball: ${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }}"
188-
echo "Otel tarball: ${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}"
189-
echo "Templates-nunjucks tarball: ${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }}"
190-
ls -la js/artifacts/
154+
run: ls -la js/artifacts/
191155
- name: Upload build artifacts
192156
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
193157
with:
194158
name: ${{ steps.artifact.outputs.name }}-dist
195-
path: |
196-
js/artifacts/${{ steps.prepare_artifact.outputs.packed_tarball }}
197-
js/artifacts/${{ steps.prepare_browser_artifact.outputs.packed_browser_tarball }}
198-
js/artifacts/${{ steps.prepare_otel_artifact.outputs.packed_otel_tarball }}
199-
js/artifacts/${{ steps.prepare_templates_nunjucks_artifact.outputs.packed_nunjucks_tarball }}
159+
path: js/artifacts/*.tgz
200160
retention-days: 1
201161

202162
e2e-hermetic:
@@ -238,7 +198,7 @@ jobs:
238198
id: published-version
239199
shell: bash
240200
run: |
241-
PUBLISHED_VERSION=$(npm view braintrust version 2>/dev/null || echo "none")
201+
PUBLISHED_VERSION=$(cd /tmp && npm view braintrust version 2>/dev/null || echo "none")
242202
echo "version=$PUBLISHED_VERSION" >> "$GITHUB_OUTPUT"
243203
echo "Published version: $PUBLISHED_VERSION"
244204
- name: Cache API compatibility test tarball
@@ -512,6 +472,7 @@ jobs:
512472
- check-typings
513473
- dead-code
514474
- ensure-pinned-actions
475+
- changeset-required
515476
- js-test
516477
- js-build
517478
- e2e-hermetic
@@ -545,6 +506,7 @@ jobs:
545506
check_result "check-typings" "${{ needs.check-typings.result }}"
546507
check_result "dead-code" "${{ needs.dead-code.result }}"
547508
check_result "ensure-pinned-actions" "${{ needs.ensure-pinned-actions.result }}"
509+
check_result "changeset-required" "${{ needs.changeset-required.result }}"
548510
check_result "js-test" "${{ needs.js-test.result }}"
549511
check_result "js-build" "${{ needs.js-build.result }}"
550512
check_result "e2e-hermetic" "${{ needs.e2e-hermetic.result }}"

0 commit comments

Comments
 (0)