Skip to content

Merge pull request #183 from fbosch/release-please--branches--master-… #77

Merge pull request #183 from fbosch/release-please--branches--master-…

Merge pull request #183 from fbosch/release-please--branches--master-… #77

name: Release Please
on:
push:
branches: [master]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
issues: write
# Release workflows must never be cancelled mid-flight to avoid
# leaving release PRs or tags in an inconsistent state.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
release-please:
name: Prepare Release
runs-on: ubuntu-latest
timeout-minutes: 15
outputs:
release_created: ${{ steps.release.outputs.release_created }}
tag_name: ${{ steps.release.outputs.tag_name }}
steps:
- name: Run release-please
id: release
uses: googleapis/release-please-action@16a9c90856f42705d54a6fda1823352bdc62cf38 # v4.4.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
- name: Release output
if: ${{ steps.release.outputs.release_created }}
run: |
echo "Release created"
echo "Tag: ${{ steps.release.outputs.tag_name }}"
echo "URL: ${{ steps.release.outputs.html_url }}"
deploy-production:
name: Deploy to Vercel Production
permissions:
contents: read
needs: release-please
if: ${{ needs.release-please.outputs.release_created == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 20
environment: Production
concurrency:
group: production-deploy
cancel-in-progress: false
env:
VERCEL_NEXT_BUNDLED_SERVER: '1'
NEXT_PUBLIC_VERCEL_ENV: production
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
steps:
- name: Checkout release tag
uses: actions/checkout@v4
with:
ref: ${{ needs.release-please.outputs.tag_name }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Setup pnpm
uses: pnpm/action-setup@f40ffcd9367d9f12939873eb1018b921a783ffaa # v4
- name: Validate Vercel secrets
run: |
for required_var in VERCEL_TOKEN VERCEL_ORG_ID VERCEL_PROJECT_ID; do
if [ -z "${!required_var}" ]; then
echo "::error::Missing required secret: ${required_var}"
exit 1
fi
done
- name: Install Vercel CLI
uses: ./.github/actions/install-vercel-cli
- name: Pull Vercel production settings
run: vercel pull --yes --environment=production --token="$VERCEL_TOKEN"
- name: Build production artifacts
run: vercel build --prod --token="$VERCEL_TOKEN"
- name: Deploy prebuilt artifacts to production
id: deploy
run: |
deployment_url="$(vercel deploy --prebuilt --prod --token="$VERCEL_TOKEN")"
echo "deployment_url=$deployment_url" >> "$GITHUB_OUTPUT"
- name: Verify deployment health
run: |
deployment_url="${{ steps.deploy.outputs.deployment_url }}"
if [[ "$deployment_url" != http* ]]; then
deployment_url="https://$deployment_url"
fi
http_status="$(curl \
--silent \
--show-error \
--location \
--retry 6 \
--retry-delay 5 \
--retry-all-errors \
--write-out '%{http_code}' \
--output /dev/null \
"$deployment_url")"
if [[ "$http_status" == "401" || "$http_status" == "403" ]]; then
echo "Deployment is reachable but access-protected (HTTP $http_status)."
exit 0
fi
if [[ "$http_status" != "200" ]]; then
echo "::error::Deployment health check failed with HTTP $http_status"
exit 1
fi
- name: Publish deployment summary
run: |
echo "### Production Deployment" >> "$GITHUB_STEP_SUMMARY"
echo "- Tag: \`${{ needs.release-please.outputs.tag_name }}\`" >> "$GITHUB_STEP_SUMMARY"
echo "- URL: \`${{ steps.deploy.outputs.deployment_url }}\`" >> "$GITHUB_STEP_SUMMARY"