Monorepo Support
semrel supports repositories containing multiple independently versioned packages. There are two approaches — choose the one that fits your workflow.
Option A — per-package (matrix)
Section titled “Option A — per-package (matrix)”Each package has its own .semrel.yaml and is released by a separate CI job or matrix step.
Directorymy-monorepo/
Directorypackages/
Directoryapi/
- .semrel.yaml
- go.mod
Directoryui/
- .semrel.yaml
- package.json
Directoryworker/
- .semrel.yaml
- go.mod
- .semrel.yaml root config (optional shared baseline)
Tagging convention
Section titled “Tagging convention”semrel prefixes every tag with the package path when tagPrefix includes the path:
packages/api@v1.4.0packages/ui@v3.2.0packages/worker@v0.9.1Per-package configuration
Section titled “Per-package configuration”schemaVersion: 1tagPrefix: "packages/api@v"branches: - name: mainplugins: - uses: @semrel/githubRunning releases (CI matrix)
Section titled “Running releases (CI matrix)”jobs: release: strategy: matrix: package: [packages/api, packages/ui, packages/worker] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Release ${{ matrix.package }} run: semrel release --config ./${{ matrix.package }}/.semrel.yaml env: SEMREL_PLUGIN_TOKEN: ${{ secrets.GITHUB_TOKEN }}Option B — workspace (single command)
Section titled “Option B — workspace (single command)”Configure all packages in the root .semrel.yaml and release them all with one command. Packages are released in dependency order; packages with nothing new are skipped automatically.
Root config
Section titled “Root config”schemaVersion: 1branches: - name: mainplugins: - uses: @semrel/github # shared plugin for all packages
workspace: strategy: independent # each package gets its own semver
# Option 1: explicit package list with optional dependency ordering packages: - path: packages/api tagPrefix: "packages/api@v" - path: packages/ui tagPrefix: "packages/ui@v" dependsOn: [packages/api] # released after api - path: packages/worker tagPrefix: "packages/worker@v"
# Option 2: auto-discover all package directories # pattern: "packages/*"
fail_fast: false # collect all errors (default: continue on failure)Each package directory can have its own .semrel.yaml that overrides the root configuration (branches, rules, plugins, tagPrefix).
Workspace subcommands
Section titled “Workspace subcommands”# List all configured packagessemrel workspace list
# Preview what would be released (dry-run, no changes)semrel workspace release --dry-run
# Release all packages in dependency ordersemrel workspace release
# Release independent packages concurrentlysemrel workspace release --parallel
# Stop immediately on the first failuresemrel workspace release --fail-fastOutput
Section titled “Output”[packages/api] releasing…Current version: v1.2.0 → v1.3.0 (minor)✓ Committed CHANGELOG.md ✓ Created tag packages/api@v1.3.0[packages/api] ✓ released
[packages/ui] releasing…No commits since last release — nothing to release.[packages/ui] – skipped (nothing to release)
[packages/worker] releasing…Current version: v0.8.0 → v0.9.0 (minor)[packages/worker] ✓ releasedCI example
Section titled “CI example”jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Restore semrel plugins run: semrel plugin restore - name: Release workspace run: semrel workspace release env: SEMREL_PLUGIN_TOKEN: ${{ secrets.GITHUB_TOKEN }}release: stage: release script: - semrel plugin restore - semrel workspace release variables: SEMREL_PLUGIN_TOKEN: $CI_JOB_TOKENChoosing between Option A and B
Section titled “Choosing between Option A and B”| Feature | Option A (matrix) | Option B (workspace) |
|---|---|---|
| Config location | Per-package .semrel.yaml | Root .semrel.yaml |
| CI jobs | One job per package | One job total |
| Dependency ordering | Manual (stage dependencies) | Automatic (dependsOn) |
| Parallel execution | Native CI parallelism | --parallel flag |
| Shared plugins | Duplicate per package | Once at root level |
| Package isolation | Complete | Packages share git repo context |