How Release-Plz Manages Unified Workspace Versions and Immutable Tags in OpenLogi
Release-Plz centralizes version bumps in OpenLogi’s Cargo workspace by assigning all crates to a single version group, then creates one immutable Git tag that triggers CI to build artifacts and publish the GitHub Release, ensuring atomic workspace-wide releases.
OpenLogi is organized as a single Cargo workspace where every crate inherits its version from the root Cargo.toml. By configuring Release-Plz with unified versioning rules and delegating release creation to GitHub Actions, the project guarantees that all crates move forward as a unit and that release tags remain immutable once pushed.
Unified Workspace Versioning via Root Cargo.toml
OpenLogi enforces a single source of truth for versioning through the workspace root. In the root Cargo.toml, the version field is defined once, and all member crates reference it via the workspace inheritance feature.
This configuration ensures that bumping the version in one location propagates to every crate in the workspace. When Release-Plz calculates the next semantic version based on conventional commits, it updates the root manifest, and all dependent crates automatically inherit the new version number without requiring individual Cargo.toml edits.
Version Groups for Synchronized Bumping
The release-plz.toml configuration file implements synchronized versioning through the version_group directive. At line 41, every package is assigned to the same group:
[[package]]
name = "openlogi"
version_group = "openlogi"
git_tag_enable = true
git_tag_name = "v{{ version }}"
git_release_enable = false
By assigning version_group = "openlogi" to all workspace members, Release-Plz calculates the next version from the highest-bumped crate within the group and applies that single version to the entire workspace. This prevents version drift between crates and ensures that cargo resolves dependencies correctly across the workspace.
Single Immutable Tag Strategy
To maintain tag immutability, only the pseudo-crate named openlogi (the top-level package) is permitted to create Git tags. In release-plz.toml, line 31 explicitly disables tagging for individual crates with git_tag_enable = false, while line 32 sets git_release_enable = false to prevent Release-Plz from creating GitHub Releases directly.
The openlogi package configuration overrides this with:
git_tag_enable = true– Enables tag creationgit_tag_name = "v{{ version }}"– Defines the immutable tag formatgit_release_enable = false– Ensures Release-Plz only pushes the tag without creating a release
This design creates the Git tag before any CI workflow runs. Because the tag exists prior to the GitHub Release draft, the target_commitish cannot be altered later, avoiding the "target_commitish cannot be changed" error that occurs when workflows attempt to modify tags after release creation.
CI Workflow Integration for Release Publishing
When Release-Plz pushes the single workspace tag (e.g., v1.2.3), the CI workflow defined in .github/workflows/release.yml triggers on the pattern v*. The workflow uses softprops/action-gh-release to create the GitHub Release as a draft, uploads macOS DMG artifacts built via cargo xtask package, and finally publishes the release.
# .github/workflows/release.yml (excerpt)
on:
push:
tags:
- 'v*'
jobs:
build-and-publish:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Build DMG
run: cargo xtask package --target macos
- name: Create draft release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ github.ref_name }}
draft: true
files: target/*.dmg
- name: Publish release
run: gh release edit ${{ github.ref_name }} --draft=false
The build orchestration logic resides in xtask/src/commands/release.rs, which implements the cargo xtask release command invoked by the CI pipeline. This separation of concerns—Release-Plz handling versioning and tagging, while CI handles artifact building and release publication—ensures that the Git tag remains immutable throughout the process.
Summary
- Unified versioning: The root
Cargo.tomlsetsversion.workspace = true, propagating a single version to all workspace members. - Version groups: The
version_group = "openlogi"directive inrelease-plz.toml(line 41) synchronizes version bumps across all crates. - Single tag: Only the
openlogipackage creates tags viagit_tag_enable = true, while other crates havegit_tag_enable = false(line 31). - Immutable tags: By setting
git_release_enable = false(line 32), Release-Plz creates the tag before CI runs, preventing modifications totarget_commitish. - CI delegation: The workflow in
.github/workflows/release.ymlreacts to thev*tag, builds artifacts usingxtask/src/commands/release.rs, and publishes the release viasoftprops/action-gh-release.
Frequently Asked Questions
How does OpenLogi ensure all workspace crates share the same version?
OpenLogi uses Cargo's workspace inheritance feature in the root Cargo.toml combined with Release-Plz version groups. By assigning version_group = "openlogi" to every package in release-plz.toml, the tool calculates the highest version bump required by any crate and applies that single version to the entire workspace.
Why does Release-Plz create only one Git tag instead of per-crate tags?
The configuration explicitly disables per-crate tagging with git_tag_enable = false for all packages except the root openlogi package. This ensures a single tag like v1.2.3 represents the entire workspace state, preventing tag pollution and ensuring atomic releases where all crates share the identical version.
What prevents the release workflow from modifying the Git tag after creation?
Release-Plz creates the Git tag with git_tag_enable = true while having git_release_enable = false, meaning the tag exists before the CI workflow in .github/workflows/release.yml triggers. Since the tag points to a specific commit SHA before the workflow runs, the target_commitish property cannot be changed, avoiding the "target_commitish cannot be changed" error.
How is the GitHub Release actually created if Release-Plz has git_release_enable set to false?
The release creation is delegated entirely to CI. The workflow in .github/workflows/release.yml listens for pushes to tags matching v*, then uses softprops/action-gh-release to create a draft release, upload DMG artifacts, and finally publish the release. This separation ensures Release-Plz handles versioning and tagging while CI handles distribution.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →