Release-plz Workflow and Unified Workspace Versioning in OpenLogi
OpenLogi uses a single-workspace versioning strategy managed by release-plz, where all crates share one version number and the CI pipeline handles tag creation, artifact building, and signed distribution automatically.
The AprilNEA/OpenLogi repository implements a sophisticated release-plz workflow with unified workspace versioning to streamline their Rust CI/CD pipeline. This approach ensures every crate in the workspace remains version-locked while automating changelog generation, tagging, and multi-platform releases through GitHub Actions.
Unified Workspace Versioning Strategy
OpenLogi employs a unified versioning model where the entire workspace advances as a single unit. This prevents version drift between crates and simplifies dependency management across the project.
Workspace Configuration
In the root Cargo.toml, the version.workspace = true directive forces all member crates to inherit the same version number from the workspace definition. This configuration ensures that when the workspace version bumps from 1.2.3 to 1.2.4, every crate updates simultaneously.
The release-plz.toml file (lines 23-33) defines the central behavior:
[workspace]
pr_branch_prefix = "release-plz/"
semver_check = false
git_tag_enable = false
git_release_enable = false
changelog_update = false
Version Groups
Crates are grouped under version_group = "openlogi" in the release-plz configuration. This grouping ensures that release-plz calculates the highest next version among all crates in the group and applies it uniformly. Each participating crate has an individual [[package]] entry that references this group, ensuring lock-step versioning across the workspace.
Release-plz Configuration and Tag-Only Mode
OpenLogi configures release-plz in tag-only mode, separating version bumping from the actual GitHub Release creation. This decoupling allows the project to use release-plz for versioning and tagging while delegating complex artifact building and publishing to a dedicated workflow.
Centralized Settings
The workspace-level settings explicitly disable automatic GitHub releases and changelog updates:
[workspace]
git_tag_enable = false # Tags created per-crate, not workspace
git_release_enable = false # GH Release created by release.yml instead
changelog_update = false # git-cliff handles changelog generation
According to the source code in release-plz.toml, this configuration delegates changelog generation to git-cliff (configured in .config/cliff.toml) and reserves GitHub Release creation for the release.yml workflow.
Per-Crate Tagging
While the workspace disables tagging, individual packages enable it to create the actual Git tag:
[[package]]
name = "openlogi"
version_group = "openlogi"
git_tag_enable = true
git_tag_name = "v{{ version }}"
git_release_enable = false
This setup ensures that when the release-plz PR merges, the workflow pushes a tag v{version} that triggers the downstream release pipeline.
The Automated Release Pipeline
The complete release workflow spans multiple GitHub Actions files and handles everything from version bumping to Homebrew tap updates.
Step 1: Release PR Creation
The .github/workflows/release-plz.yml runs release-plz on branches matching release-plz/*. When executed, release-plz:
- Bumps the unified version in the root
Cargo.toml - Generates a condensed changelog entry
- Opens a PR on a branch prefixed with
release-plz/
The PR contains the version bump and changelog updates, requiring manual review before merging.
Step 2: Tag Push and Trigger
Upon merging the release-plz PR, the CI pushes the tag vX.Y.Z. This tag push triggers the on.push.tags event in .github/workflows/release.yml, initiating the official release pipeline.
Step 3: Build and Sign Artifacts
The release.yml workflow calls the reusable build.yml workflow to construct platform-specific installers:
- macOS: DMG packages with notarization
- Windows: MSI and ZIP with code-signing
- Linux: DEB and RPM packages with GPG signing
Artifacts are stored as workflow outputs and signed using minisign for verification.
Step 4: Publish and Distribute
The publish job in release.yml orchestrates final distribution:
# Generate SHA-256 checksums
sha256sum * > SHA256SUMS
# Sign artifacts with minisign
minisign -S -m OpenLogi-1.2.3.dmg
# Create updater manifest via xtask
cargo run -p xtask --release latest-json \
--dist ./dist \
--tag v1.2.3 \
--base-url https://openlogi.example.com/releases \
--output ./dist/latest.json
The workflow uploads artifacts to GitHub Releases (using softprops/action-gh-release), publishes to Cloudflare R2 for static hosting, and dispatches an event to update the Homebrew tap repository.
Practical Usage and Local Testing
Developers can interact with the release system both through CI triggers and local tooling.
Creating a Release PR
To manually trigger version bumping and PR creation:
# Install release-plz if needed
cargo install release-plz
# Run from repository root
release-plz release
This creates a branch release-plz/vX.Y.Z, updates Cargo.toml versions, and opens a pull request. Merging triggers the tag push automatically.
Generating Updater Manifests
The xtask crate provides utilities for local release testing. To generate the latest.json updater manifest locally:
cargo run -p xtask --release latest-json \
--dist ./dist \
--tag v1.2.3 \
--base-url https://openlogi.example.com/releases \
--include-windows \
--output ./dist/latest.json
See xtask/src/main.rs for additional release-related commands and CLI options.
Verifying Signed Artifacts
End users can verify downloaded artifacts using the project's minisign public key:
minisign -V -P <public-key> \
-m OpenLogi-1.2.3.dmg \
-x OpenLogi-1.2.3.dmg.minisig
Summary
- Unified versioning via
version.workspace = truein the rootCargo.tomlkeeps all OpenLogi crates synchronized to a single version number. - Tag-only mode in release-plz (configured in
release-plz.tomllines 23-33) separates version management from GitHub Release creation, allowing complex build pipelines inrelease.yml. - Automated changelog generation is handled by git-cliff (configured in
.config/cliff.toml) rather than release-plz's internal changelogger. - Multi-platform artifacts (DMG, MSI, DEB, RPM) are built, signed with minisign, and published to both GitHub Releases and Cloudflare R2 via the
release.ymlworkflow. - Local tooling via the
xtaskcrate supports generating updater manifests and testing release workflows without triggering CI.
Frequently Asked Questions
What is unified workspace versioning in OpenLogi?
Unified workspace versioning means every crate in the OpenLogi repository shares the exact same version number defined in the root Cargo.toml. By setting version.workspace = true in each crate's configuration and using release-plz's version_group setting, the project ensures that bumping from version 1.2.3 to 1.2.4 updates every crate simultaneously, preventing dependency conflicts and simplifying release management.
Why does OpenLogi use tag-only mode with release-plz?
OpenLogi uses tag-only mode (where git_release_enable = false for the workspace but git_tag_enable = true for packages) because the project requires complex artifact building, code signing, and multi-platform packaging that release-plz does not handle natively. In this configuration, release-plz manages versioning and creates Git tags, while the custom release.yml workflow handles the actual GitHub Release creation, artifact uploading, and distribution to Cloudflare R2 and Homebrew.
How are the release artifacts signed and verified?
Every release artifact is signed using minisign, a simple and secure signature system. During the release.yml workflow, the publish job generates SHA-256 checksums and creates .minisig signature files for each artifact. Users verify downloads by running minisign -V with the project's public key, the artifact file, and its corresponding signature file, ensuring the integrity and authenticity of downloaded DMGs, MSIs, and Linux packages.
Can I run the release workflow locally for testing?
Yes, local testing is supported through the xtask crate located in xtask/src/main.rs. Developers can generate updater manifests, test build configurations, and validate release artifacts without triggering the full CI pipeline. The cargo run -p xtask command provides subcommands like latest-json for creating the auto-updater manifest locally, allowing validation of release metadata before pushing tags to the repository.
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 →