Skip to content

Instantly share code, notes, and snippets.

@FranciscoMoretti
Created October 23, 2025 07:22
Show Gist options
  • Select an option

  • Save FranciscoMoretti/15566f23e6e8babbf551f94f6b4d2990 to your computer and use it in GitHub Desktop.

Select an option

Save FranciscoMoretti/15566f23e6e8babbf551f94f6b4d2990 to your computer and use it in GitHub Desktop.
ai-registry: Changesets + Release workflow + Vercel deploy

NPM releases for a pnpm monorepo (GitHub Actions + Changesets)

Minimal, reliable setup to auto-version, create GitHub Releases, and publish to npm from main using Changesets. No GitHub App required (uses GITHUB_TOKEN).

What this does

  • Opens a "Version Packages" PR when changesets land on main.
  • On merging that PR, publishes to npm and creates GitHub Releases.
  • Optionally deploys to Vercel after publish (see VERCEL_DEPLOYMENTS.md).

1) Install and initialize Changesets

pnpm add -D @changesets/cli
pnpm changeset init

Root package.json scripts (recommended):

{
  "scripts": {
    "changeset": "changeset",
    "version": "changeset version && pnpm install -r --no-frozen-lockfile",
    "publish-packages": "changeset publish"
  }
}

.changeset/config.json (sane defaults):

{
  "$schema": "https://unpkg.com/@changesets/config/schema.json",
  "changelog": "@changesets/changelog-git",
  "commit": true,
  "fixed": [],
  "linked": [],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}

For public scoped packages (e.g. @scope/pkg), add to each published package:

{
  "publishConfig": { "access": "public" }
}

2) GitHub Actions workflow

Create .github/workflows/release.yml (adjust the build step for your workspace):

name: Release

on:
  push:
    branches:
      - main

concurrency: ${{ github.workflow }}-${{ github.ref }}

permissions:
  contents: write
  pull-requests: write
  id-token: write

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4

      - name: Setup Git User
        run: |
          git config --global user.email "ai-registry-bot[bot]@users.noreply.github.com"
          git config --global user.name "ai-registry-bot[bot]"

      - name: Setup pnpm
        uses: pnpm/action-setup@v4

      - name: Setup Node.js 22
        uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: "https://registry.npmjs.org"

      - name: Install Dependencies
        run: pnpm i

      # Build all packages. If you prefer a single package:
      # run: pnpm build --filter <your-package-name>
      - name: Build Packages
        run: pnpm -r build

      - name: Run Tests
        run: pnpm test

      - name: Create Release Pull Request or Publish to npm
        id: changesets
        uses: changesets/action@v1
        with:
          version: pnpm changeset version
          publish: pnpm changeset publish
          createGithubReleases: true
          setupGitUser: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

      # Optional: deploy to Vercel after publish
      # See VERCEL_DEPLOYMENTS.md for a monorepo-friendly variant
      - name: Deploy to Vercel
        if: steps.changesets.outputs.published == 'true'
        run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
        env:
          VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
          VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

Notes:

  • If you filter the build step, make sure the name matches your package (e.g. @airegistry/vercel-gateway).
  • Use Node 20 if required by dependencies (change node-version: 22).

3) Repo settings and secrets

Repo → Settings → Actions → General

  • Workflow permissions: "Read and write permissions"
  • Check: "Allow GitHub Actions to create and approve pull requests"

Repo → Settings → Secrets and variables → Actions

  • NPM_TOKEN: npm Automation token (required)
  • Optional Vercel: VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID

Create npm Automation token (bypasses 2FA for CI):

gh secret set NPM_TOKEN --repo <owner>/<repo> --body 'npm_XXXXXXXXXXXXXXXXXXXXXXXX'

4) Daily flow

# on a feature branch
pnpm changeset     # select packages + bump types
git add . && git commit -m "chore: changeset" && git push

# merge PR into main → CI opens "Version Packages" PR
# merge that PR → CI publishes to npm & creates GitHub Releases

5) Troubleshooting

  • Error: GitHub Actions not permitted to create or approve PRs

    • Enable the two settings in step 3 (permissions + allow create/approve PRs).
  • E404 on publish to a scoped package

    • You must own the npm scope. Either:
      • Create/claim the org for the scope and ensure your user (token owner) is a maintainer, or
      • Change the package scope to one you own (e.g. @airegistry/...) or publish unscoped.
    • Ensure publishConfig.access = public on public scoped packages.
  • Verify npm auth in CI

