ajoberstar / reckon

Infer a project's version from your Git repository.
Apache License 2.0
185 stars 28 forks source link

Why are snapshotFromProp and stage - mutually exclusive? #120

Closed ieugen closed 5 years ago

ieugen commented 5 years ago

Hello @ajoberstar ,

We are using reckon and so far it worked very well for us. However I've noticed that we can't use a stage with snapshotFromProp and I am curious as to why?

More over how can we make a release candidate using snapshotFromProp ? In my opinion this is very valid use case and I find this to be a limitation for us.

Our goal is to make a release candidate that we can deploy in a pre-production environment. And it would be nice to have releases like: 1.2.3 (final) 1.2.3-rc-1 (rc) , 1.2.3-SNAPSHOT.

I have a hunch that the reason for this is because of SemVer compatibility. Maybe there is a solution in that case: sort the versions according to some rules. I've seen this done in [1]

default order:

[1] https://github.com/yannickcr/eslint-plugin-react/blob/master/docs/rules/sort-comp.md#rule-options

ajoberstar commented 5 years ago

Yeah, your hunch is right on. The SemVer spec defines strict ordering rules, which would always sort rc before SNAPSHOT. That seemed unintuitive, so I kept the stage and snapshot schemes separate to avoid confusion.

As more of a side note, the other constraint on the version scheme is Gradle's sorting rules. They're subtly different from SemVer, so the reckon versions are specifically tuned to sort consistently between Gradle and SemVer.

ieugen commented 5 years ago

Is the solution to provide a custom sort order (like described in the link above) a valid one?

Following the specs is pretty limiting and not flexible. I believe this is a difference between the semver spec (and gradle spec?!) and real life scenarios.

ajoberstar commented 5 years ago

Following the SemVer spec is core to reckon's purpose, so that's intentionally inflexible. It's a limitation that means you can use the resulting versions anywhere SemVer is supported.

Ultimately, the versions have to play well with the outside world. If Gradle consumes the version, Gradle uses its own (unconfigurable) rules. If something supporting SemVer consumes the version, it uses the spec's rules. Reckon making a different sorting decision during inference wouldn't be known or considered by the consumer, and would just result in inconsistency.

ieugen commented 5 years ago

Ok. I'll close this since you've decided the scope of reckon and this is out of scope.

It would be nice to be more flexible though. To that end I'll share this lerna documentation regarding how they handle versions (also semver compatible, but not limited to that I believe). In case you find it interesting and useful: https://github.com/lerna/lerna/tree/master/commands/publish#--canary

JavierSegoviaCordoba commented 3 years ago

I would like to see a flag that lets the usage of snapshot + alpha. Currently, I can't upload snapshots to the Sonatype snapshots repo because there is no way to mark the version as -SNAPSHOT without adding boilerplate.

I understand that it should be separated but this should work:

scopeFromProp()
snapshotFromProp()
stageFromProp("alpha", "beta", "rc", "final")

Or something like:

scopeFromProp()
snapshotFromProp(force = true)
stageFromProp("alpha", "beta", "rc", "final")
ajoberstar commented 3 years ago

@JavierSegoviaCordoba What's an example version you would like to see output in this mode?

JavierSegoviaCordoba commented 3 years ago

I think the same that a final version does:

My current workaround (I have to test it):

reckon {
    scopeFromProp()
    if (properties["isSnapshot"]?.toString()?.toBoolean() == true) snapshotFromProp()
    else stageFromProp("alpha", "beta", "rc", "final")
}

Which let me use:

- name: Publish a snapshot
  if: github.ref == 'refs/heads/develop'
  env:
    ossUser: ${{ secrets.ossUser }}
    ossToken: ${{ secrets.ossToken }}
  run: ./gradlew publishToSonatype -P"reckon.stage"="snapshot" -P"isSnapshot"="true"

I understand this plugin is fully focused on semantic versioning, but I think a few flexibilities about SNAPSHOT should be great.

It is a common pattern not only publishing snapshots, even publishing them with, for example, the current date:

The problem I see here is semantic versions use numbers after stage, meanwhile, the Maven Snapshot pattern is that -SNAPSHOT should be the last word in the string.

I don't know if you think something like snapshotFromProp(isMaven = true) could be acceptable, which could be completely focused on facilitating to publish on Maven.

If you think so, isMaven could be mavenConfig to allow more flexibility about snapshot naming (hash, date, etc).

JavierSegoviaCordoba commented 3 years ago

Can be this reopened?

JavierSegoviaCordoba commented 3 years ago

After talking in Kotlinlang slack, the conclusion we got is SNAPSHOT stage is higher than every stage except the final one, and it is strange using a version that uses S or higher.

SNAPSHOT would be available in stage mode too, not only in snapshot one. Conceptually, the current snapshot implementation is different from the stage + snapshot (but the same priority at the end, final > snapshot), however, you can keep both.

Additionally, usually, a SNAPSHOT will have newer code than the last rc, for example thinking in publishing to MavenCentral, you can just publish the version 1.3.0-rc.1, and after that publishing and overriding multiple snapshots in snapshots repository (1.3.0-SNAPSHOT), and later publishing the 1.3.0-rc.2.

Probably, the latest rc version should have exactly the same code that the latest snapshot (with the same major/minor/path).

What do you think?