Skip to content

Developer Workflow with Changesets

This guide explains how to use changesets for version management and changelog generation in the ERP-Unlocked monorepo. For the full end-to-end release pipeline, see Releasing.

ERP-Unlocked uses Changesets to manage versions and changelogs across the monorepo. Each time you make a change to any app or package, you create a changeset that describes what changed and what type of change it is (major, minor, or patch).

The typical workflow for making changes:

  1. Create a new branch for your feature/fix
  2. Make your code changes
  3. Before committing: Create a changeset
  4. Commit both your changes and the changeset file
  5. Push and create a pull request against staging

After making your code changes, run:

Terminal window
pnpm changeset

The CLI will prompt you to select which apps or packages have changed. Use the arrow keys and spacebar to select from the workspace apps and packages:

Apps (apps/*):

  • @erp-unlocked/webapp (apps/webapp) - Main customer application
  • @erp-unlocked/internal (apps/internal) - Internal admin application
  • @repo/temporal-worker (apps/temporal-worker) - Primary Python Temporal worker
  • @repo/ts-temporal-worker (apps/ts-temporal-worker) - TypeScript Temporal worker
  • @erp-unlocked/dagster (apps/dagster) - Dagster data pipeline orchestration
  • @erp-unlocked/email-worker (apps/email-worker) - Inbound email Cloudflare Worker
  • ops-mcp (apps/ops-mcp), @erp-unlocked/content-mcp (apps/content-mcp), graph-mcp (apps/graph-mcp) - MCP servers
  • partner-data-api (apps/partner-data-api), tidycal-hubspot-sync (apps/tidycal-hubspot-sync), @repo/docs (apps/docs)

Shared Packages (packages/*):

  • @repo/db, @repo/ui, @repo/auth, @repo/utils, @repo/ai, @repo/observability, @repo/feature-flags, @repo/contracts, @repo/eval, @repo/integrations, @repo/mcp-oauth, @repo/pricing, @repo/mockoon (and Python packages packages/pdf-shared, packages/erp-data-py, packages/erp-sql-py, packages/feature-flags-py)

For each selected package, choose the type of change:

  • patch - Bug fixes and minor changes (0.1.0 → 0.1.1)
  • minor - New features, backward compatible (0.1.0 → 0.2.0)
  • major - Breaking changes (0.1.0 → 1.0.0)

Provide a clear, concise summary of the changes. This will appear in the changelog:

Good Examples:

Fixed order validation to properly handle decimal quantities
Added support for custom tax rates in the order editor
BREAKING: Removed support for legacy CSV format

Bad Examples:

Fixed bug
Updated code

The changeset will be saved to .changeset/random-words-here.md. Commit this file along with your code changes:

Terminal window
git add .changeset/random-words-here.md
git commit -m "feat: add custom tax rates support"

See what would be released based on current changesets:

Terminal window
pnpm version:check

For more detailed information about what will change:

Terminal window
pnpm version:preview

Verify that all necessary changesets are present:

Terminal window
pnpm changeset:status

Changesets uses Semantic Versioning (SemVer):

Use for:

  • Bug fixes
  • Documentation updates
  • Internal refactoring
  • Performance improvements

Example:

Terminal window
# Select: patch
# Summary: Fixed PDF extraction error for invoices with special characters

Use for:

  • New features
  • New API endpoints
  • Backward-compatible functionality additions
  • UI enhancements

Example:

Terminal window
# Select: minor
# Summary: Added bulk order import feature with CSV upload

Use for:

  • Breaking changes
  • API changes that require client updates
  • Removal of deprecated features
  • Database schema changes

Example:

Terminal window
# Select: major
# Summary: BREAKING: Changed authentication to require organization context

See Releasing for the authoritative runbook.

Staging Branch (Automated via release.yml + ordermatic-release-bot)

Section titled “Staging Branch (Automated via release.yml + ordermatic-release-bot)”
  1. All feature PRs merge into staging with a .changeset/*.md file (enforced by .husky/pre-commit and the Changeset required CI check).
  2. .github/workflows/release.yml runs on an hourly cron schedule (or via manual workflow_dispatch) against staging.
  3. Using the ordermatic-release-bot GitHub App token (RELEASE_APP_ID + RELEASE_APP_PRIVATE_KEY), release.yml opens or updates the Version Packages (staging) PR (changeset-release/staging), consuming pending .changeset/*.md files, bumping package.json versions, and updating CHANGELOG.md files.
  4. release.yml automatically approves and squash-merges the Version Packages (staging) PR once required status checks pass.
  5. Pushes to staging trigger .github/workflows/gcp-deploy.yml → GCP Cloud Build to deploy updated services to staging.
  1. No one merges or pushes to main directly, and release.yml never runs on main.
  2. A maintainer promotes staging to main by manually dispatching .github/workflows/auto-deploy-main.yml:
    Terminal window
    gh workflow run auto-deploy-main.yml --ref staging
  3. auto-deploy-main.yml verifies main is an ancestor of staging and fast-forwards main to the exact staging commit SHA, triggering production deploys via gcp-deploy.yml → Cloud Build.

Never run pnpm version:apply or scripts/release.sh locally on your machine, and never push directly to staging or main.

To trigger version consumption on staging immediately instead of waiting for the hourly cron:

Terminal window
# Consume pending changesets on staging and auto-merge Version Packages PR
gh workflow run release.yml --ref staging
# Promote staging to production (fast-forward main to staging)
gh workflow run auto-deploy-main.yml --ref staging

The repository has a .husky/pre-commit hook that enforces changeset creation. If you stage changes under apps/ or packages/ without also staging a .changeset/*.md file, the hook blocks the commit (exit 1):

⚠️ Staged changes under apps/ or packages/ but no staged .changeset/*.md.
Please run: pnpm changeset
Then git add the new file under .changeset/
Or skip with: git commit --no-verify

In rare cases where a changeset is not needed (e.g., CI config changes), you can skip the hook:

Terminal window
git commit --no-verify -m "ci: update workflow configuration"

Note: Use --no-verify sparingly. Most code changes should have a changeset.

Make sure you’ve made changes to files in apps/ or packages/ directories. Changesets only tracks versioned packages.

If multiple developers create changesets simultaneously, you may encounter conflicts in changeset files. To resolve:

  1. Keep both changeset files (they have unique names)
  2. Don’t try to merge the content
  3. Both changesets will be processed during release

If the pre-commit hook is not working:

Terminal window
# Reinstall hooks
pnpm prepare

Ensure the changeset file is committed and pushed:

Terminal window
git status
git add .changeset/*.md
git commit -m "chore: add changeset"
git push

Production and staging images in GCP Artifact Registry are built by cloudbuild.yaml and tagged with the git commit SHA (and latest), while package.json and CHANGELOG.md files track semantic versions via Changesets.

Terminal window
# 1. Make the fix
# 2. Create changeset
pnpm changeset
# Select: @erp-unlocked/webapp
# Type: patch
# Summary: Fixed date formatting in order history
# 3. Commit
git add .
git commit -m "fix: correct date formatting in order history"
git push

Example 2: New Feature Across Multiple Apps

Section titled “Example 2: New Feature Across Multiple Apps”
Terminal window
# 1. Implement feature in webapp and internal
# 2. Create changeset
pnpm changeset
# Select: @erp-unlocked/webapp, @erp-unlocked/internal
# Type: minor for both
# Summary: Added real-time order status updates
# 3. Commit
git add .
git commit -m "feat: add real-time order status updates"
git push
Terminal window
# 1. Make breaking changes to API
# 2. Create changeset
pnpm changeset
# Select: @erp-unlocked/webapp
# Type: major
# Summary: BREAKING: Changed /api/erp/orders endpoint to require organization context
# 3. Commit
git add .
git commit -m "feat!: require organization context in order endpoints"
git push
  1. One changeset per logical change - Don’t combine unrelated changes
  2. Write clear summaries - They become your changelog
  3. Use conventional commit messages - Helps with PR organization
  4. Create changesets early - Don’t wait until the PR is ready
  5. Review changesets in PRs - Ensure accuracy before merging
  6. Keep changesets focused - Smaller, focused changes are easier to review

For questions or issues with the changeset workflow, please reach out to the maintainers or create an issue in the repository.