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

potentially customize sbt-git versioning #122

Open
mroth opened this issue May 5, 2019 · 1 comment
Open

potentially customize sbt-git versioning #122

mroth opened this issue May 5, 2019 · 1 comment

Comments

@mroth
Copy link
Contributor

mroth commented May 5, 2019

(Documenting some of my conversations with @outkaj for broader discussion and async. Note this is a discussion related to the upcoming changes switching to sbt-git versioning, not what is currently in master.)

Currently we have sbt-git utilizing it's default versioning schematic, which is almost identical to what git describe does.

In this schematic, if the last release was tagged v1.2.3, you may notice your local version is something like 1.2.3-7-a1b2c3d. This means you are 7 commits past release 1.2.3, and the latest commit was SHA a1b2c3d.

There are two changes we may want to discuss making to this behavior.

Making the versions more SemVer compliant

There is an official specification for allowing pre-release versions in SemVer, and this differs from it a little. Basically it's this:

Major.Minor.Patch-pre(.pre)*+metadata

Primary section: 3 dot separated fields, numeric major, minor, patch numbers (MUST exist, and MUST be numeric). This is the "public API" of SemVer.

Optional pre-release section: Following a - separator, any number of dot separated fields. What can go in them is more relaxed, alphanumerics are supported, thus you'll often see things like -rc.3 or -1 or alpha.123. While this portion is less standardized, generally people try to keep them as something that can be ordered.

Build metadata: Following a +, anything goes here that should not affect version ordering.

(For more formal spec with more detail see https://semver.org)

Version ordering: The most notable change is the that in SemVer, 1.2.3-7 would indicate a prerelease of 1.2.3, e.g. something that comes before it.

This is very common with pre-releases in SemVer, and is widely adopted in the wild. (This is what we do with NPM in openlaw-client, as it's the default.)

Metadata: In SemVer, the separator before build metadata field should be +. I don't see this as often in the wild, but it's in the specification. I consider this to be less of an issue but it's there.

Combing the above, the simplest set of changes would mean 1.2.3-7-a1b2c3d would become 1.2.4-7+a1b2c3d.

Neither would affect public releases at all unless we wanted to start pushing these versions to GitHubReleases+BinTray. This is more for our local development currently? Unknown to me is how SBT considers version ordering and how this might affect it.

We could also use a different schematic for pre-release versions if we ever want to actually "release" them, and not care so much about what sbt-git shows locally when doing development. Combining this choice with the SNAPSHOT option below could help enforce that better.

Adding in SNAPSHOT for more cases

Currently sbt-git only appends SNAPSHOT if your local worktree is dirty (e.g. non-commited changes). We may wish to make it so anything not explicitly on a release tag is considered a SNAPSHOT -- and thus can't accidentally be released to BinTray.

(If we did that, but still wanted to release a "pre-release" version at some point, we could just do a semver prerelease git tag within our normal release process and it would work.)

Implementation

sbt-git gives us the flexibility to totally override the versioning schematic as we see fit. So anything we want should be achieveable. An example from someone's blog post where they were doing something fairly similar (I think? I still don't grok sbt-git configuration intuitively. But it still shows it's easy to get under the hood):

val VersionRegex = "v([0-9]+.[0-9]+.[0-9]+)-?(.*)?".r
git.gitTagToVersionNumber := {
  case VersionRegex(v,"") => Some(v)
  case VersionRegex(v,"SNAPSHOT") => Some(s"$v-SNAPSHOT")  
  case VersionRegex(v,s) => Some(s"$v-$s-SNAPSHOT")
  case _ => None
}
@mroth
Copy link
Contributor Author

mroth commented May 10, 2019

Been doing some research on the semver+git describe options. A live "defacto standard" I found in the NodeJS/NPM community is basically $FULL_TAGGED_SEMVER+$gitcommitsahead.$gitsha, e.g. for above example would be:

1.2.3+7.a1b2c3d

I actually kinda like this upon reflection, as you completely make your local state into the build metadata field only, and releasing a pre-release version becomes always an active decision, e.g. tagging v1.2.4-rc1 or whatever you choose, at which point the above local autoversioning schematic would continue past that in local commits as 1.2.4-rc1+1.b2c3d4e etc. This solves the issue of not knowing whether a next release is going to be major/minor/patch in advance, and acknowledges that trying do comparison based on number of commits is error prone, due to git rebase et al, so keeping it in the buildinfo field (which does not determine precedence by nature) is desirable.

If melding that mechanism with "SNAPSHOT" (it's still unclear to me if we want this for local versioning), I imagine we would simply append it as the buildinfo suffix in all cases where we are not on a direct tagged commit, e.g. 1.2.3+7.a1b2c3d.SNAPSHOT and 1.2.4-rc1+1.b2c3d4e.SNAPSHOT.

(I'm assuming this would be compatible with SBT versioning schematics, however if not, a close reading of the semver spec does seem to technically allow a - in build metadata field, even though that looks confusing. With that, we would do 1.2.4-rc1+1.b2c3d4e-SNAPSHOT instead.

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

1 participant