Releasing several packages from one repository¶
One repository, several independently versioned packages. tag-prefix is what keeps
their version histories apart.
A wrong tag-prefix ships the wrong version, silently
Nothing errors. The release succeeds, the tag is created, the artifact publishes — it just carries a version computed from another package's history. This is the one setting on this page worth double-checking before a first release.
Diatreme releases one versioned unit per job. To release more than one package out of a single repository, run one job per package, each pointed at that package's directory and its own tag series.
The versioning tools do the path filtering; Diatreme's part is to keep every tag lookup scoped to the package being released.
tag-prefix is what scopes the release¶
Give each package a distinct tag series and tell Diatreme about it:
jobs:
release-core:
steps:
- uses: actions/checkout@v5
with: { fetch-depth: 0, fetch-tags: true }
- uses: MagmaMoose/diatreme@v2
with:
working-directory: packages/core
tag-prefix: 'core-v' # ← tags are core-v1.2.3
publish-package: 'true'
package-ecosystem: pip
package-path: packages/core
This input is not cosmetic here. Diatreme resolves "what was the last
release?" from the repository's tags. Unscoped, that question is answered by
whichever package released most recently — and the answer is a real version
attached to a real tag, so nothing errors. The wrong number simply flows into
the image tag, the published package and the GitHub Release. Every tag lookup
in the action is scoped by tag-prefix; leave it at the default v in a
multi-package repo and the packages will read each other's versions.
tag-prefix must agree with the tag format the versioning tool writes. Diatreme
cannot read that out of your tool's config, so the two are set independently and
it is on you to keep them in step.
Python — python-semantic-release¶
PSR has had a monorepo commit parser since v10.4.0. Configure it in the
package's own pyproject.toml; Diatreme runs PSR with working-directory as
its cwd, so this is the file it reads:
[tool.semantic_release]
commit_parser = "conventional-monorepo"
tag_format = "core-v{version}" # ← must match tag-prefix above
[tool.semantic_release.commit_parser_options]
path_filters = ["."] # only commits touching this directory
scope_prefix = "core-" # optional: also match feat(core-api):
path_filters accepts negated patterns prefixed with !.
Node — semantic-release-monorepo¶
semantic-release has no built-in equivalent; the community shareable config does
the filtering. Declare it in the package's .releaserc.json:
{
"extends": "semantic-release-monorepo",
"plugins": ["@semantic-release/commit-analyzer", "@semantic-release/github"]
}
Diatreme installs whatever your config declares — including extends, which it
must, because semantic-release-monorepo is only ever referenced there and
never appears under plugins. A shareable config that is not installed fails at
config load with MODULE_NOT_FOUND, before any release logic runs.
Checkout depth¶
Path filtering needs history, and comparing against the previous release needs
tags. fetch-depth: 0 and fetch-tags: true on the checkout are required —
with a shallow clone the parsers see a truncated commit range and quietly
under-report what changed.