Skip to content

Release Sourcebot (Production) #14

Release Sourcebot (Production)

Release Sourcebot (Production) #14

Workflow file for this run

name: Release Sourcebot (Production)
permissions:
contents: read
packages: write
id-token: write
on:
workflow_dispatch:
inputs:
bump_type:
description: "Type of version bump to apply"
required: true
type: choice
options:
- patch
- minor
- major
concurrency:
group: release-sourcebot
cancel-in-progress: false
env:
# Use docker.io for Docker Hub if empty
REGISTRY_IMAGE: ghcr.io/sourcebot-dev/sourcebot
jobs:
prepare-release:
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version: ${{ steps.calculate_version.outputs.version }}
temp_branch: ${{ steps.push_temp_branch.outputs.temp_branch }}
steps:
- name: Generate GitHub App token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Calculate new version
id: calculate_version
run: |
# Extract current version from CHANGELOG.md
CURRENT_VERSION=$(grep -oP '## \[\K[0-9]+\.[0-9]+\.[0-9]+' CHANGELOG.md | head -n 1)
if [ -z "$CURRENT_VERSION" ]; then
echo "Error: Could not extract current version from CHANGELOG.md"
exit 1
fi
echo "Current version: $CURRENT_VERSION"
# Parse version components
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
# Apply bump based on input
BUMP_TYPE="${{ inputs.bump_type }}"
case "$BUMP_TYPE" in
major)
MAJOR=$((MAJOR + 1))
MINOR=0
PATCH=0
;;
minor)
MINOR=$((MINOR + 1))
PATCH=0
;;
patch)
PATCH=$((PATCH + 1))
;;
*)
echo "Error: Invalid bump type: $BUMP_TYPE"
exit 1
;;
esac
NEW_VERSION="$MAJOR.$MINOR.$PATCH"
echo "New version: $NEW_VERSION"
# Export to GITHUB_ENV for use in subsequent steps within this job
echo "VERSION=$NEW_VERSION" >> $GITHUB_ENV
# Export to GITHUB_OUTPUT for use in other jobs
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
- name: Check if version already exists
run: |
if grep -q "## \[$VERSION\]" CHANGELOG.md; then
echo "Error: Version $VERSION already exists in CHANGELOG.md"
exit 1
fi
if git tag | grep -q "^v$VERSION$"; then
echo "Error: Tag v$VERSION already exists"
exit 1
fi
- name: Update CHANGELOG.md and version.ts
run: |
DATE=$(date +%Y-%m-%d)
# Insert the new version header after the [Unreleased] line
sed -i "/## \[Unreleased\]/a\\
\\
## [$VERSION] - $DATE" CHANGELOG.md
echo "Updated CHANGELOG.md with version $VERSION"
cat CHANGELOG.md | head -n 15
# Update version.ts
cat > packages/shared/src/version.ts << EOF
// This file is auto-generated by .github/workflows/release-sourcebot.yml
export const SOURCEBOT_VERSION = "v$VERSION";
EOF
echo "Updated version.ts with version v$VERSION"
cat packages/shared/src/version.ts
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Commit changes
run: |
git add CHANGELOG.md packages/shared/src/version.ts
git commit -m "Release v$VERSION"
- name: Push to temporary branch
id: push_temp_branch
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
TEMP_BRANCH="release-v$VERSION"
git push origin HEAD:refs/heads/$TEMP_BRANCH
echo "Pushed commit to temporary branch: $TEMP_BRANCH"
echo "temp_branch=$TEMP_BRANCH" >> $GITHUB_OUTPUT
build:
needs: prepare-release
uses: ./.github/workflows/_build.yml
with:
git_ref: ${{ needs.prepare-release.outputs.temp_branch }}
docker_tags: |
type=raw,value=v${{ needs.prepare-release.outputs.version }}
type=raw,value=latest
use_app_token: true
secrets:
release_app_id: ${{ secrets.RELEASE_APP_ID }}
release_app_private_key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
finalize-release:
needs: [prepare-release, build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Generate GitHub App token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Checkout temporary branch
uses: actions/checkout@v4
with:
ref: ${{ needs.prepare-release.outputs.temp_branch }}
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Fast-forward main to temporary branch
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
VERSION: ${{ needs.prepare-release.outputs.version }}
TEMP_BRANCH: ${{ needs.prepare-release.outputs.temp_branch }}
run: |
# Fetch main branch
git fetch origin main:main
git checkout main
# Check if fast-forward is possible
if ! git merge-base --is-ancestor main "$TEMP_BRANCH"; then
echo "❌ ERROR: Cannot fast-forward main branch to release commit"
echo ""
echo "This means new commits were pushed to main after the release process started."
echo ""
echo "Recent commits on main that caused the conflict:"
git log --oneline $TEMP_BRANCH..main | head -5
exit 1
fi
# Fast-forward main to release commit
git merge --ff-only "$TEMP_BRANCH"
echo "✓ Successfully fast-forwarded main to release commit"
- name: Create annotated tag
env:
VERSION: ${{ needs.prepare-release.outputs.version }}
run: |
git tag -a "v$VERSION" -m "sourcebot v$VERSION"
echo "Created tag v$VERSION"
- name: Push main and tag
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
run: |
git push origin main
git push origin --tags
echo "Pushed main branch and tags"
- name: Create GitHub release
env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }}
VERSION: ${{ needs.prepare-release.outputs.version }}
run: |
gh release create "v$VERSION" \
--verify-tag \
--generate-notes \
--latest
publish-to-registry:
needs: [prepare-release, build, finalize-release]
uses: ./.github/workflows/_merge.yml
with:
docker_tags: |
type=raw,value=v${{ needs.prepare-release.outputs.version }}
type=raw,value=latest
update-helm-chart:
needs: [finalize-release, publish-to-registry]
permissions:
contents: write
pull-requests: write
uses: sourcebot-dev/sourcebot-helm-chart/.github/workflows/update-sourcebot-version.yaml@main
secrets: inherit
cleanup:
needs: [prepare-release, build, publish-to-registry, finalize-release, update-helm-chart]
if: always() && needs.prepare-release.outputs.temp_branch != ''
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Generate GitHub App token
id: generate_token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.generate_token.outputs.token }}
- name: Delete temporary branch
env:
TEMP_BRANCH: ${{ needs.prepare-release.outputs.temp_branch }}
run: |
# Check if branch exists before attempting to delete
if git ls-remote --heads origin "$TEMP_BRANCH" | grep -q "$TEMP_BRANCH"; then
git push origin --delete "$TEMP_BRANCH"
echo "✓ Deleted temporary branch: $TEMP_BRANCH"
else
echo "ℹ Temporary branch $TEMP_BRANCH does not exist (may have been already deleted)"
fi