Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,18 @@ jobs:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

ensure-pinned-actions:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- run: bash scripts/ensure-pinned-actions.sh

# Summary job that requires all matrix tests to pass
# This is what branch protection will check
ci-success:
name: CI Success
needs: test
needs: [test, ensure-pinned-actions]
runs-on: ubuntu-latest
if: always()
steps:
Expand Down
131 changes: 131 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#
# Prerelease workflow for the Ruby SDK.
# Publishes a release candidate (rc) from any ref to RubyGems.
# Version is auto-generated as {base_version}.rc.{run_number} — no version bump required.
# Follows the same approval gate as stable releases.
#

name: Prerelease Ruby SDK

on:
workflow_dispatch:
inputs:
ref:
description: "Branch, tag, or commit SHA to publish as prerelease"
required: true
type: string
default: "main"

jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
release_tag: ${{ steps.get-tag.outputs.tag }}
sha: ${{ steps.get-tag.outputs.sha }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ inputs.ref }}
fetch-depth: 0

- uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: '3.4'
bundler-cache: true

- name: Generate rc version and validate
id: get-tag
run: |
VERSION=$(ruby -r "./lib/braintrust/version.rb" -e "puts Braintrust::VERSION")
TAG="v${VERSION}.rc.${GITHUB_RUN_NUMBER}"
SHA=$(git rev-parse HEAD)

if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: Tag $TAG already exists"
exit 1
fi

echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "sha=$SHA" >> $GITHUB_OUTPUT
echo "Ready to release $TAG @ $SHA"

notify:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- name: Post release summary and notify Slack
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL: ${{ vars.SLACK_SDK_RELEASE_CHANNEL }}
TAG: ${{ needs.validate.outputs.release_tag }}
SHA: ${{ needs.validate.outputs.sha }}
run: |
APPROVE_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"

echo "## braintrust-sdk-ruby $TAG (prerelease)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Ref:** ${{ inputs.ref }}" >> $GITHUB_STEP_SUMMARY
echo "**SHA:** $SHA" >> $GITHUB_STEP_SUMMARY

curl -s -X POST "https://slack.com/api/chat.postMessage" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"channel\": \"$SLACK_CHANNEL\",
\"text\": \":gem: *braintrust-sdk-ruby $TAG* (prerelease) is awaiting approval. <$APPROVE_URL|View & approve>\"
}"

publish:
needs: [validate, notify]
runs-on: ubuntu-latest
timeout-minutes: 15
environment: rubygems-publish

permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ needs.validate.outputs.sha }}
fetch-depth: 0

- uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: '3.4'
bundler-cache: true

- name: Unfreeze bundler for version modification
run: bundle config set --local frozen false

- name: Configure RubyGems credentials
uses: rubygems/configure-rubygems-credentials@a991f145d5e4a60c4b0a3ddb204f557dc1a4f985 # main

- name: Build and publish prerelease gem
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_RUN_NUMBER: ${{ github.run_number }}
TAG: ${{ needs.validate.outputs.release_tag }}
run: |
bundle exec rake release:prerelease
git tag "$TAG"
gh release create "$TAG" --title "$TAG" --prerelease --generate-notes

- name: Notify Slack on release
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL: ${{ vars.SLACK_SDK_RELEASE_CHANNEL }}
TAG: ${{ needs.validate.outputs.release_tag }}
run: |
curl -s -X POST "https://slack.com/api/chat.postMessage" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"channel\": \"$SLACK_CHANNEL\",
\"text\": \":white_check_mark: *braintrust-sdk-ruby $TAG* (prerelease) has been published to RubyGems.\"
}"
50 changes: 0 additions & 50 deletions .github/workflows/publish-gem-prerelease.yaml

This file was deleted.

60 changes: 0 additions & 60 deletions .github/workflows/publish-gem.yaml

This file was deleted.

134 changes: 134 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#
# Primary release workflow for the Ruby SDK.
# Triggered manually via GitHub Actions UI (browser session required — not via local git push).
# Reads the version from lib/braintrust/version.rb on main, posts a job summary with the
# list of changes for the reviewer, then waits for human approval before publishing.
#

name: Release Ruby SDK

on:
workflow_dispatch:

jobs:
validate:
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
release_tag: ${{ steps.get-tag.outputs.tag }}
sha: ${{ steps.get-tag.outputs.sha }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: main
fetch-depth: 0

- uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: '3.4'
bundler-cache: true

- name: Read version and validate
id: get-tag
run: |
VERSION=$(ruby -r "./lib/braintrust/version.rb" -e "puts Braintrust::VERSION")
TAG="v${VERSION}"
SHA=$(git log -1 --format="%H" -- lib/braintrust/version.rb)

if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Error: Tag $TAG already exists — has the version been bumped?"
exit 1
fi

echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "sha=$SHA" >> $GITHUB_OUTPUT
echo "Ready to release $TAG @ $SHA"

notify:
needs: validate
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ needs.validate.outputs.sha }}
fetch-depth: 0

- name: Post release summary and notify Slack
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL: ${{ vars.SLACK_SDK_RELEASE_CHANNEL }}
TAG: ${{ needs.validate.outputs.release_tag }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PREVIOUS_TAG=$(git describe --tags --abbrev=0 \
--match='v[0-9]*.[0-9]*.[0-9]*' HEAD^ 2>/dev/null || echo "")

NOTES=$(gh api "repos/$GITHUB_REPOSITORY/releases/generate-notes" \
--method POST \
--field tag_name="$TAG" \
--jq '.body' 2>/dev/null || echo "_No previous release found — initial release._")

APPROVE_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"

# Write full PR list to job summary — visible on the approval page
echo "## braintrust-sdk-ruby $TAG" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "$NOTES" >> $GITHUB_STEP_SUMMARY

# Slack message is intentionally brief — full details are one click away
curl -s -X POST "https://slack.com/api/chat.postMessage" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"channel\": \"$SLACK_CHANNEL\",
\"text\": \":gem: *braintrust-sdk-ruby $TAG* is awaiting release approval. <$APPROVE_URL|View changes & approve>\"
}"

publish:
needs: [validate, notify]
runs-on: ubuntu-latest
timeout-minutes: 15
environment: rubygems-publish

permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ needs.validate.outputs.sha }}
fetch-depth: 0

- uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0
with:
ruby-version: '3.4'
bundler-cache: true

- name: Configure RubyGems credentials
uses: rubygems/configure-rubygems-credentials@a991f145d5e4a60c4b0a3ddb204f557dc1a4f985 # main

- name: Publish gem
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REF_NAME: ${{ needs.validate.outputs.release_tag }}
run: |
git tag "$GITHUB_REF_NAME"
bundle exec rake release

- name: Notify Slack on release
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL: ${{ vars.SLACK_SDK_RELEASE_CHANNEL }}
TAG: ${{ needs.validate.outputs.release_tag }}
run: |
curl -s -X POST "https://slack.com/api/chat.postMessage" \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"channel\": \"$SLACK_CHANNEL\",
\"text\": \":white_check_mark: *braintrust-sdk-ruby $TAG* has been published to RubyGems.\"
}"
Loading
Loading