cargo-release
cargo-release copied to clipboard
Setting level per crate in a workspace
Lets have a single repo workspace with 3 crates as directories in that repository
❯ tree -L 1
.
├── Cargo.lock
├── Cargo.toml
├── release.toml
├── the-lib/
├── the-db/
└── the-cli/
the-lib and the-db are 0.1.0 while the-cli is 0.2.0. Now, I'm starting to use cargo release, so I manually run cargo release <LEVEL=release> and I'm left with 3 new tags. All good so far. Now it's time to make it automated as soon as a new release PR to the main is merged.
Due to the fact that (usually) the CI is per repository and not per directory (ie. crate), I need to have some generic flow that works depending on the conditions. Now the problem I faced is that when running cargo release in the root (ie. workspace) directory, I need to specify the LEVEL for all crates. However, what if the-lib introduced breaking API changes and I want to bump it's major (ie. 0.1.0->1.0.0) while the-cli (that depends on the-lib) should merely be bumped with minor 0.2.0->0.3.0 and at the same time have it's crates dependencies (ie. the-lib) updated from ^0.1.0 to ^1.0.0. the-db was not changed at all so I'd like to skip it's version bump completely (not even make it a patch) but I don't have a "skip" LEVEL and any other options will leave me with an unnecessary version bump or an error that I'm trying to publish an already published package.
Ideally (I think) the decision on what should be the bump level I'd like to leave to the person that introduced those changes. So if I was the one who changed the-lib that it is not backwards compatible anymore, I should also be the one to somehow store that information in the code (think: gitflow). Perhaps I could use per-crate release.toml for that?
Right now I'm thinking to use pre-release hooks but I still don't know what should those hooks do exactly to achieve my goal. Any suggestions? thanks!
It sounds like you are wanting to run cargo release in a github action that is triggered by a PR being merged?
Say cargo-release supported per-crate levels, how do you see sending that information to cargo release?
It sounds like you are wanting to run cargo release in a github action that is triggered by a PR being merged?
Correct, more precisely in gitlab's CI, but yeah, some kind of CI/CD.
Say cargo-release supported per-crate levels, how do you see sending that information to cargo release?
Actually I'd like to stick with cargo release per workspace just as it is now, but I'd like to have a bit more fine-grained control over bump level so that if only one crate needs major bump then I don't have to bump major version for all other crates.
And as for how to achieve that -- I was thinking whether I could have a level = <LEVEL> in per-crate release.toml that overrides the CLI argument? wdyt
If its in the release.toml, then its static. How would a user decide they need to do a major, minor, or patch release? Is it expected that that would be part of the release PR? Maybe just me but it feels a bit wrong to be tracking transient state in git and could lead to workflow bugs where people forget to update it and get the wrong release level.
Is it expected that that would be part of the release PR?
That's how I imagined it. A developer who, for example, breaks the public API, in the same commit changes the level = to major.
If its in the release.toml, then its static.
I see, release.toml was only a suggestion. It could as well be tackled by pre-release hooks but the information on which level shall be used for a crate can as well be taken from elsewhere.
I'm not saying it's by the book -- I just couldn't figure out a better way to do that. I imagine a release PR where two crates are updated at the same time (see OP above) where one must be bumped with major and the other one with minor, though I don't know how to configure cargo release to do that automatically. The CI cannot make the decision on its own so it has to be specified either by the developer or the PR maintainer.
Even if I configure the CI to run cargo release from within the crate directories and not the workspace directory (ie. twice in my example) then :
- I have to maintain the order manually to make sure that
the-clinotices thatthe-libversion was bumped - When the CI kicks in, it already must somehow know that I want it to bump major for
the-liband minor forthe-cli.
I know that it might sounds like configuring the CD flow (ie. level) dynamically in the codebase itself is off, though that's how gitops approaches this kind of workflow and IMHO it's not that bad. After all the PR maintainer (approver) double checks that the version bump in the codebase, specified by the developer, is about right.
That's how I imagined it. A developer who, for example, breaks the public API, in the same commit changes the level = to major.
Who is responsible for lowering it?
though that's how gitops approaches this kind of workflow
While I'm not fully versed in gitops, I assume gitops tends to focus on moving towards a fixed state and that actions are idempotent. Tracking the release level in a file does not qualify as idempotent.
Its a big smell when you have to rely on review and checklists for process safety. These should be baked into the process or are sytemic failures.
Without re-evaluating from the ground up how I would build what you are wanting but starting from where you are, what I think I would explore is tracking what the next version should be in absolute terms and not by level, maintaining a list of the release order and having a script that steps through it, doing the release for each crate only if the intended version isn't already released. I'd maybe have a tool where dev can say cargo bump major and if the local version isn't the next major version from what is published, it goes ahead and bumps the number so a developer doesn't have to think about what the next version should be but declares their intent. You could even use conventional-commit style commits to have a tool to make sure that a crate is bumped in each PR relative to what the commit type and breaking-status are (I emphasize "a" because cross-crate changes make it ambiguous which the status should apply to).
With all of that said, this seems like a fairly specialized use case that has problems that doesn't seem like supporting per-crate levels and a skip level justify the upfront implementation and associated complexity.
#530 added a cargo release version subcommand for setting the version on a per-crate basis. #538 then made it so we could release these versions as-is. I think this is the route we'll be going for bumping per crate generally rather than complicate the command line or try to store transient information in a static file. We can see how this works out and iterate.
For doing things in actions, I recommend checking out #117, #119, and #528. I'm closing this as a mix of resolved and closing in favor of those issues.