Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for alternative workflows #528

Open
matthiasbeyer opened this issue Oct 4, 2022 · 5 comments
Open

Support for alternative workflows #528

matthiasbeyer opened this issue Oct 4, 2022 · 5 comments

Comments

@matthiasbeyer
Copy link

I had a look at cargo-release and found that it does only support one workflow (please correct me if I'm wrong).

Current workflow

From what I see, the workflow for using cargo-release is that I have to be on my main branch (cargo-release checks that) and I do a release from there. cargo-release then does pre-release steps (clearing up the changelog file, setting the right version strings), then does the release (cargo-publish) and tag that commit appropriately. After that, it does some post-release steps (bump versions). Then, these commits and tags are pushed to the remote repository.

Please correct me if anything from above is not correct.

Desired workflow

I currently use workflows that do not support committing to the main branch at all and actually pushing changes to "main" is forbidden on all my repositories. I exclusively use bors for merging to main/master!

There are two scenarios:

Small projects

For "small projects" (few contributors, less frequent merges to main) I branch off of "main" and create a "prepare-x.y.z" branch (where "x.y.z" is acutually the version of the release about to be created), that prepares for the next release. I update the changelog (by hand for now, but I plan on implementing cargo-changelog soon), update version strings in README, examples, Cargo.toml if needed. I push that out as a normal PR to github and wait for CI to be green.

I merge using bors. Bors is the only actor that is allowed to push to my main branch in any case.
Once bors merged, I forward my local main branch to that merge commit, create a tag, do cargo-publish and push out that tag.

Big Projects

For big projects, I am going to use a more sophisticated workflow (I did not yet get the chance to actually use that workflow, but it has been discussed among my peers and it looks like we want to go with exactly that workflow).
The overall idea of that workflow is that main does never slow down. With the "Small projects" workflow from above, I do not merge changes to main between the branch-off of the "prepare" branch and its merge. With this workflow, merging to main is never forbidden or even delayed for one second.

For this workflow, I create a release-1.2.x branch (normally patchlevel is set to the string "x" because patch-releases will happen on that release branch) on a commit on main. Because main has to be always green, it does not matter which one.
That release-1.2.x branch is directly protected on github. Nobody is allowed to push to that branch, except for the merge bot (bors).
I then create a PR to that release-1.2.x branch for consolidating the changelog. Once that is merged, I go to that merge commit and create a tag and do a cargo-publish just like above.

To visualize (I left out progress on main because that would make the diagram even more complicated):

gitGraph
    commit
    branch release-1.2.x
    branch changelog-1.2.0
    checkout changelog-1.2.0
    commit id:"make changelog"
    checkout release-1.2.x
    merge changelog-1.2.0 tag:"v1.2.0"

Once the release is done, the commits for consolidating the changelog (and others, if any) are cherry-picked to PRs for main, to backport these patches to the main development branch.
Also, a PR is opened for main to update the version number (minor version) for the next release.

To visualize based on the diagram from above (I left out progress on main because that would make the diagram even more complicated):

gitGraph
    commit
    branch release-1.2.x
    branch changelog-1.2.0
    checkout changelog-1.2.0
    commit id:"make changelog"
    checkout release-1.2.x
    merge changelog-1.2.0 tag:"v1.2.0"
    checkout main
    branch backport-changelog-1.2.0
    checkout backport-changelog-1.2.0
    commit id:"cherry-pick make changelog"
    checkout main
    branch post-release-version-bump
    commit id:"bump version to 1.3.0"
    checkout main
    merge backport-changelog-1.2.0
    merge post-release-version-bump

Patch-releases will happen in the same way: A PR is created towards the "release-1.2.x" branch and if merged, that merge will be tagged as release and published. (Fixes are actually cherry-picked because they have to be merged to main before they can be backported, but that's a detail that's not relevant here).

To visualize (based on the first diagram, again without progress on main to keep the diagram less complicated):

gitGraph
    commit
    branch release-1.2.x
    branch changelog-1.2.0
    checkout changelog-1.2.0
    commit id:"make changelog"
    checkout release-1.2.x
    merge changelog-1.2.0 tag:"v1.2.0"

    checkout release-1.2.x
    branch backport-fix-abc
    checkout backport-fix-abc
    commit id:"Cherry-pick fix ABC"
    checkout release-1.2.x
    merge backport-fix-abc tag:"v1.2.1"

The whole idea of that workflow is that main is always green and always in a release-able state and that development on main never slows down. Nobody has to care about me making a release off of main, they are not impacted at all by that workflow.

How to support these workflows

My question now is: How can these workflows be supported by cargo-release. From what I see, there's actually nothing that could be automated further (except for the parts with cargo-changelog that are not yet implemented... but will be at some point).

Maybe you can see how cargo-release can provide value for these workflows where I don't! 😆

@epage
Copy link
Collaborator

epage commented Oct 21, 2022

FYI I'd recommend also checking out #119 as it discusses an alternative workflow

@epage
Copy link
Collaborator

epage commented Oct 21, 2022

While I will step through to see how cargo-release can help, I think being too strict on what/who can push can end up causing more pain to the process than it is worth and I'd recommend re-evaluating that stance.

Small projects

For "small projects" (few contributors, less frequent merges to main) I branch off of "main" and create a "prepare-x.y.z" branch (where "x.y.z" is acutually the version of the release about to be created), that prepares for the next release. I update the changelog (by hand for now, but I plan on implementing cargo-changelog soon), update version strings in README, examples, Cargo.toml if needed. I push that out as a normal PR to github and wait for CI to be green.

I merge using bors. Bors is the only actor that is allowed to push to my main branch in any case. Once bors merged, I forward my local main branch to that merge commit, create a tag, do cargo-publish and push out that tag.

With 0.22 out, you can use

$ cargo release changes  # review changes to choose versions
$ cargo release version patch  # update versions including in dependents
$ ./prepare.sh  # call `cargo release replace` and `cargo release commit` as needed

Then once merged

$ cargo release tag --workspace  # will automatically skip existing tags
$ cargo release push --workspace # will push the tags
$ cargo release publish --workspace  # will automatically skip existing published

In #119, I discuss a cargo release prepare that would replace the need for the prepare.sh script. Feel free to chime in their with any additional thoughts.

I left out cargo release owner in this as it is usually used to update the owners when new ones are added. cargo release will also automatically add owners when publishing new crates. It might be worthwhile to integrate that into cargo release publish. Feel free to create an issue on that if you want.

What this buys you over doing it by hand

  • You get various health checks up front (releasing something that isn't needed, forgetting to release something, missing metadata earlier in the process, etc
  • The updating of version strings is automated.
  • A commit template is used for consistency
  • Consistent tag names are enforced
  • For workspaces, no need to manually order the publishing of crates
  • Makes it easier to keep the expected owners set for crates
  • Fewer steps to document for others to take over within rust-cli

@epage
Copy link
Collaborator

epage commented Oct 21, 2022

Large projects

The overall idea of that workflow is that main does never slow down. With the "Small projects" workflow from above, I do not merge changes to main between the branch-off of the "prepare" branch and its merge. With this workflow, merging to main is never forbidden or even delayed for one second.

Why does main have to pause for the small workflow? You can let main continue to progress and then merge the release back in. We have #147 for tracking making that easier.

@matthiasbeyer
Copy link
Author

Why does main have to pause for the small workflow?

Because between forking off the release preparation branch and the merge of the same, another PR could be merged that introduces new functionality, bugs, etc.:

gitGraph
    commit
    branch release
    checkout release
    commit id:"release preparation"
    checkout main
    branch feature
    checkout feature
    commit id:"new feature"
    checkout main
    merge feature
    merge release tag:"v0.1.0"

I will have a look at the other points you mentioned, thanks! 👍

@epage
Copy link
Collaborator

epage commented Oct 24, 2022

Oh right, you would be tagging and publishing main. When done locally and not pushing to bors, this isn't an issue which is why I overlooked this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants