Skip to content

Release SDK

Release SDK #14

Workflow file for this run

name: Release SDK
on:
workflow_dispatch:
inputs:
version:
description: SDK version to release (SemVer, for example 1.2.3)
required: true
type: string
permissions:
contents: write
concurrency:
group: release-sdk
cancel-in-progress: false
jobs:
authorize:
name: Authorize release actor
runs-on: ubuntu-latest
steps:
- name: Ensure actor is maintainer or admin on main
uses: actions/github-script@v7
env:
TRIGGERING_ACTOR: ${{ github.triggering_actor }}
with:
script: |
const owner = context.repo.owner
const repo = context.repo.repo
const actor = process.env.TRIGGERING_ACTOR || context.actor
const refName = context.ref.replace("refs/heads/", "")
if (refName !== "main") {
core.setFailed(`Release workflow must be run from 'main'. Current ref is '${refName}'.`)
return
}
const response = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: actor
})
const permission = String(response.data.permission || "").toLowerCase()
const role = String(response.data.role_name || permission).toLowerCase()
const allowed = new Set(["maintain", "admin"])
core.info(`Actor '${actor}' has role='${role}', permission='${permission}'`)
if (!allowed.has(role)) {
core.setFailed(
`Only maintainers/admins can run this workflow. Actor '${actor}' has role '${role}' (permission '${permission}').`
)
}
checks:
name: Shared checks (with integration tests)
needs: authorize
uses: ./.github/workflows/shared-checks.yml
with:
run_integration_tests: true
secrets: inherit
publish:
name: Bump, tag, and publish release
needs: checks
runs-on: macos-latest
env:
RELEASE_VERSION: ${{ inputs.version }}
steps:
- name: Checkout triggering commit
uses: actions/checkout@v4
with:
ref: ${{ github.sha }}
fetch-depth: 0
token: ${{ secrets.IOS_RELEASE_PUSH_TOKEN }}
- name: Validate version input and detect rerun state
id: release_state
run: |
set -euo pipefail
version_file="Sources/ClerkKit/Utils/Version.swift"
if [[ ! "$RELEASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?$ ]]; then
echo "❌ Invalid version: '$RELEASE_VERSION'. Expected SemVer (for example 1.2.3 or 1.2.3-rc.1)."
exit 1
fi
current_version="$(sed -n 's/.*sdkVersion: String = "\([^"]*\)".*/\1/p' "$version_file")"
if [ -z "$current_version" ]; then
echo "❌ Could not read current SDK version from $version_file"
exit 1
fi
version_already_set="false"
if [ "$current_version" = "$RELEASE_VERSION" ]; then
version_already_set="true"
echo "ℹ️ $version_file already contains sdkVersion: String = \"$RELEASE_VERSION\"."
fi
release_tag="$RELEASE_VERSION"
tag_already_exists="false"
if git rev-parse --verify "refs/tags/$release_tag" >/dev/null 2>&1; then
tag_already_exists="true"
echo "ℹ️ Tag '$release_tag' already exists locally; skipping git tag \"$release_tag\"."
fi
if git ls-remote --tags origin "refs/tags/$release_tag" | grep -q "$release_tag"; then
tag_already_exists="true"
echo "ℹ️ Tag '$release_tag' already exists on origin; skipping git push origin \"$release_tag\"."
fi
echo "version_already_set=$version_already_set" >> "$GITHUB_OUTPUT"
echo "tag_already_exists=$tag_already_exists" >> "$GITHUB_OUTPUT"
- name: Update SDK version constant
if: steps.release_state.outputs.version_already_set != 'true'
run: |
set -euo pipefail
version_file="Sources/ClerkKit/Utils/Version.swift"
sed -i '' -E "s/(sdkVersion: String = \").*(\")/\\1$RELEASE_VERSION\\2/" "$version_file"
echo "Updated version file:"
grep -n "sdkVersion" "$version_file"
- name: Verify version change is present
run: |
set -euo pipefail
version_file="Sources/ClerkKit/Utils/Version.swift"
if ! grep -q "sdkVersion: String = \"$RELEASE_VERSION\"" "$version_file"; then
echo "❌ Failed to apply SDK version update in $version_file"
exit 1
fi
- name: Commit release version bump to main
run: |
set -euo pipefail
if [ "${{ steps.release_state.outputs.version_already_set }}" = "true" ]; then
echo "ℹ️ Skipping commit because Sources/ClerkKit/Utils/Version.swift already matches $RELEASE_VERSION."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Sources/ClerkKit/Utils/Version.swift
if git diff --cached --quiet; then
echo "❌ No changes to commit for release version bump"
exit 1
fi
git commit -m "chore(release): $RELEASE_VERSION"
git push origin HEAD:main
- name: Create and push release tag
run: |
set -euo pipefail
release_tag="$RELEASE_VERSION"
if [ "${{ steps.release_state.outputs.tag_already_exists }}" = "true" ]; then
echo "ℹ️ Skipping git tag \"$release_tag\" and push because tag already exists."
exit 0
fi
git tag "$release_tag"
git push origin "$release_tag"
- name: Determine prerelease flag
id: prerelease
run: |
if [[ "$RELEASE_VERSION" == *-* ]]; then
echo "value=true" >> "$GITHUB_OUTPUT"
else
echo "value=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish GitHub Release with generated notes
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.version }}
name: ${{ inputs.version }}
generate_release_notes: true
prerelease: ${{ steps.prerelease.outputs.value }}
token: ${{ secrets.IOS_RELEASE_PUSH_TOKEN }}