Skip to content

Monorepo Support

semrel supports repositories containing multiple independently versioned packages. There are two approaches — choose the one that fits your workflow.


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)

semrel prefixes every tag with the package path when tagPrefix includes the path:

packages/api@v1.4.0
packages/ui@v3.2.0
packages/worker@v0.9.1
packages/api/.semrel.yaml
schemaVersion: 1
tagPrefix: "packages/api@v"
branches:
- name: main
plugins:
- uses: @semrel/github
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 }}

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.

.semrel.yaml
schemaVersion: 1
branches:
- name: main
plugins:
- 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).

Terminal window
# List all configured packages
semrel workspace list
# Preview what would be released (dry-run, no changes)
semrel workspace release --dry-run
# Release all packages in dependency order
semrel workspace release
# Release independent packages concurrently
semrel workspace release --parallel
# Stop immediately on the first failure
semrel workspace release --fail-fast
[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] ✓ released
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 }}

FeatureOption A (matrix)Option B (workspace)
Config locationPer-package .semrel.yamlRoot .semrel.yaml
CI jobsOne job per packageOne job total
Dependency orderingManual (stage dependencies)Automatic (dependsOn)
Parallel executionNative CI parallelism--parallel flag
Shared pluginsDuplicate per packageOnce at root level
Package isolationCompletePackages share git repo context