changesets / changesets

🦋 A way to manage your versioning and changelogs with a focus on monorepos
MIT License
8.89k stars 552 forks source link

Support release branch workflows #548

Open KyleAMathews opened 3 years ago

KyleAMathews commented 3 years ago

We're looking into using changesets for Gatsby to generate better Changelogs. We use a release branch workflow where every two weeks, we create a new branch of master e.g. releases/3.2.0 and then publish latest from there.

@wardpeet said he'd talked to one of you and that changesets would need some changes to support this flow? If we can help out, let us know!

Andarist commented 3 years ago

Hi! Thanks for looking into Changesets. I remember talking with @wardpeet about this stuff but I don't recall the exact problem and unfortunately, our chat history is not accessible as we've been talking in a free (or smth) Slack workspace.

Could you describe your workflow in more detail so I could give you proper advice on that one? Especially details around what is automated.

wardpeet commented 3 years ago

Hey @Andarist,

I was trying to find it too. Our workflow looks like the following: Every PR gets merged into master. We publish pre-patches with preid next (3.3.0-next.0).

We create a release branch from master (release/3.3) it will remain there for about 4 weeks. We cherry-pick commits/PRs if we need to backport fixes. Than we do a patch publish.

Currently we use lerna to publish our packages to keep transitive versions in sync.

Andarist commented 3 years ago

I’m still unsure if I understand your complete workflow but I think that little to no changes would have to be done in Changesets so you could use them.

  1. You could release „snapshot” releases from your trunk which would create versions like 1.2.0-dev20210405 (the exact format might be slightly different as I’m writing that from memory)
  2. At the same time Changeset would push out a „release branch” and a versioning PR would be created with all bumps applied
  3. At any moment you could merge that PR to your trunk to kick off the stable release from your trunk

Does this sound good? Or is some requirement missing here?

wardpeet commented 3 years ago

Hopefully, after our private chat it became a little bit more clear. Something that's missing from the above comment is that I'm not sure how we would patch a previous release.

This is roughly how we do it now, in a sketch. We don't have to keep this structure as long as the behaviour stays the same :)

image

vladar commented 3 years ago

Our model is pretty much the same as described here: https://trunkbaseddevelopment.com/branch-for-release/

So we never publish stable releases from trunk. And also the same change may end up in multiple releases - next minor and backported to the previous minor (and sometimes previous major) as a patch.

Andarist commented 3 years ago

The important thing to realize about changesets is that "release intents" (changesets) are kept on disk/in git. This has some implications on the workflow you are using - it's not that it's not possible to support it but it would be the easiest to change it a little bit to what we need here. If the proposed approach won't work for you for some reason - then we can discuss this further, I'm also open to setting up a call to figure out a suitable workflow for you.

  1. keep merging regular PRs with changesets to master
  2. manually force push to the rc-channel each 2 week
    • before force pushing, you would actually enter our "prerelease mode" (this could be easily scripted)
    • setup a changeset workflow for the rc-channel, when anything new lands there a versioning PR will get open against the rc-channel
    • this gives you time to review changes and merge from the GitHub UI whenever you like it (it's nice as you can prepare a release properly before actually publishing it)
    • when that versioning PR lands on rc-channel all scheduled to release packages will be released under rc tag
  3. after the stabilization period you would be able to merge a PR exiting the prerelease mode (to automate this something would have to be scripted here as currently we do not open exiting PRs automatically) which would trigger a stable release (again - this would be nicely reviewable before merging)
    • it feels like this step should also be force-pushed to a stable-channel somehow, but I'm not sure yet how exactly to accommodate that using GitHub UI alone. Worst case scenario this could be scripted from the rc-channel so the exiting PR would not be active throughout the whole stabilization period but rather just when you decide to manually~ invoke the script to create it

This doesn't seem to be overly complicated to me and would utilize the Changesets in a pretty straightforward way.

Fixing PRs are somewhat problematic - if merge/cherry-pick/whatever a fixing PR with a changeset to either rc-channel or stable-channel branches then Changesets will create versioning PRs for them and you will be able to merge them (this allows you to batch multiple fixes in a single release per channel). So far so good. The problematic part is that in the current workflow you merge fixing PRs to master and cherry-pick that to other branches - but we'd like to remove the changeset itself from the master as otherwise it would become a part of the future RC release and that's not what you want to achieve. So my proposal would be to actually prepare those fixing PRs against other channels and cherry-pick to master which would allow you to drop the changeset file in the process.

An alternative solution for that would be to somehow mark the changeset as belonging to a different release which would allow us to ignore it (and remove it) when force pushing to the rc-channel. This would result in the extra commit on master as we'd have to alter git content to remove those changesets. This one would require a minor feature to be added to Changesets.

Please tell me how does it feel, what do you think about the proposed workflow and the workflow related to fixing PRs. Are there any particular things that you don't like about it? Is everything clear? Or should I explain some part of this in more detail?