shipkit / shipkit-auto-version

Gradle plugin that helps automating releases by automatically deducing the next Semver version
Apache License 2.0
42 stars 10 forks source link

Optionally increase patch version by 1 #72

Closed nipafx closed 3 years ago

nipafx commented 3 years ago

At the moment, this plugin increases the patch number by number of commits, e.g. version 1.3.0 is followed by 1.3.8 if eight commits happened in between. Personally, I prefer for for the patch versions to be sequential, e.g. releasing 1.3.1 after 1.3.0. It would be great if Shipkit offered a configuration option to switch to that behavior.

mockitoguy commented 3 years ago

Hey! Thanks for trying out the plugin!

At the moment, this plugin increases the patch number by number of commits, e.g. version 1.3.0 is followed by 1.3.8 if eight commits happened in between.

The reason we do it is that we want to enable our customers to release concurrently (should they need to). Counting commits guarantees unique versions in the case of 2 PRs merged at the same time (assuming we're releasing every PR). Concrete use case: imagine that you're getting 2 PRs from Dependabot and you rapidly merge them one-by-one.

To avoid explosion of commits, we added some magic to try to selectively count GH's "merge PRs". The result is that most of the time we are incrementing by one, even though there may be many commits in the PR. Proof: see the release notes: https://github.com/shipkit/shipkit-auto-version/tags, take a look at version 1.1.1 - it was incremented by 1 even though 2 commits made up the release. I'm curious if that would work for your use case.

Do you still want to pursue consistent single digit increment? Are you OK with the trade-off? Basically, I want to understand the problem statement better before we commit to this enhancement. Happy to see that you were able to put together a PR in a short time!

nipafx commented 3 years ago

Thanks for your quick feedback, @mockitoguy! :)

Our use case differs substantially from Shipkits default because we don't like to release on each commit to main. We often work on the project (JUnit Pioneer) in bursts, which means a bunch of PRs get merged within a few hours. Releasing each of those commits feels pointless.

Instead, we work on said bursts and once we're done for the night, we manually kick off a dedicated GitHub Action that uses Gradle/Shipkit to create a release (which, btw, is amazing - thank you for this project! 😍 ). Without sequential versioning, this currently leads to somewhat large jumps in patch versions, like 1.3.0 to 1.3.8 recently. Personally speaking, I find that somewhat confusing.

Since this action never runs concurrently, sequential versions are fine, so I'm happy to accept the trade-off.

mockitoguy commented 3 years ago

Got it. I understand the use case now! I'll review the PR shortly.

mockitoguy commented 3 years ago

we manually kick off a dedicated GitHub Action

@nipafx, curious, why don't you set up GH action so that it releases when new release tag is pushed?

nipafx commented 3 years ago

That requires somebody to sit in front of a machine with Git to release. Wouldn't be a big problem but given the choice we liked the route via website. Why do you ask, would pushing a tag make a difference here? (I can try to answer it myself: The tag could define the version?)

mockitoguy commented 3 years ago

That requires somebody to sit in front of a machine with Git to release

Not necessarily - the tag gets automatically created if you create GH release from the UI.

I can try to answer it myself: The tag could define the version?

Yes. This gives full control of the version.

Do you still prefer an explicit, manually triggered GH action? (if so, please justify because I'll keep asking ;-))

nipafx commented 3 years ago

the tag gets automatically created if you create GH release from the UI.

And Shipkit GitHub Release will then backfill that release with changelog, binaries, etc?

Yes. This gives full control of the version.

What would be the simplest way to get the tag as version into Shipkit?

Do you still prefer an explicit, manually triggered GH action?

Maybe not. I still think that it makes sense for Shipkit to not enforce a specific (and uncommon) versioning scheme, but if I can duck out, I'm no longer concerned about that. 😉

mockitoguy commented 3 years ago

And Shipkit GitHub Release will then backfill that release with changelog, binaries, etc?

Not yet, but we want to build it (we need this for Mockito and friends). It should be fairly easy. Currently, shipkit-github-release fails when the tag is already present.

What would be the simplest way to get the tag as version into Shipkit?

Here's a little Groovy hack:

def tag = "git describe --tags".execute().text.trim()
def found = tag.matches("v\\d+\\.\\d+\\.\\d+")
if (found) {
    allprojects {
        version = tag - "v"
    }
}

Proper solution will be a part of shipkit-auto-version, ticket: #1

I still think that it makes sense for Shipkit to not enforce a specific (and uncommon) versioning scheme

That's fair. Let me think about it a little more.

nipafx commented 3 years ago

If I understand this correctly, these are the options to get sequential versioning:

  1. push a tag (detecting version works as you showed or out of the box when #1 is done, but fails when backfilling GitHub release)
  2. create a release on GitHub (same as pushing a tag)
  3. trigger a release build on GitHub (build is successful, but until this issue is implemented, version is increased by number of commits)
  4. trigger a release build on GitHub and pass the version as an argument

I may opt for the last one if you think sequential versioning isn't a good fit for Shipkit. In that case I have no need for version.properties, which (see comment in #1) currently still needs to be there. If you're interested, I could create a PR where the file is not required if the version was otherwise determined (at the moment by Gradle - later potentially by reading tags).

mockitoguy commented 3 years ago

if you think sequential versioning isn't a good fit for Shipkit

Yeah, I feel that the use case is not strong enough. Feels like clicking GH action to release is a bit off the beaten path. I'd like shipkit-auto-version and shipkit-changelog provide simple, clean support for 2 strong use cases: A. release on demand: push a tag (or click on UI) -> version is taken from the tag, changelog is updated B. release on every change: push a change to branch -> version is incremented safely, changelog is updated

A) needs #1 and https://github.com/shipkit/shipkit-changelog/issues/97 B) is fully supported today

@nipafx, do you want to take a look at https://github.com/shipkit/shipkit-changelog/issues/97?

nipafx commented 3 years ago

I still mildly prefer kicking off a release builde over creating an empty release and waiting for it to be filled, so I think I'll go with my option 4. (If I didn't miss anything that should already work.) I don't think I will contribute to shipkit/shipkit-changelog#97, but if you're interested I'd like to make version.properties superfluous for the case where the Gradle project already has a version. Should I open a new issue to discuss that?

mockitoguy commented 3 years ago

I still mildly prefer kicking off a release build over creating an empty release and waiting for it to be filled

Interesting! I'm curious, why you prefer to have the release build? (love to understand our customers ;-)

If you're interested I'd like to make version.properties superfluous for the case where the Gradle project already has a version. Should I open a new issue to discuss that?

No need, but thanks for asking! We'll take care of it in #1 and there is already a contributor who wants to look into it.

nipafx commented 3 years ago

I'm curious, why you prefer to have the release build?

Because that order just makes more sense to me. Want a release? Kick off a build that does the release. Input: code + version number / Output: artifacts + tag + GitHub release.