Back to Blog

Monorepo Release Management: Changesets, Semantic Versioning, and Publish Pipelines

Manage releases in a monorepo: implement Changesets for versioning and changelogs, configure automated publish pipelines with GitHub Actions, handle peer dependency bumps, publish to npm with provenance, and coordinate breaking changes across packages.

Viprasol Tech Team
October 17, 2026
13 min read

Monorepo release management has two hard problems: coordinating version bumps across packages that depend on each other, and generating accurate changelogs from hundreds of commits. Changesets solves both by asking developers to declare the intent of their changes in small markdown files, then automating the version calculation and changelog generation from those declarations.


Changesets Workflow

Developer makes a change:
  1. git add, git commit (code change)
  2. pnpm changeset (declares what changed and semver impact)
     โ†’ creates .changeset/purple-lions-cry.md

When ready to release:
  3. pnpm changeset version (reads all .changeset files, bumps versions, generates CHANGELOG.md)
  4. pnpm changeset publish (builds packages, publishes to npm)

Setup

# Install Changesets
pnpm add -D @changesets/cli @changesets/changelog-github

# Initialize (creates .changeset/config.json)
pnpm changeset init
// .changeset/config.json
{
  "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
  "changelog": [
    "@changesets/changelog-github",
    { "repo": "viprasol/design-system" }
  ],
  "commit": false,
  "fixed": [],
  // Linked: packages in the same group always share the same version
  "linked": [
    ["@viprasol/tokens", "@viprasol/components", "@viprasol/icons"]
  ],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": ["@viprasol/docs"]  // Never publish the docs app
}

๐ŸŒ Looking for a Dev Team That Actually Delivers?

Most agencies sell you a project manager and assign juniors. Viprasol is different โ€” senior engineers only, direct Slack access, and a 5.0โ˜… Upwork record across 100+ projects.

  • React, Next.js, Node.js, TypeScript โ€” production-grade stack
  • Fixed-price contracts โ€” no surprise invoices
  • Full source code ownership from day one
  • 90-day post-launch support included

Writing Changesets

# Developer runs this after making changes
pnpm changeset

# Interactive prompt:
# ? Which packages would you like to include? 
#   โ—‰ @viprasol/components
#   โ—ฏ @viprasol/tokens
# ? Which type of change is this for @viprasol/components?
#   โ—‹ patch โ€” Bug fixes (0.0.X)
#   โ— minor โ€” New features, backwards-compatible (0.X.0)
#   โ—‹ major โ€” Breaking changes (X.0.0)
# ? Please enter a summary for this change:
#   > Add `size` prop to Button component with sm/md/lg/xl variants
<!-- .changeset/graceful-lions-run.md (auto-named) -->
---
"@viprasol/components": minor
---

Add `size` prop to `Button` component with `sm`, `md`, `lg`, and `xl` variants.
Previously all buttons used a single fixed size. The default is `md`, maintaining
backwards compatibility.

Automated Release Pipeline

# .github/workflows/release.yml
name: Release

on:
  push:
    branches:
      - main

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

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    permissions:
      contents: write        # Push version commits and tags
      pull-requests: write   # Create the "Version Packages" PR
      id-token: write        # npm provenance (signed publish)

    steps:
      - uses: actions/checkout@v4
        with:
          # Full history needed for changelog generation
          fetch-depth: 0
          # Use a PAT so pushed commits trigger other workflows
          token: ${{ secrets.RELEASE_BOT_PAT }}

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: "pnpm"
          registry-url: "https://registry.npmjs.org"

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build all packages
        run: pnpm -r build

      - name: Run tests
        run: pnpm -r test

      # The Changesets action does two things:
      # 1. If changesets exist: creates/updates a "Version Packages" PR
      # 2. If "Version Packages" PR is merged: publishes to npm
      - name: Create Release PR or Publish
        id: changesets
        uses: changesets/action@v1
        with:
          version: pnpm changeset version
          publish: pnpm changeset publish
          commit: "chore: release packages"
          title: "chore: release packages"
        env:
          GITHUB_TOKEN: ${{ secrets.RELEASE_BOT_PAT }}
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          # Provenance: signed attestation linking npm publish to GitHub Actions run
          NPM_CONFIG_PROVENANCE: "true"

      # Post release: create GitHub Releases for each published package
      - name: Create GitHub Releases
        if: steps.changesets.outputs.published == 'true'
        uses: actions/github-script@v7
        with:
          script: |
            const publishedPackages = JSON.parse('${{ steps.changesets.outputs.publishedPackages }}');
            for (const pkg of publishedPackages) {
              await github.rest.repos.createRelease({
                owner: context.repo.owner,
                repo: context.repo.repo,
                tag_name: `${pkg.name}@${pkg.version}`,
                name: `${pkg.name} v${pkg.version}`,
                generate_release_notes: false,
              });
            }

๐Ÿš€ Senior Engineers. No Junior Handoffs. Ever.

