diff --git a/.github/workflows/publish-js-sdk-canary-scheduler.yaml b/.github/workflows/publish-js-sdk-canary-scheduler.yaml new file mode 100644 index 00000000..a8f449ec --- /dev/null +++ b/.github/workflows/publish-js-sdk-canary-scheduler.yaml @@ -0,0 +1,47 @@ +# This workflow is responsible for scheduling the JavaScript SDK canary publish workflow on a daily basis. +# The actual publish workflow is defined in `publish-js-sdk.yaml`, which is triggered by this scheduler workflow. +# `publish-js-sdk.yaml` has to be where the publish actually happens so that npm trusted publishing still works. +# npm trusted publishing that only one workflow can publish to npm. + +name: Schedule JavaScript SDK Canary Publish + +concurrency: + group: publish-js-sdk-canary-scheduler + cancel-in-progress: false + +on: + schedule: + - cron: "17 6 * * *" + workflow_dispatch: + +jobs: + dispatch-canary-publish: + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + actions: write + steps: + - name: Dispatch publish workflow + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: "publish-js-sdk.yaml", + ref: "main", + inputs: { + release_type: "canary", + branch: "main", + }, + }); + + - name: Summarize dispatch + run: | + { + echo "## JavaScript SDK Canary Dispatch Queued" + echo + echo "- Workflow: \`publish-js-sdk.yaml\`" + echo "- Release type: \`canary\`" + echo "- Branch: \`main\`" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/publish-js-sdk.yaml b/.github/workflows/publish-js-sdk.yaml index 883d8280..693f5e61 100644 --- a/.github/workflows/publish-js-sdk.yaml +++ b/.github/workflows/publish-js-sdk.yaml @@ -1,7 +1,7 @@ # # This workflow publishes the JavaScript SDK to npm. # -# It supports two manual modes: +# It supports three modes: # # 1. STABLE RELEASE: # - Manually triggered via GitHub Actions UI @@ -15,6 +15,11 @@ # - Publishes with the "rc" dist-tag # - Does NOT require updating package.json in the repository # +# 3. CANARY RELEASE: +# - Triggered manually or by the canary scheduler workflow +# - Publishes with the "canary" dist-tag +# - Reuses this workflow file so npm trusted publishing only needs one publisher +# name: Publish JavaScript SDK @@ -33,6 +38,7 @@ on: options: - stable - prerelease + - canary branch: description: Branch to release from required: true @@ -46,9 +52,11 @@ jobs: outputs: version: ${{ steps.release_metadata.outputs.version }} is_prerelease: ${{ steps.release_metadata.outputs.is_prerelease }} + is_canary: ${{ steps.release_metadata.outputs.is_canary }} release_tag: ${{ steps.release_metadata.outputs.release_tag }} branch: ${{ steps.release_metadata.outputs.branch }} commit: ${{ steps.release_metadata.outputs.commit }} + release_type: ${{ steps.release_metadata.outputs.release_type }} steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: @@ -57,7 +65,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: "20" + node-version: "22" - name: Determine release metadata id: release_metadata working-directory: js @@ -69,6 +77,11 @@ jobs: CURRENT_VERSION=$(node -p "require('./package.json').version") RELEASE_COMMIT=$(git rev-parse HEAD) + CURRENT_SHA=$(git rev-parse --short=7 HEAD) + + echo "release_type=${RELEASE_TYPE}" >> "$GITHUB_OUTPUT" + echo "branch=${TARGET_BRANCH}" >> "$GITHUB_OUTPUT" + echo "commit=${RELEASE_COMMIT}" >> "$GITHUB_OUTPUT" if [[ "$RELEASE_TYPE" == "stable" ]]; then RELEASE_TAG="js-sdk-v${CURRENT_VERSION}" @@ -76,20 +89,27 @@ jobs: echo "version=${CURRENT_VERSION}" >> "$GITHUB_OUTPUT" echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + echo "is_canary=false" >> "$GITHUB_OUTPUT" echo "release_tag=${RELEASE_TAG}" >> "$GITHUB_OUTPUT" - else + elif [[ "$RELEASE_TYPE" == "prerelease" ]]; then VERSION="${CURRENT_VERSION}-rc.${GITHUB_RUN_NUMBER}" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "is_prerelease=true" >> "$GITHUB_OUTPUT" + echo "is_canary=false" >> "$GITHUB_OUTPUT" echo "release_tag=" >> "$GITHUB_OUTPUT" - fi + else + VERSION="${CURRENT_VERSION}-canary.$(date -u +%Y%m%d).${GITHUB_RUN_NUMBER}.g${CURRENT_SHA}" - echo "branch=${TARGET_BRANCH}" >> "$GITHUB_OUTPUT" - echo "commit=${RELEASE_COMMIT}" >> "$GITHUB_OUTPUT" + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + echo "is_canary=true" >> "$GITHUB_OUTPUT" + echo "release_tag=" >> "$GITHUB_OUTPUT" + fi build-and-publish-stable: needs: prepare-release - if: needs.prepare-release.outputs.is_prerelease == 'false' + if: needs.prepare-release.outputs.release_type == 'stable' runs-on: ubuntu-latest timeout-minutes: 20 permissions: @@ -109,7 +129,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: "20" + node-version: "22" registry-url: "https://registry.npmjs.org" - name: Install npm 11.6.2 run: npm install -g npm@11.6.2 @@ -164,7 +184,7 @@ jobs: build-and-publish-prerelease: needs: prepare-release - if: needs.prepare-release.outputs.is_prerelease == 'true' + if: needs.prepare-release.outputs.release_type == 'prerelease' runs-on: ubuntu-latest timeout-minutes: 20 permissions: @@ -180,7 +200,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: - node-version: "20" + node-version: "22" registry-url: "https://registry.npmjs.org" - name: Install npm 11.6.2 run: npm install -g npm@11.6.2 @@ -195,20 +215,244 @@ jobs: path: js/dist/ retention-days: 5 + publish-canary: + needs: prepare-release + if: needs.prepare-release.outputs.release_type == 'canary' + runs-on: ubuntu-latest + timeout-minutes: 20 + outputs: + published: ${{ steps.publish_status.outputs.published }} + version: ${{ steps.publish_status.outputs.version }} + package_name: ${{ steps.publish_status.outputs.package_name }} + commit_sha: ${{ steps.publish_status.outputs.commit_sha }} + reason: ${{ steps.publish_status.outputs.reason }} + permissions: + actions: read + contents: read + id-token: write + env: + TARGET_BRANCH: ${{ needs.prepare-release.outputs.branch }} + VERSION: ${{ needs.prepare-release.outputs.version }} + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + fetch-depth: 0 + ref: ${{ needs.prepare-release.outputs.branch }} + + - name: Set up pnpm + uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 + + - name: Set up Node.js + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "22" + cache: "pnpm" + registry-url: "https://registry.npmjs.org" + + - name: Install npm 11.6.2 + run: npm install -g npm@11.6.2 + + - name: Check whether a new canary is needed + id: should_publish + run: | + set -euo pipefail + + PACKAGE_NAME="braintrust" + CURRENT_SHA=$(git rev-parse --short=7 HEAD) + PUBLISHED_VERSION=$(npm view "${PACKAGE_NAME}@canary" version --registry=https://registry.npmjs.org 2>/dev/null || true) + + if [ -z "$PUBLISHED_VERSION" ]; then + echo "should_publish=true" >> "$GITHUB_OUTPUT" + echo "reason=No existing canary found on npm." >> "$GITHUB_OUTPUT" + echo "previous_version=" >> "$GITHUB_OUTPUT" + echo "previous_sha=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + PUBLISHED_SHA=$(printf '%s\n' "$PUBLISHED_VERSION" | sed -n 's/.*\.g\([0-9a-f]\{7\}\)$/\1/p') + echo "previous_version=${PUBLISHED_VERSION}" >> "$GITHUB_OUTPUT" + echo "previous_sha=${PUBLISHED_SHA}" >> "$GITHUB_OUTPUT" + + if [ "$PUBLISHED_SHA" = "$CURRENT_SHA" ]; then + echo "should_publish=false" >> "$GITHUB_OUTPUT" + echo "reason=Current HEAD ${CURRENT_SHA} is already published as canary ${PUBLISHED_VERSION}." >> "$GITHUB_OUTPUT" + else + echo "should_publish=true" >> "$GITHUB_OUTPUT" + echo "reason=Published canary ${PUBLISHED_VERSION} does not match HEAD ${CURRENT_SHA}." >> "$GITHUB_OUTPUT" + fi + + - name: Check JS CI status + if: steps.should_publish.outputs.should_publish == 'true' + id: ci_status + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + env: + TARGET_BRANCH: ${{ env.TARGET_BRANCH }} + with: + script: | + const { owner, repo } = context.repo; + const response = await github.rest.actions.listWorkflowRuns({ + owner, + repo, + workflow_id: "js.yaml", + branch: process.env.TARGET_BRANCH, + status: "completed", + per_page: 1, + }); + + const run = response.data.workflow_runs[0]; + if (!run) { + core.setOutput("should_publish", "false"); + core.setOutput("reason", `No completed js.yaml run found on ${process.env.TARGET_BRANCH}.`); + return; + } + + if (run.conclusion !== "success") { + core.setOutput("should_publish", "false"); + core.setOutput( + "reason", + `Latest completed js.yaml run on ${process.env.TARGET_BRANCH} concluded with ${run.conclusion} (${run.html_url}).`, + ); + return; + } + + core.setOutput("should_publish", "true"); + core.setOutput( + "reason", + `Latest completed js.yaml run on ${process.env.TARGET_BRANCH} succeeded (${run.html_url}).`, + ); + + - name: Install dependencies + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + run: pnpm install --frozen-lockfile + + - name: Prepare canary package metadata + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + id: metadata + working-directory: js + env: + VERSION: ${{ env.VERSION }} + run: | + set -euo pipefail + + CURRENT_SHA=$(git rev-parse --short=7 HEAD) + CANARY_NAME="braintrust" + npm version "$VERSION" --no-git-tag-version --allow-same-version + + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "package_name=${CANARY_NAME}" >> "$GITHUB_OUTPUT" + echo "commit_sha=${CURRENT_SHA}" >> "$GITHUB_OUTPUT" + + - name: Build SDK + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + working-directory: js + run: pnpm run build + + - name: Publish canary to npm + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + working-directory: js + run: npm publish --tag canary + + - name: Upload build artifacts + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: javascript-sdk-canary-dist + path: js/dist/ + retention-days: 5 + + - name: Summarize canary publish + if: steps.should_publish.outputs.should_publish == 'true' && steps.ci_status.outputs.should_publish == 'true' + env: + PACKAGE_NAME: ${{ steps.metadata.outputs.package_name }} + VERSION: ${{ steps.metadata.outputs.version }} + COMMIT_SHA: ${{ steps.metadata.outputs.commit_sha }} + PREVIOUS_VERSION: ${{ steps.should_publish.outputs.previous_version }} + PREVIOUS_SHA: ${{ steps.should_publish.outputs.previous_sha }} + run: | + set -euo pipefail + + { + echo "## JavaScript SDK Canary Published" + echo + echo "- Package: \`${PACKAGE_NAME}\`" + echo "- Version: \`${VERSION}\`" + echo "- Commit: \`${COMMIT_SHA}\`" + echo "- Registry: \`https://registry.npmjs.org\`" + echo "- Install: \`npm install ${PACKAGE_NAME}@canary\`" + echo + echo "### Included commits" + if [ -n "$PREVIOUS_SHA" ]; then + echo "- Previous canary: \`${PREVIOUS_VERSION}\`" + git log "${PREVIOUS_SHA}..HEAD" --pretty=format:"- %h %s (%an)" + else + echo "- Previous canary: none" + git log -n 20 --pretty=format:"- %h %s (%an)" + fi + } >> "$GITHUB_STEP_SUMMARY" + + - name: Summarize skipped canary publish + if: steps.should_publish.outputs.should_publish != 'true' || steps.ci_status.outputs.should_publish != 'true' + env: + SHOULD_PUBLISH_REASON: ${{ steps.should_publish.outputs.reason }} + CI_REASON: ${{ steps.ci_status.outputs.reason }} + run: | + set -euo pipefail + + REASON="${CI_REASON:-$SHOULD_PUBLISH_REASON}" + + { + echo "## JavaScript SDK Canary Skipped" + echo + echo "$REASON" + } >> "$GITHUB_STEP_SUMMARY" + + - name: Set publish status outputs + id: publish_status + if: always() + env: + SHOULD_PUBLISH: ${{ steps.should_publish.outputs.should_publish }} + CI_SHOULD_PUBLISH: ${{ steps.ci_status.outputs.should_publish }} + VERSION: ${{ steps.metadata.outputs.version }} + PACKAGE_NAME: ${{ steps.metadata.outputs.package_name }} + COMMIT_SHA: ${{ steps.metadata.outputs.commit_sha }} + SHOULD_PUBLISH_REASON: ${{ steps.should_publish.outputs.reason }} + CI_REASON: ${{ steps.ci_status.outputs.reason }} + run: | + set -euo pipefail + + if [ "${SHOULD_PUBLISH}" = "true" ] && [ "${CI_SHOULD_PUBLISH}" = "true" ]; then + echo "published=true" >> "$GITHUB_OUTPUT" + else + echo "published=false" >> "$GITHUB_OUTPUT" + fi + + REASON="${CI_REASON:-$SHOULD_PUBLISH_REASON}" + + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + echo "package_name=${PACKAGE_NAME}" >> "$GITHUB_OUTPUT" + echo "commit_sha=${COMMIT_SHA}" >> "$GITHUB_OUTPUT" + echo "reason=${REASON}" >> "$GITHUB_OUTPUT" + notify-success: needs: - [prepare-release, build-and-publish-stable, build-and-publish-prerelease] + [ + prepare-release, + build-and-publish-stable, + build-and-publish-prerelease, + publish-canary, + ] if: | always() && ( needs.build-and-publish-stable.result == 'success' || - needs.build-and-publish-prerelease.result == 'success' + needs.build-and-publish-prerelease.result == 'success' || + (needs.publish-canary.result == 'success' && needs.publish-canary.outputs.published == 'true') ) runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: Post to Slack on success (stable release) - if: needs.prepare-release.outputs.is_prerelease == 'false' + if: needs.prepare-release.outputs.release_type == 'stable' uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 with: method: chat.postMessage @@ -225,8 +469,9 @@ jobs: text: type: "mrkdwn" text: "*Version:* ${{ needs.prepare-release.outputs.version }}\n*Branch:* `${{ needs.prepare-release.outputs.branch }}`\n*Package:* \n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" + - name: Post to Slack on success (pre-release) - if: needs.prepare-release.outputs.is_prerelease == 'true' + if: needs.prepare-release.outputs.release_type == 'prerelease' uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 with: method: chat.postMessage @@ -244,15 +489,40 @@ jobs: type: "mrkdwn" text: "*Version:* ${{ needs.prepare-release.outputs.version }}\n*Branch:* `${{ needs.prepare-release.outputs.branch }}`\n*npm tag:* `rc` (install with `npm install braintrust@rc`)\n*Package:* \n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" + - name: Post to Slack on success (canary) + if: needs.prepare-release.outputs.release_type == 'canary' + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + channel: C0ABHT0SWA2 + text: "🧪 JavaScript SDK canary ${{ needs.publish-canary.outputs.version }} published: https://www.npmjs.com/package/braintrust/v/${{ needs.publish-canary.outputs.version }}" + blocks: + - type: "header" + text: + type: "plain_text" + text: "🧪 JavaScript SDK Canary Published" + - type: "section" + text: + type: "mrkdwn" + text: "*Version:* ${{ needs.publish-canary.outputs.version }}\n*Branch:* `${{ needs.prepare-release.outputs.branch }}`\n*Commit:* `${{ needs.publish-canary.outputs.commit_sha }}`\n*Package:* \n*Install:* `npm install ${{ needs.publish-canary.outputs.package_name }}@canary`\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" + notify-failure: needs: - [prepare-release, build-and-publish-stable, build-and-publish-prerelease] + [ + prepare-release, + build-and-publish-stable, + build-and-publish-prerelease, + publish-canary, + ] if: | always() && ( needs.prepare-release.result == 'failure' || needs.build-and-publish-stable.result == 'failure' || - needs.build-and-publish-prerelease.result == 'failure' + needs.build-and-publish-prerelease.result == 'failure' || + needs.publish-canary.result == 'failure' ) runs-on: ubuntu-latest timeout-minutes: 5 @@ -273,4 +543,32 @@ jobs: - type: "section" text: type: "mrkdwn" - text: "*Release type:* ${{ inputs.release_type }}\n*Branch:* `${{ inputs.branch }}`\n*Commit:* ${{ needs.prepare-release.outputs.commit || github.sha }}\n*Triggered by:* ${{ github.event_name }}\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" + text: "*Release type:* ${{ needs.prepare-release.outputs.release_type || 'canary' }}\n*Branch:* `${{ needs.prepare-release.outputs.branch || 'main' }}`\n*Commit:* ${{ needs.prepare-release.outputs.commit || github.sha }}\n*Triggered by:* ${{ github.event_name }}\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" + + notify-skipped: + needs: [prepare-release, publish-canary] + if: | + always() && + needs.prepare-release.outputs.release_type == 'canary' && + needs.publish-canary.result == 'success' && + needs.publish-canary.outputs.published != 'true' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Post to Slack on intentional skip + uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + channel: C0ABHT0SWA2 + text: "⏭️ JavaScript SDK canary publish skipped: ${{ needs.publish-canary.outputs.reason }}" + blocks: + - type: "header" + text: + type: "plain_text" + text: "⏭️ JavaScript SDK Canary Publish Skipped" + - type: "section" + text: + type: "mrkdwn" + text: "*Branch:* `${{ needs.prepare-release.outputs.branch }}`\n*Commit:* `${{ needs.prepare-release.outputs.commit }}`\n*Reason:* ${{ needs.publish-canary.outputs.reason }}\n\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>" diff --git a/Makefile b/Makefile index cc49249f..076312b6 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ js-test-otel-docker: # ------------------------------------------------------------------------------------------------- # Stable release publishing # Preferred: trigger publish-js-sdk.yaml from GitHub Actions UI -# Fallback: make release-js-sdk [BRANCH=] dispatches the same workflow via gh +# Fallback: make release-js-sdk [RELEASE_TYPE=stable|prerelease|canary] [BRANCH=] dispatches the same workflow via gh # ------------------------------------------------------------------------------------------------- .PHONY: release-js-sdk diff --git a/PUBLISHING_JS.md b/PUBLISHING_JS.md index ec6df106..afb4f44a 100644 --- a/PUBLISHING_JS.md +++ b/PUBLISHING_JS.md @@ -4,7 +4,9 @@ Use the [Publish JavaScript SDK workflow](https://github.com/braintrustdata/braintrust-sdk-javascript/actions/workflows/publish-js-sdk.yaml) in GitHub Actions. -This is the primary release entrypoint for both stable releases and prereleases. +This is the single npm publish entrypoint for stable releases, prereleases, and canaries. + +We keep all npm publishes in one workflow file because npm trusted publishing only allows one configured GitHub Actions publisher per package. Stable releases now pause at the `npm-publish` GitHub Actions environment and require approval before the publish job runs. @@ -25,6 +27,15 @@ Stable releases now pause at the `npm-publish` GitHub Actions environment and re - Publishes to the `rc` npm dist-tag - Does not update `js/package.json` in the repository +### Canary + +- Can be triggered manually by running the same workflow with `release_type=canary` +- Publishes `-canary...g` +- Publishes to the `canary` npm dist-tag +- Does not create a GitHub release +- Skips publishing if the current `HEAD` commit already matches the existing `canary` tag on npm +- Skips publishing unless the latest completed `js.yaml` run on the target branch succeeded + ## Stable Release Checklist 1. Bump `js/package.json` according to [SEMVER](https://semver.org/) principles. @@ -51,6 +62,17 @@ Stable releases now pause at the `npm-publish` GitHub Actions environment and re If you prerelease from a non-`main` branch, make sure that branch is in the state you intend to publish. +## Nightly Canary + +Nightly canary scheduling now lives in the separate [Schedule JavaScript SDK Canary Publish workflow](https://github.com/braintrustdata/braintrust-sdk-javascript/actions/workflows/publish-js-sdk-canary-scheduler.yaml). + +- The scheduler only dispatches [Publish JavaScript SDK](https://github.com/braintrustdata/braintrust-sdk-javascript/actions/workflows/publish-js-sdk.yaml) with `release_type=canary` and `branch=main`. +- The actual npm publish still runs in `publish-js-sdk.yaml`, so npm trusted publishing only needs that one workflow configured as the publisher. +- Manual canary runs still use the publish workflow dispatch form directly. +- Install with `npm install braintrust@canary`. + +The workflow writes a short run summary with the published version and recent commits touching `js/` so there is at least a lightweight change summary even though there is no formal changelog. + ## Fallback CLI Trigger If you do not want to open GitHub Actions manually, you can dispatch the same workflow from the terminal: @@ -65,12 +87,20 @@ To target a different remote branch: make release-js-sdk BRANCH= ``` +To dispatch a prerelease or canary instead of a stable release: + +```bash +make release-js-sdk RELEASE_TYPE=prerelease +make release-js-sdk RELEASE_TYPE=canary +``` + Notes: - This is a fallback, not the recommended path. - It requires `gh` to be installed and authenticated. - It does not publish from your local checkout. - It dispatches the same GitHub Actions workflow against the selected branch on GitHub. +- `RELEASE_TYPE` defaults to `stable`. ## Repository Setup diff --git a/js/scripts/dispatch-release-workflow.sh b/js/scripts/dispatch-release-workflow.sh index 9e5d9633..c814ef0b 100755 --- a/js/scripts/dispatch-release-workflow.sh +++ b/js/scripts/dispatch-release-workflow.sh @@ -15,6 +15,16 @@ if ! gh auth status >/dev/null 2>&1; then fi BRANCH="${BRANCH:-$(git rev-parse --abbrev-ref HEAD)}" +RELEASE_TYPE="${RELEASE_TYPE:-stable}" + +case "$RELEASE_TYPE" in + stable|prerelease|canary) + ;; + *) + echo "ERROR: RELEASE_TYPE must be one of: stable, prerelease, canary" + exit 1 + ;; +esac if [ "$BRANCH" = "HEAD" ]; then echo "ERROR: Could not determine the current branch. Set BRANCH= and retry." @@ -26,7 +36,7 @@ if ! git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then exit 1 fi -echo "Dispatching publish-js-sdk workflow for branch '$BRANCH'..." -gh workflow run publish-js-sdk.yaml --ref "$BRANCH" -f release_type=stable -f branch="$BRANCH" +echo "Dispatching publish-js-sdk workflow for branch '$BRANCH' with release_type='$RELEASE_TYPE'..." +gh workflow run publish-js-sdk.yaml --ref "$BRANCH" -f release_type="$RELEASE_TYPE" -f branch="$BRANCH" echo "Workflow dispatched:" echo "https://github.com/braintrustdata/braintrust-sdk-javascript/actions/workflows/publish-js-sdk.yaml"