skills/codervisor/forge/monorepo-version-sync

monorepo-version-sync

SKILL.md

Monorepo Version Sync

Teach agents how to manage coordinated versioning across a polyglot monorepo with Node.js and Rust packages.

When to Use This Skill

Activate when any of the following are true:

  • Project has pnpm-workspace.yaml, lerna.json, or turbo.json
  • Multiple package.json files exist in subdirectories
  • Both Cargo.toml and package.json are present
  • User asks about version syncing, workspace protocol, or pre-release versions
  • Scripts named *version* or *sync* exist

Core Concept: Single Source of Truth

Root package.json owns the version. Everything else derives from it.

root package.json (version: "0.2.15")
  ├── packages/cli/package.json        → 0.2.15
  ├── packages/sdk/package.json        → 0.2.15
  ├── packages/shared/package.json     → 0.2.15
  ├── Cargo.toml                       → 0.2.15
  └── platform-packages/*/package.json → 0.2.15

Never manually edit version in child packages or Cargo.toml. Always update root, then run sync.

Version Sync Flow

# 1. Bump version in root
npm version patch    # 0.2.15 → 0.2.16
# or: npm version minor / npm version major

# 2. Sync to all packages
pnpm tsx scripts/sync-versions.ts

# 3. Verify
grep '"version"' packages/*/package.json
grep '^version' Cargo.toml

What sync-versions.ts Does

  1. Reads version from root package.json
  2. Updates every workspace package.json → same version
  3. Updates Cargo.toml version field via regex:
    /^version\s*=\s*"[^"]*"/m → version = "0.2.16"
    
  4. Updates platform package manifests (if generated)
  5. Reports: updated / skipped / errors

Workspace Protocol (workspace:*)

What It Is

pnpm workspaces use workspace:* for internal dependencies during development:

{
  "dependencies": {
    "@scope/shared": "workspace:*"
  }
}

This resolves to the local workspace package, not a published npm version.

The Problem

workspace:* cannot be published to npm — consumers can't resolve it.

The Solution: Replace → Publish → Restore

# 1. Replace workspace:* with actual versions
pnpm tsx scripts/prepare-publish.ts
# @scope/shared: workspace:* → 0.2.16

# 2. Safety check
pnpm tsx scripts/validate-no-workspace-protocol.ts

# 3. Publish
npm publish

# 4. Restore originals
pnpm tsx scripts/restore-packages.ts
# @scope/shared: 0.2.16 → workspace:*

prepare-publish.ts creates .backup files for safe restoration.

Dev (Pre-release) Versioning

Strategy

For non-release builds (CI on main branch, workflow_dispatch):

base:  0.2.15
dev:   0.2.16-dev.12345678
              │    │
              │    └── GitHub Actions run_id (unique, monotonic)
              └── patch bumped

Implementation

// bump-dev-version.ts
const [major, minor, patch] = baseVersion.split('.').map(Number);
const devVersion = `${major}.${minor}.${patch + 1}-dev.${process.env.GITHUB_RUN_ID}`;

npm Tag

# Dev builds
npm publish --tag dev

# Users install explicitly
npm install my-cli@dev

# Production (default)
npm publish          # tagged as 'latest' automatically
npm install my-cli   # gets latest

Decision Tree

When to Sync

Changed root package.json version?
  YES → Run sync-versions.ts
  NO  → No sync needed

Adding new workspace package?
  YES → Add to sync-versions.ts discovery
  NO  → Existing sync handles it

Publishing to npm?
  YES → Run prepare-publish → validate → publish → restore
  NO  → workspace:* is fine for development

Choosing Version Bump

Breaking API change?         → major (1.0.0 → 2.0.0)
New feature, backwards-compat? → minor (0.2.0 → 0.3.0)
Bug fix, no API change?      → patch (0.2.15 → 0.2.16)
CI/testing build?            → dev   (0.2.15 → 0.2.16-dev.123)

Troubleshooting

Version mismatch between packages

# Check all versions
grep -r '"version"' packages/*/package.json
grep '^version' Cargo.toml

# Fix: sync from root
pnpm tsx scripts/sync-versions.ts

workspace:* in published package

# Validate before publish
pnpm tsx scripts/validate-no-workspace-protocol.ts

# If already published, unpublish within 72h
npm unpublish @scope/pkg@version

Cargo.toml version not updating

  • Check regex matches: version = "x.y.z" (with spaces around =)
  • Ensure Cargo.toml path is correct in config
  • Note: Cargo doesn't support pre-release the same way npm does

References

Setup & Activation

Install via forge:

lean-spec skill install codervisor/forge --skill monorepo-version-sync

Or place this folder in:

Setup & Activation

Install via forge:

lean-spec skill install codervisor/forge --skill monorepo-version-sync

Auto-activation hints

  • pnpm-workspace.yaml or lerna.json or turbo.json present
  • Multiple package.json files in subdirectories
  • scripts/*version* or scripts/*sync* files exist
Weekly Installs
0
First Seen
14 days ago