You get the senior developer, not a project manager who relays your requirements to someone you never meet. Every Viprasol project has a senior lead from kickoff to launch.

  • MVPs in 4โ€“8 weeks, full platforms in 3โ€“5 months
  • Lighthouse 90+ performance scores standard
  • Works across US, UK, AU timezones
  • Free 30-min architecture review, no commitment

Pre-Release Versions

# Enter pre-release mode for a major version
pnpm changeset pre enter alpha

# Any changesets added while in pre mode become pre-releases
# e.g., @viprasol/components 2.0.0-alpha.0, 2.0.0-alpha.1, etc.

pnpm changeset version   # Bumps to 2.0.0-alpha.1
pnpm changeset publish   # Publishes with --tag alpha

# Exit pre-release mode for final release
pnpm changeset pre exit
pnpm changeset version   # Finalizes to 2.0.0
pnpm changeset publish   # Publishes to latest tag

Handling Breaking Changes

# Breaking change workflow:
# 1. Add major changeset
pnpm changeset
# Select: major
# Message: "BREAKING: Remove deprecated `color` prop from Button. Use `variant` instead."

# 2. Optionally add a migration guide file
cat > .changeset/migration-v2.md << 'EOF'
# Migration Guide: @viprasol/components v2.0

Breaking Changes

Button: color prop removed

Before:

<Button color="blue">Click me</Button>

After:

<Button variant="primary">Click me</Button>

The variant prop supports: primary, secondary, outline, ghost, destructive. EOF


---

## Package.json for Published Packages

```json
// packages/components/package.json
{
  "name": "@viprasol/components",
  "version": "1.4.2",
  "description": "Viprasol design system components",
  "homepage": "https://design.viprasol.com",
  "repository": {
    "type": "git",
    "url": "https://github.com/viprasol/design-system",
    "directory": "packages/components"
  },
  "license": "MIT",
  "main": "./dist/index.js",
  "module": "./dist/index.mjs",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.js",
      "types": "./dist/index.d.ts"
    },
    "./package.json": "./package.json"
  },
  "files": [
    "dist",
    "!dist/**/*.test.*",
    "CHANGELOG.md"
  ],
  "sideEffects": false,
  "scripts": {
    "build": "tsup src/index.ts --format cjs,esm --dts",
    "typecheck": "tsc --noEmit",
    "test": "vitest run"
  },
  "peerDependencies": {
    "react": ">=18",
    "react-dom": ">=18"
  },
  "devDependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0"
  }
}

Verifying Published Packages

# Check npm provenance (signed attestation)
npm audit signatures @viprasol/components

# Verify package contents before release
pnpm pack --dry-run
# Lists all files that would be published โ€” check for accidental inclusions

# View the generated CHANGELOG before releasing
cat packages/components/CHANGELOG.md | head -50

# Check published versions
npm view @viprasol/components versions --json

# Deprecate a version if needed
npm deprecate @viprasol/components@1.3.0 "Security fix in 1.3.1, please upgrade"

Canary Releases from Feature Branches

# .github/workflows/canary.yml
name: Canary Release

on:
  push:
    branches:
      - "feat/**"
      - "fix/**"

jobs:
  canary:
    runs-on: ubuntu-latest
    if: github.actor != 'dependabot[bot]'
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          registry-url: "https://registry.npmjs.org"

      - run: pnpm install --frozen-lockfile
      - run: pnpm -r build

      - name: Publish canary
        run: |
          # Set version to canary with git SHA suffix
          SHA=$(git rev-parse --short HEAD)
          pnpm -r exec -- node -e "
            const pkg = require('./package.json');
            if (pkg.private) process.exit(0);
            pkg.version = pkg.version + '-canary.' + process.env.SHA;
            require('fs').writeFileSync('package.json', JSON.stringify(pkg, null, 2));
          "
          pnpm changeset publish --no-git-tag --tag canary
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
          SHA: ${{ github.sha }}

See Also


Working With Viprasol

Release management across a monorepo becomes a real engineering problem once you have multiple teams and packages with interdependencies. We set up Changesets pipelines, configure automated publish workflows with provenance signing, and establish the release conventions that keep your component library and shared packages easy to maintain.

Monorepo engineering โ†’ | Talk to our engineers โ†’

Share this article:

About the Author

V

Viprasol Tech Team

Custom Software Development Specialists

The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.

MT4/MT5 EA DevelopmentAI Agent SystemsSaaS DevelopmentAlgorithmic Trading

Need a Modern Web Application?

From landing pages to complex SaaS platforms โ€” we build it all with Next.js and React.

Free consultation โ€ข No commitment โ€ข Response within 24 hours

Viprasol ยท Web Development

Need a custom web application built?

We build React and Next.js web applications with Lighthouse โ‰ฅ90 scores, mobile-first design, and full source code ownership. Senior engineers only โ€” from architecture through deployment.