Skip to content

chore(test): refresh e2e fixtures #787

chore(test): refresh e2e fixtures

chore(test): refresh e2e fixtures #787

Workflow file for this run

name: Release
on:
push:
branches: [main]
issue_comment:
types: [created]
concurrency:
group: release-${{ github.event_name == 'issue_comment' && format('snapshot-{0}', github.event.issue.number) || 'main' }}
cancel-in-progress: false
permissions:
contents: read
jobs:
# ═══════════════════════════════════════════════════════════════════════
# Push to main → stable or canary release
# ═══════════════════════════════════════════════════════════════════════
ci:
if: github.event_name == 'push'
uses: ./.github/workflows/ci.yml
secrets: inherit
versioning:
needs: [ci]
if: github.event_name == 'push'
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 5
permissions:
contents: write
pull-requests: write
outputs:
release_created: ${{ steps.check.outputs.release_created }}
version: ${{ steps.check.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- uses: actions/cache/restore@v6
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: bun-${{ runner.os }}-
- run: bun install --frozen-lockfile
- name: Check if release needed
id: check
run: bun run scripts/check-release.ts
- id: changesets
uses: changesets/action@v1
with:
version: bun run version-packages
commit: "ci(repo): version packages"
title: "ci(repo): Version Packages"
env:
GITHUB_TOKEN: ${{ github.token }}
# ─── Stable release ────────────────────────────────────────────────
build:
needs: versioning
if: needs.versioning.outputs.release_created == 'true'
uses: ./.github/workflows/build-binaries.yml
with:
version: ${{ needs.versioning.outputs.version }}
ref: ${{ github.sha }}
artifact-prefix: clerk
secrets: inherit
sign-macos:
needs: [versioning, build]
if: needs.versioning.outputs.release_created == 'true'
uses: ./.github/workflows/sign-macos.yml
with:
artifact-prefix: clerk
secrets:
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
smoke-test:
needs: [versioning, build, sign-macos]
uses: ./.github/workflows/smoke-test.yml
with:
version: ${{ needs.versioning.outputs.version }}
artifact-prefix: clerk
preset: stable
publish-npm:
needs: [versioning, build, sign-macos, smoke-test]
# Must run on GitHub-hosted runner for npm OIDC trusted publishing
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@v8
with:
pattern: clerk-*
path: dist/artifacts
- name: Publish packages
run: bun run release
env:
ARTIFACTS_DIR: ${{ github.workspace }}/dist/artifacts
GH_TOKEN: ${{ github.token }}
publish-github:
needs: [versioning, build, sign-macos, smoke-test, publish-npm]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
pattern: clerk-*
path: dist/artifacts
- name: Upload binaries to GitHub Release
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
tag="v${{ needs.versioning.outputs.version }}"
for dir in dist/artifacts/clerk-*/; do
target=${dir#dist/artifacts/clerk-} && target=${target%/}
ext=""; [[ "$target" == win32-* ]] && ext=".exe"
cp "${dir}clerk${ext}" "${dir}clerk-${target}${ext}"
gh release upload "$tag" "${dir}clerk-${target}${ext}" --clobber
done
homebrew:
needs: [versioning, build, sign-macos, smoke-test, publish-npm]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@v8
with:
pattern: clerk-{darwin-arm64,darwin-x64,linux-arm64,linux-x64}
path: dist/artifacts
- name: Publish Homebrew formula
run: bun run scripts/homebrew.ts --version "$VERSION"
env:
VERSION: ${{ needs.versioning.outputs.version }}
ARTIFACTS_DIR: ${{ github.workspace }}/dist/artifacts
GH_TOKEN: ${{ github.token }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
notify-stable-failure:
if: >-
always() &&
contains(needs.*.result, 'failure')
needs: [ci, versioning, build, sign-macos, smoke-test, publish-npm, publish-github, homebrew]
uses: ./.github/workflows/notify-failure.yml
with:
workflow-name: Stable release
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
notify-stable-success:
needs: [versioning, publish-npm, publish-github, homebrew]
if: needs.versioning.outputs.release_created == 'true'
uses: ./.github/workflows/notify-release.yml
with:
version: ${{ needs.versioning.outputs.version }}
secrets:
SLACK_RELEASE_WEBHOOK_URL: ${{ secrets.SLACK_RELEASE_WEBHOOK_URL }}
# ─── Canary release ────────────────────────────────────────────────
canary-version:
needs: versioning
if: needs.versioning.outputs.release_created != 'true'
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 5
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- uses: actions/cache/restore@v6
with:
path: ~/.bun/install/cache
key: bun-${{ runner.os }}-${{ hashFiles('bun.lock') }}
restore-keys: bun-${{ runner.os }}-
- run: bun install --frozen-lockfile
- name: Version packages for canary
id: version
run: |
bun run version-packages:canary
version=$(jq -r '.version' packages/cli/package.json)
echo "version=${version}" >> "$GITHUB_OUTPUT"
canary-build:
needs: canary-version
uses: ./.github/workflows/build-binaries.yml
with:
version: ${{ needs.canary-version.outputs.version }}
ref: ${{ github.sha }}
artifact-prefix: clerk-canary
secrets: inherit
canary-sign-macos:
needs: [canary-version, canary-build]
uses: ./.github/workflows/sign-macos.yml
with:
artifact-prefix: clerk-canary
secrets:
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
canary-smoke-test:
needs: [canary-version, canary-build, canary-sign-macos]
uses: ./.github/workflows/smoke-test.yml
with:
version: ${{ needs.canary-version.outputs.version }}
artifact-prefix: clerk-canary
preset: canary
canary-publish-github:
needs: [canary-version, canary-build, canary-sign-macos, canary-smoke-test]
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: write
steps:
- uses: actions/download-artifact@v8
with:
pattern: clerk-canary-*
path: dist/artifacts
- name: Create pre-release and upload binaries
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
tag="v${{ needs.canary-version.outputs.version }}"
# Create GitHub Release as a pre-release
gh release view "$tag" --repo "$GH_REPO" 2>/dev/null || \
gh release create "$tag" \
--repo "$GH_REPO" \
--title "$tag" \
--target "${{ github.sha }}" \
--prerelease \
--notes "Canary release \`$tag\`"
# Upload binaries
for dir in dist/artifacts/clerk-canary-*/; do
target=${dir#dist/artifacts/clerk-canary-} && target=${target%/}
ext=""; [[ "$target" == win32-* ]] && ext=".exe"
cp "${dir}clerk${ext}" "${dir}clerk-${target}${ext}"
gh release upload "$tag" "${dir}clerk-${target}${ext}" \
--repo "$GH_REPO" --clobber
done
canary-publish-npm:
needs:
[canary-version, canary-build, canary-smoke-test, canary-publish-github]
# Must run on GitHub-hosted runner for npm OIDC trusted publishing.
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@v8
with:
pattern: clerk-canary-*
path: dist/artifacts
- name: Rename artifact directories
run: |
cd dist/artifacts
for dir in clerk-canary-*/; do
target=${dir#clerk-canary-} && target=${target%/}
mv "$dir" "clerk-${target}"
done
- name: Publish canary packages
run: bun run release:canary --version "$CANARY_VERSION"
env:
CANARY_VERSION: ${{ needs.canary-version.outputs.version }}
ARTIFACTS_DIR: ${{ github.workspace }}/dist/artifacts
GH_TOKEN: ${{ github.token }}
notify-canary-failure:
if: >-
always() &&
contains(needs.*.result, 'failure')
needs:
[
ci,
canary-version,
canary-build,
canary-sign-macos,
canary-smoke-test,
canary-publish-github,
canary-publish-npm,
]
uses: ./.github/workflows/notify-failure.yml
with:
workflow-name: Canary release
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
# ═══════════════════════════════════════════════════════════════════════
# PR comment (!snapshot) → snapshot release
# ═══════════════════════════════════════════════════════════════════════
snapshot:
# Intentionally restricted to MEMBER and OWNER — external collaborators
# (COLLABORATOR association) cannot trigger snapshots. This is a deliberate
# security boundary: snapshot publishing has npm write access via OIDC.
if: >-
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '!snapshot') &&
contains(fromJSON('["MEMBER","OWNER"]'), github.event.comment.author_association)
runs-on: blacksmith-2vcpu-ubuntu-2404
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
outputs:
version: ${{ steps.version.outputs.version }}
sha: ${{ steps.pr.outputs.sha }}
is_fork: ${{ steps.pr.outputs.is_fork }}
steps:
- name: React to comment
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
gh api "repos/${GH_REPO}/issues/comments/${{ github.event.comment.id }}/reactions" \
-f content=eyes --silent
- name: Get PR head SHA
id: pr
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
pr_json=$(gh api "repos/${GH_REPO}/pulls/${{ github.event.issue.number }}")
sha=$(echo "$pr_json" | jq -r '.head.sha')
head_repo=$(echo "$pr_json" | jq -r '.head.repo.full_name')
base_repo=$(echo "$pr_json" | jq -r '.base.repo.full_name')
is_fork="false"
if [ "$head_repo" != "$base_repo" ]; then
is_fork="true"
echo "::warning::Snapshot requested on fork PR (head: ${head_repo}) — publish will be skipped."
fi
echo "sha=${sha}" >> "$GITHUB_OUTPUT"
echo "is_fork=${is_fork}" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@v7
with:
ref: ${{ steps.pr.outputs.sha }}
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- name: Compute snapshot version
id: version
env:
COMMENT_BODY: ${{ github.event.comment.body }}
run: |
# Extract optional name from "!snapshot <name>" — default to "snapshot"
name=$(echo "$COMMENT_BODY" | sed 's/^!snapshot[[:space:]]*//' | tr -cd 'a-zA-Z0-9-')
if [ -z "$name" ]; then name="snapshot"; fi
bun run version-packages:snapshot -- "$name"
version=$(jq -r '.version' packages/cli/package.json)
echo "version=${version}" >> "$GITHUB_OUTPUT"
snapshot-ci:
needs: snapshot
if: needs.snapshot.outputs.is_fork != 'true'
uses: ./.github/workflows/ci.yml
with:
ref: ${{ needs.snapshot.outputs.sha }}
secrets: inherit
snapshot-build:
needs: [snapshot, snapshot-ci]
if: needs.snapshot.outputs.is_fork != 'true'
uses: ./.github/workflows/build-binaries.yml
with:
version: ${{ needs.snapshot.outputs.version }}
ref: ${{ needs.snapshot.outputs.sha }}
artifact-prefix: clerk-snapshot
secrets: inherit
snapshot-sign-macos:
needs: [snapshot, snapshot-build]
if: needs.snapshot.outputs.is_fork != 'true'
uses: ./.github/workflows/sign-macos.yml
with:
artifact-prefix: clerk-snapshot
secrets:
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_API_KEY_BASE64: ${{ secrets.APPLE_API_KEY_BASE64 }}
APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }}
APPLE_API_ISSUER_ID: ${{ secrets.APPLE_API_ISSUER_ID }}
snapshot-smoke-test:
needs: [snapshot, snapshot-build, snapshot-sign-macos]
if: needs.snapshot.outputs.is_fork != 'true'
uses: ./.github/workflows/smoke-test.yml
with:
version: ${{ needs.snapshot.outputs.version }}
artifact-prefix: clerk-snapshot
preset: snapshot
snapshot-publish:
needs: [snapshot, snapshot-build, snapshot-sign-macos, snapshot-smoke-test]
if: needs.snapshot.outputs.is_fork != 'true'
# Must run on GitHub-hosted runner for npm OIDC trusted publishing
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pull-requests: write
id-token: write
steps:
- uses: actions/checkout@v7
with:
ref: ${{ needs.snapshot.outputs.sha }}
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v6
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- run: bun install --frozen-lockfile
- uses: actions/download-artifact@v8
with:
pattern: clerk-snapshot-*
path: dist/artifacts
- name: Rename artifact directories
run: |
cd dist/artifacts
for dir in clerk-snapshot-*/; do
target=${dir#clerk-snapshot-} && target=${target%/}
mv "$dir" "clerk-${target}"
done
- name: Publish snapshot packages
run: bun run release:snapshot --version "$SNAPSHOT_VERSION"
env:
SNAPSHOT_VERSION: ${{ needs.snapshot.outputs.version }}
ARTIFACTS_DIR: ${{ github.workspace }}/dist/artifacts
- name: React with rocket
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
gh api "repos/${GH_REPO}/issues/comments/${{ github.event.comment.id }}/reactions" \
-f content=rocket --silent
- name: Post installation comment
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
SNAPSHOT_VERSION: ${{ needs.snapshot.outputs.version }}
SNAPSHOT_SHA: ${{ needs.snapshot.outputs.sha }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
short_sha=$(echo "${SNAPSHOT_SHA}" | cut -c1-7)
{
echo '## Snapshot published'
echo ''
echo '```sh'
echo "npm install -g clerk@${SNAPSHOT_VERSION}"
echo '```'
echo ''
echo '| Package | Version |'
echo '|---------|---------|'
echo "| \`clerk\` | \`${SNAPSHOT_VERSION}\` |"
echo ''
echo "> Published from ${short_sha}"
} > /tmp/comment-body.md
gh pr comment "${PR_NUMBER}" --repo "${GH_REPO}" --body-file /tmp/comment-body.md
snapshot-notify-failure:
needs:
[snapshot, snapshot-ci, snapshot-build, snapshot-sign-macos, snapshot-smoke-test, snapshot-publish]
if: >-
always() &&
contains(needs.*.result, 'failure')
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: write
steps:
- name: React with confused emoji
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
run: |
gh api "repos/${GH_REPO}/issues/comments/${{ github.event.comment.id }}/reactions" \
-f content=confused --silent
- name: Post failure comment
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
run: |
{
echo '## Snapshot failed'
echo ''
echo "The snapshot publish workflow failed. [View the workflow run](${RUN_URL}) for details."
} > /tmp/comment-body.md
gh pr comment "${PR_NUMBER}" --repo "${GH_REPO}" --body-file /tmp/comment-body.md