- name: Debug npm auth
  run: |
    npm config get registry
    npm whoami
  • Build failures

    • Ensure each published package has a build script and is included in pnpm-workspace.yaml.
    • If filtering a single package, use pnpm build --filter <pkg>.
  • Need CI commits to trigger other workflows

    • Use a PAT secret instead of GITHUB_TOKEN and pass it to checkout and the Changesets step.

6) Vercel deploys (optional)

Use the built-in step above or see VERCEL_DEPLOYMENTS.md for a monorepo-targeted version with working-directory: apps/website and how to retrieve ORG_ID/PROJECT_ID.

name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
pull-requests: write
id-token: write
jobs:
release:
name: Release
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# Using default GITHUB_TOKEN; GitHub App token generation removed
- name: Checkout Repo
uses: actions/checkout@v4
- name: Setup Git User
run: |
git config --global user.email "airegistry-bot[bot]@users.noreply.github.com"
git config --global user.name "airegistry-bot[bot]"
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js 22
uses: actions/setup-node@v4
with:
node-version: 22
registry-url: "https://registry.npmjs.org"
- name: Install Dependencies
run: pnpm i
- name: Build Packages
run: pnpm build --filter @airegistry/vercel-gateway
- name: Run Tests
run: pnpm test
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@v1
with:
version: pnpm changeset version
publish: pnpm changeset publish
createGithubReleases: true
setupGitUser: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Deploy to Vercel
run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
env:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

Vercel deployments via custom release workflow

This repo deploys to Vercel from a GitHub Actions release workflow. Below is the minimal, reliable setup and the exact CI step used here.

1) Create a Vercel token

  • Vercel Dashboard → Account Settings → Tokens → Create (or https://vercel.com/account/tokens).
  • Copy it once; you can’t view it again.

Sanity check (locally):

npx vercel whoami --token="$VERCEL_TOKEN"

2) Get your Org ID and Project ID

Fastest (repo-linked):

cat apps/website/.vercel/project.json
# {"projectId":"prj_xxx","orgId":"team_xxx"}  # or "user_xxx"

If the file doesn’t exist yet (safe, non-deploy fetch):

npx vercel pull --yes --environment=production --token="$VERCEL_TOKEN" --cwd apps/website
cat apps/website/.vercel/project.json

From the dashboard:

  • Project → Settings → General → “Project ID” (looks like prj_xxx)
  • Team: Team Settings → General → “Team ID” (team_xxx)
  • Personal: Account Settings → “User ID” (user_xxx)

3) Store them as GitHub Actions secrets

In your repo: Settings → Secrets and variables → Actions → New repository secret

  • VERCEL_TOKEN
  • VERCEL_ORG_ID (e.g., team_xxx or user_xxx)
  • VERCEL_PROJECT_ID (e.g., prj_xxx)

4) Add the deploy step to your workflow

If your app lives in apps/website, run the step from that directory to ensure the correct project context:

- name: Deploy to Vercel
  working-directory: apps/website
  run: npx vercel --prod --token=${{ secrets.VERCEL_TOKEN }}
  env:
    VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
    VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

This repo already contains a release workflow at /.github/workflows/release.yml with the Vercel deploy step. The snippet above is identical except for working-directory, which you may prefer for monorepos.

5) Troubleshooting

  • “Not authorized” → Check VERCEL_TOKEN and whether it has access to the org/project.
  • “Project not found” → VERCEL_PROJECT_ID mismatch (confirm in .vercel/project.json or dashboard).
  • “Missing project settings” → Run npx vercel pull --yes --environment=production --token="$VERCEL_TOKEN" --cwd apps/website.
  • Monorepo issues → Ensure the step runs in the app directory or a .vercel/project.json exists there.

References

  • Vercel CLI pull: https://vercel.com/docs/cli#commands/pull
  • Projects API: https://vercel.com/docs/rest-api/endpoints/projects#get-a-project
  • Teams API: https://vercel.com/docs/rest-api/endpoints/teams
  • User API: https://vercel.com/docs/rest-api/endpoints/users#get-the-authenticated-user
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment