Skip to content

Merge pull request #72 from braintrustdata/ark/spring-ai-revamp #28

Merge pull request #72 from braintrustdata/ark/spring-ai-revamp

Merge pull request #72 from braintrustdata/ark/spring-ai-revamp #28

# This workflow is triggered when a new tag is pushed to main.
# It can also be run manually to re-publish a release in case it failed for some reason.
name: Publish Release From Tag
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish (e.g., v1.0.0)'
required: true
type: string
permissions:
contents: write
jobs:
validate-and-publish:
name: Validate Tag and Publish Release
# we want to run ubuntu-latest but we'll pin to a specific version so workflow is reproducable
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0
- name: Determine tag
id: determine-tag
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
TAG_NAME="${{ github.ref_name }}"
else
TAG_NAME="${{ inputs.tag }}"
fi
echo "tag=$TAG_NAME" >> $GITHUB_OUTPUT
echo "Using tag: $TAG_NAME"
- name: Validate tag format
run: |
TAG="${{ steps.determine-tag.outputs.tag }}"
# Check if tag starts with 'v'
if [[ ! "$TAG" =~ ^v ]]; then
echo "Error: Tag '$TAG' must start with 'v'"
exit 1
fi
# Extract version without 'v' prefix
VERSION="${TAG#v}"
# Check if version is valid semver (x.y.z)
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Tag '$TAG' is not valid semver format (vx.y.z)"
exit 1
fi
# Check that version does not end with -SNAPSHOT
if [[ "$VERSION" =~ -SNAPSHOT$ ]]; then
echo "Error: Tag '$TAG' cannot end with '-SNAPSHOT'"
exit 1
fi
echo "Tag '$TAG' is valid"
- name: Verify tag exists
run: |
TAG="${{ steps.determine-tag.outputs.tag }}"
if ! git tag -l | grep -q "^$TAG$"; then
echo "Error: Tag '$TAG' does not exist"
exit 1
fi
echo "Tag '$TAG' exists"
- name: Checkout tag
run: |
git checkout ${{ steps.determine-tag.outputs.tag }}
- name: Set up JDK 17
uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4.8.0
with:
java-version: '17'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0
- name: Run CI
run: ./gradlew check
- name: Build release artifacts
run: ./gradlew build publishToMavenLocal
- name: Find built artifacts
id: find-artifacts
run: |
TAG="${{ steps.determine-tag.outputs.tag }}"
# Strip 'v' prefix to get the actual version used by Gradle
VERSION="${TAG#v}"
# braintrust-sdk artifacts
SDK_MAIN_JAR=$(find braintrust-sdk/build/libs -name "*-${VERSION}.jar" ! -name "*-sources.jar" ! -name "*-javadoc.jar" | head -1)
SDK_SOURCES_JAR=$(find braintrust-sdk/build/libs -name "*-${VERSION}-sources.jar" | head -1)
SDK_JAVADOC_JAR=$(find braintrust-sdk/build/libs -name "*-${VERSION}-javadoc.jar" | head -1)
# braintrust-java-agent artifact (single fat jar, no sources/javadoc)
AGENT_JAR=$(find braintrust-java-agent/build/libs -name "braintrust-java-agent-${VERSION}.jar" | head -1)
echo "sdk-main-jar=$SDK_MAIN_JAR" >> $GITHUB_OUTPUT
echo "sdk-sources-jar=$SDK_SOURCES_JAR" >> $GITHUB_OUTPUT
echo "sdk-javadoc-jar=$SDK_JAVADOC_JAR" >> $GITHUB_OUTPUT
echo "agent-jar=$AGENT_JAR" >> $GITHUB_OUTPUT
echo "Found artifacts:"
echo " SDK Main JAR: $SDK_MAIN_JAR"
echo " SDK Sources JAR: $SDK_SOURCES_JAR"
echo " SDK Javadoc JAR: $SDK_JAVADOC_JAR"
echo " Agent JAR: $AGENT_JAR"
- name: Create GitHub Release
run: |
TAG="${{ steps.determine-tag.outputs.tag }}"
# Create the release
gh release create "$TAG" \
--generate-notes \
--title "Release $TAG"
# Upload SDK artifacts
for jar in \
"${{ steps.find-artifacts.outputs.sdk-main-jar }}" \
"${{ steps.find-artifacts.outputs.sdk-sources-jar }}" \
"${{ steps.find-artifacts.outputs.sdk-javadoc-jar }}" \
"${{ steps.find-artifacts.outputs.agent-jar }}"; do
if [[ -n "$jar" && -f "$jar" ]]; then
gh release upload "$TAG" "$jar"
fi
done
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish to Sonatype
run: |-
if [ -z "$SONATYPE_USERNAME" ]; then
echo "Error: SONATYPE_USERNAME is not set"
exit 1
fi
if [ -z "$SONATYPE_PASSWORD" ]; then
echo "Error: SONATYPE_PASSWORD is not set"
exit 1
fi
if [ -z "$GPG_SIGNING_KEY" ]; then
echo "Error: GPG_SIGNING_KEY is not set"
exit 1
fi
if [ -z "$GPG_SIGNING_PASSWORD" ]; then
echo "Error: GPG_SIGNING_PASSWORD is not set"
exit 1
fi
echo "All required credentials are set"
export -- GPG_SIGNING_KEY_ID
printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD"
GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')"
./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache
env:
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_PASSWORD: ${{ secrets.GPG_SIGNING_PASSWORD }}
- name: Wait for Maven Central sync
run: |
TAG="${{ steps.determine-tag.outputs.tag }}"
# Strip 'v' prefix to get the Maven version
VERSION="${TAG#v}"
echo "Waiting for version $VERSION to sync to Maven Central. THIS CAN TAKE MANY HOURS! Godspeed"
./scripts/wait-for-maven.sh "$VERSION"