Release Packages #18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Packages | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| dry_run: | |
| description: "Dry run (no actual release)" | |
| required: true | |
| default: false | |
| type: boolean | |
| # Ensure only one release can run at a time | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| # Permissions: add id-token for OIDC; keep others for PRs | |
| permissions: | |
| id-token: write | |
| contents: write | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| quality: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Get pnpm store directory | |
| id: pnpm-cache | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Run format check | |
| run: pnpm format | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| needs: quality | |
| environment: publish | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| registry-url: "https://registry.npmjs.org" | |
| - name: Ensure npm >= 11.5.1 for OIDC | |
| run: npm i -g npm@^11.5.1 | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Get pnpm store directory | |
| id: pnpm-cache | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store- | |
| - name: Install dependencies | |
| run: pnpm install | |
| # If you have PRIVATE deps, uncomment and set a read-only token: | |
| # env: | |
| # NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }} | |
| - name: Cache Firebase emulators | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/firebase/emulators | |
| key: ${{ runner.os }}-firebase-emulators-${{ hashFiles('.github/workflows/release.yml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-firebase-emulators- | |
| - name: Install Firebase CLI | |
| uses: nick-invision/retry@v3 | |
| with: | |
| timeout_minutes: 10 | |
| retry_wait_seconds: 60 | |
| max_attempts: 3 | |
| command: npm i -g firebase-tools@latest | |
| - name: Run tests with emulator | |
| run: pnpm test:emulator | |
| - name: Build packages | |
| run: pnpm turbo build | |
| - name: Verify build outputs | |
| run: | | |
| echo "Checking build outputs..." | |
| MISSING_BUILDS="" | |
| for PKG_DIR in packages/*; do | |
| if [ -d "$PKG_DIR" ] && [ -f "$PKG_DIR/package.json" ]; then | |
| PKG_NAME=$(basename "$PKG_DIR") | |
| if [ ! -d "$PKG_DIR/dist" ]; then | |
| MISSING_BUILDS="$MISSING_BUILDS $PKG_NAME" | |
| fi | |
| fi | |
| done | |
| if [ -n "$MISSING_BUILDS" ]; then | |
| echo "❌ Build outputs missing for: $MISSING_BUILDS" | |
| exit 1 | |
| fi | |
| echo "✅ All build outputs verified" | |
| - name: Create Release Pull Request or Publish | |
| if: ${{ !inputs.dry_run }} | |
| id: changesets | |
| uses: changesets/action@v1 | |
| with: | |
| publish: pnpm release # runs: pnpm build && changeset publish | |
| commit: "chore: version packages" | |
| title: "chore: version packages" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| # NPM_TOKEN removed – OIDC will be used automatically | |
| - name: Dry Run - Show Changes | |
| if: ${{ inputs.dry_run }} | |
| run: | | |
| echo "🔍 This is a dry run. The following changes would be made:" | |
| echo "" | |
| echo "📋 Changeset contents:" | |
| for file in .changeset/*.md; do | |
| if [ -f "$file" ] && [ "$(basename "$file")" != "README.md" ]; then | |
| echo "--- $(basename "$file") ---" | |
| cat "$file" | |
| echo "" | |
| fi | |
| done | |
| echo "📦 Version changes that would be applied:" | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| ORIGINAL_HEAD=$(git rev-parse HEAD) | |
| FALLBACK_ID=${GITHUB_RUN_ID:-$RANDOM$RANDOM} | |
| TEMP_BRANCH="dry-run-temp-$FALLBACK_ID" | |
| git checkout -b "$TEMP_BRANCH" | |
| pnpm changeset version | |
| echo "" | |
| echo "🔍 Changed files:" | |
| git diff --name-status "$ORIGINAL_HEAD" | |
| echo "" | |
| echo "🔍 Package version changes:" | |
| VERSION_CHANGES=$(git diff "$ORIGINAL_HEAD" -- '**/package.json' | grep -E "^[+-]\s*\"version\"" || true) | |
| if [ -z "$VERSION_CHANGES" ]; then | |
| echo " No version changes detected (this might indicate an issue with changesets)" | |
| else | |
| echo "$VERSION_CHANGES" | |
| fi | |
| git checkout - | |
| git branch -D "$TEMP_BRANCH" | |
| echo "" | |
| echo "✅ Dry run completed successfully" |