Releasing Rust packages is tedious and error-prone, just like most IT manual tasks. For every package you want to release, you need to:
- Increase the version in
Cargo.toml
. - Update the changelog.
- Publish the package in the cargo registry (for example, crates.io).
- Create and push a git tag.
Meet release-plz: a Rust open-source project that automates these tasks, allowing developers to release Rust packages without the command line.
Features
- Version update based on conventional commits.
- Changelog update with git-cliff.
- Cargo workspaces support.
- No configuration required.
- Optional
cargo update
before releasing. - Git tag created for every released package.
- Package published to any cargo registry.
How does it work
The recommended way to run release-plz is via the GitHub action.
By default, every time you merge a commit to the main branch, the GitHub action runs two commands: release-plz release-pr
and release-plz release
.
Creating a release pull request
The release-plz release-pr
command opens a pull request that prepares the next release.
The command:
- Downloads the packages of the project from the cargo registry.
- Compares the local packages with the downloaded ones to determine the new commits.
- Updates the packages versions based on the messages of the new commits (based on conventional commits and semantic versioning).
- Updates the packages changelogs with the messages of the new commits.
- Updates all dependencies by running
cargo update
(disabled by default). - Raises a pull request with the above changes.
When the project maintainer merges the release pull request, the packages are ready to be published.
Here’s an example of a PR opened by release-plz in the release-plz GitHub project itself:
Releasing all updated packages
The release-plz release
command releases all the packages with a new version.
For example, let’s say you have a workspace with two packages:
pkg-a
(version 0.3.1) andpkg-b
(version 0.2.2). The crates.io registry containspkg-a
version 0.3.1, but it doesn’t containpkg-b
version 0.2.2 because you didn’t publish this version yet. In this case, release-plz would releasepkg-b
.
For every release, release-plz:
- Creates a git tag named
<package_name>-v<version>
(e.g.tokio-v1.8.1
). - Publishes the package to the cargo registry by running
cargo publish
.
Releases made easy
In short, release-plz makes releasing Rust packages child’s play:
- For every change, release-plz creates a release pull request.
- The release pull request reminds the maintainer about the unpublished changes.
- When the maintainer reviews and merges the pull request, release-plz releases the updated packages.
Release-plz makes releasing Rust packages as easy as clicking the pull request “merge” button.
Why yet another release tool
New Rust apps and rewrites are mushrooming every day. Choosing which tools to add to your developer toolbox is becoming harder and harder.
I feel obliged to explain why I created this project and how it compares with similar tools.
Differences with release-please
I learned about the “pull request driven release flow” from the article My ideal Rust workflow by fasterthanlime, where he talks about release-please. I immediately felt like release-please could fit great with the way I work, so I decided to try it. Like release-plz, release-please is an open-source project that manages releases via pull requests. I tried release-please both with the GitHub action and the CLI, but it didn’t work for me:
- I got a “not found” error, which wasn’t very descriptive.
- Two configuration files were required:
.release-please-manifest.json
andrelease-please-config.json
. Most of the fields I had to write in these two files were already in theCargo.toml
files. I thought it was a shame that Rust developers needed to duplicate these fields. - Release-please considers a package “published” when the relative git tag exists. Release-please doesn’t interact at all with cargo registries. However, some Rust projects don’t create git tags. Instead, they just publish the package to crates.io, which is the ultimate source of truth.
Most of the problems listed above mainly exist because release-please aims to support different programming languages. So I thought:
What if I write a tool specifically optimized for Rust that solves all the problems I have experienced? A tool that works out-of-the-box with nearly every Rust project, without any extra configuration.
It took six months of my spare time to write release-plz, but here we are!
Differences with other Rust release tools
These are the release tools in the Rust ecosystem I am aware of:
- cargo-release:
- Bumps the version and publishes Rust packages from the CLI.
- Doesn’t support automatic releases from CI yet. See this open issue.
- cargo-workspaces:
- It’s a set of commands to manage cargo workspaces and their crates.
- The
publish
command releases the packages from the CLI similarly tocargo-release
.
- cargo-smart-release:
- Updates and publishes packages from the CLI.
- It’s very similar to release-plz, but it is not meant to be run in CI (see this comment from the author).
To respect the “Unix philosophy”, I tried to delegate the release flow to cargo-release
and cargo-workspaces
. However, after discussing with the maintainers here and here,
I decided to implement the release-plz release
command by myself.
Overall, I wasn’t satisfied with the existing Rust release tools because:
- They use git tags to determine if a package is already published — release-plz uses cargo registries instead.
- They primarily focus on the CLI use case — release-plz focuses mainly on CI.
Conclusion
Using release-plz increased my productivity. Having an automated release pipeline helps you deliver at a faster pace, with a lower risk of manual mistakes.
If you try release-plz, please let me know on Twitter. Also, make sure to open issues for feature requests or bug reports!