shipkit / shipkit-auto-version

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

Support always building `-SNAPSHOT` versions when not building with a special flag #90

Open magneticflux- opened 3 years ago

magneticflux- commented 3 years ago

My workflow is as follows:

  1. Start with branches release/xyz and develop.
  2. Branch off of develop to feature/xyz.
  3. Complete development of the feature, merge feature/xyz into develop.
  4. Possibly repeat 2-3 multiple times.
  5. When it's time for a release (large enough changes, finished with changes for now), merge develop into release/xyz.

I already publish builds from release/xyz branches to various maven repos and Github Releases using the Shipkit plugins.

I would like to expose snapshot builds from develop and feature/xyz branches somewhere (Maven, Github Actions build artifacts, etc.). Additionally, local builds (potentially having non-committed changes) should by default be marked as snapshots to distinguish them from reproducible builds on CI. I personally like having Git tree status included in the version like is done here: https://github.com/CaffeineMC/sodium-fabric/blob/68ca12bcbd57eddfaf47aa66492464540c2c7581/build.gradle#L75-L97

This would be extremely useful for simply linking development builds to users in order to get feedback on issue fixes quickly. Examples of this workflow can be found in one of my repos here: https://github.com/magneticflux-/fabric-tree-chopper

37 and #77 are similar to this, but #37 requires an override for snapshot builds rather than the reverse and #77 requires -SNAPSHOT in the version property to be set (if I'm reading the PR's code correctly: https://github.com/shipkit/shipkit-auto-version/pull/78/files#diff-b565cb97994bdd103d4038e053277da3b27f44237fcc958388e286ec930caa1aR112-R114)

mockitoguy commented 3 years ago

Interesting. Can you describe the the requested feature in the form of current vs requested behavior? I want to make sure I understand it. Thanks for reporting!

magneticflux- commented 3 years ago

Sorry about the ramble, I wrote all that just before going to bed 😄.

What currently happens: Local builds on feature/xyz and develop branches get versioned n patch versions ahead of the last version where n is the number of commits since last tagged release.

What I would like to happen: Whenever a build is run anywhere, it should be suffixed with -SNAPSHOT and be one patch version ahead of the last tagged release UNLESS a special flag (for CI runs on release/xyz branches) is set somewhere.

mockitoguy commented 3 years ago

Hey @magneticflux-

Interesting use case. I think the -SNAPSHOT part is fairly easy to solve and I don't think it requires changing the plugin. You could just if () { version += "-SNAPSHOT" }

The incrementing bit is a little tricky. Some options:

Thoughts? Other options?

magneticflux- commented 3 years ago

I think incrementStrategy is the way to go, but I also think there's an underlying issue in the selection of next version that my workflow exposes:

When building a version on a feature branch, the patch number is incremented for each commit. However, as soon as that feature branch is merged, the patch number goes back to +1 for the merge commit. An example:

  1. main just built and tagged v1.0.0
  2. feature/abc branches off and adds 3 new commits, it builds v1.0.3
  3. feature/abc merges (via PR or otherwise) into main
  4. main builds and tags v1.0.1.
  5. Problem! v1.0.1 can be built after checking out main OR after checking out the first commit of feature/abc; these two artifacts are different but have the same version.

If I'm understanding the plugin behavior correctly, this leads to situations where a feature branch from the past could have built a version that a different branch now builds, and there's no way to tell which branch a given version was built from. I think this could be a big problem down the road if someone were to just discover a jar file somewhere and not know where it was built from.

To resolve this, I think the plugin needs some understanding of if it's on a feature branch or on the main branch. A regex match on a branch name could indicate being on a "main" branch (for me release/.+, for a simple branching model main or master). Being on a non-main branch would just build a snapshot version of what would be released if it were merged: the last tag +1 patch version.

mockitoguy commented 3 years ago

If I'm understanding the plugin behavior correctly

The reason we count the commits is to allow "concurrent PR merges" that trigger releases. If you close 3 PRs at the same time, you'll get 1.0.1, 1.0.2, 1.0.3 (assuming that previous was 1.0.0).

there's no way to tell which branch a given version was built from

I think that's normal ;-) Version number does not contain this information. (you could add it will little effort version = version + 'branch'). Have you seen Axion plugin? (it has features that you might like)

magneticflux- commented 3 years ago

The reason we count the commits is to allow "concurrent PR merges" that trigger releases. If you close 3 PRs at the same time, you'll get 1.0.1, 1.0.2, 1.0.3 (assuming that previous was 1.0.0).

I totally agree, this works great for counting merge commits! I just don't think it makes sense to count non-merge commits on non-release branches the same way. I'm also skeptical if people actually use the generated version numbers on non-release branches (this project at least doesn't do anything with them since releases are only pushed on master) My idea still doesn't solve the problem of two concurrent feature branches building the same snapshot versions, but it would prevent feature branches with dozens of commits from (IMO confusingly) "blowing up" the patch version +N before the merge takes it down to just +1 again.

I've looked at Axion, but it seems to have pretty poor support for Kotlin DSL which is a personal must for my new projects (https://github.com/allegro/axion-release-plugin/issues/285). I also feel it's a little further from the "sensible defaults, batteries included" approach that I like with this plugin (of course, I'm biased by my own opinions of "sensible" 😉).


there's no way to tell which branch a given version was built from

I think that's normal ;-)

I also agree with this to some extent: it's definitely not expected to be able to pinpoint what branch, commit, and VCS history went into an artifact. However, in this instance I think it's really useful to be able to immediately see -SNAPSHOT and know it was built on a non-release branch and based on a certain previously released version.

mockitoguy commented 8 months ago

@magneticflux-, it's been long, I'll close the ticket. Reopen if needed!