Skip to content

Monorepo Setup Example

A complete example of setting up Versu for a monorepo with multiple interdependent modules. It uses the running example from Multi-Module Projects: the my-monorepo workspace with the common, auth, api, web and mobile modules.

Project Structure

text
my-monorepo/
├── packages/
│   ├── common/
│   │   ├── src/
│   │   ├── package.json
│   │   └── CHANGELOG.md
│   ├── auth/
│   │   ├── src/
│   │   ├── package.json
│   │   └── CHANGELOG.md
│   ├── api/
│   │   ├── src/
│   │   ├── package.json
│   │   └── CHANGELOG.md
│   ├── web/
│   │   ├── src/
│   │   ├── package.json
│   │   └── CHANGELOG.md
│   └── mobile/
│       ├── src/
│       ├── package.json
│       └── CHANGELOG.md
├── versu.config.js
├── package.json
└── README.md

Dependency Graph

Configuration

Declare the workspace members in the root package.json - the Node adapter derives the modules and the dependency graph from it:

json
{
  "name": "my-monorepo",
  "private": true,
  "workspaces": ["packages/*"]
}

The dependency graph shown above comes from regular dependency declarations between packages, e.g. in packages/auth/package.json:

json
{
  "name": "@my-org/auth",
  "version": "1.5.2",
  "dependencies": {
    "@my-org/common": "^2.3.1"
  }
}

Then configure Versu itself:

javascript
// versu.config.js
export default {
  plugins: ["@versu/plugin-node"],
  versioning: {
    cascadeRules: {
      // A dependency bump cascades to dependents as a patch bump
      stable: {
        major: "major",
        minor: "patch",
        patch: "patch",
      },
    },
  },
};

Step-by-Step Setup

1. Install Versu

bash
npm install -D @versu/cli @versu/plugin-node

2. Create Configuration

bash
touch versu.config.js
# Copy the configuration above

3. Preview with a Dry Run

bash
npx versu run --dry-run

Check the log output: module discovery should list all workspace packages (:, :packages:common, :packages:auth, ...), and the calculated bumps should reflect your commits and the cascade rules.

4. Release

bash
npx versu run

For a feat commit touching packages/common, one run will:

  1. Bump common with a minor bump (2.3.12.4.0)
  2. Cascade a patch bump to its dependent auth (1.5.21.5.3) - and transitively to api (1.2.01.2.1), web (3.1.03.1.1) and mobile (0.9.00.9.1)
  3. Update every affected package.json, including internal dependency ranges (^2.3.1^2.4.0)
  4. Write a CHANGELOG.md per changed module plus the root changelog
  5. Commit, tag each changed module (@my-org/common@2.4.0, @my-org/auth@1.5.3, ...) and push

Note the patch cascades come from this example's tuned cascadeRules - with the default same-level rules, the dependents would all receive minor bumps instead, as shown in Dependency Cascade.

TIP

Commits are attributed to modules by path: a commit that only touches packages/common bumps only common (plus its cascade). Keep commits scoped to one package when you can.

Next Steps


Ready to automate everything? Check out the GitHub Actions Guide!

Released under the MIT License.