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

Treat versions with hashes as pre-releases #1549

Merged
merged 4 commits into from
Jul 27, 2020
Merged

Treat versions with hashes as pre-releases #1549

merged 4 commits into from
Jul 27, 2020

Conversation

fthomas
Copy link
Member

@fthomas fthomas commented Jul 26, 2020

This changes Version.selectNext in a few ways:

  • isPreRelease now returns true, if the version contains a hash that
    starts with - or +. So a b in the hash does not change the
    value of isPreRelease anymore.
  • Updates to a pre-release from a non-pre-release of the same series
    are explicitly prevented. 1.2.0 to 1.2.0+17-7ef98061 for example.
  • No more ad hoc rules that prevent updates where the new version
    contains a - or + when the previous version does not.
    1.2.3 to 1.2.3-4 for example are allowed now.
    These rules were added in Do not select a dynamic version as next version #1134 and Do not select versions with a hyphen #1148.

This feels much more principled since hashes designate versions now as
pre-releases in addition to the other pre-release identifiers like
SNAPSHOT, MILESTONE, RC, and others.

Closes #1260.

This changes `Version.selectNext` in a few ways:
  * `isPreRelease` now returns `true`, if the version contains a hash that
    starts with `-` or `+`. So a `b` in the hash does not change the
    value of `isPreRelease` anymore.
  * Updates to a pre-release from a non-pre-release of the same series
    are explicitly prevented. 1.2.0 to 1.2.0+17-7ef98061 for example.
  * No more ad hoc rules that prevents updates where the new version
    contains a `-` or `+` when the previous version does not.
    1.2.3 to 1.2.3-4 for example are allowed now.

This feels much more principled since hashes designate versions now as
pre-releases in addition to the other pre-release identifiers like
SNAPSHOT, MILESTONE, RC, and others.

Closes #1260.
@fthomas fthomas added this to the 0.7.0 milestone Jul 26, 2020
@fthomas fthomas added the bug Something isn't working label Jul 26, 2020
@codecov
Copy link

codecov bot commented Jul 26, 2020

Codecov Report

Merging #1549 into master will increase coverage by 0.03%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1549      +/-   ##
==========================================
+ Coverage   70.15%   70.19%   +0.03%     
==========================================
  Files         113      113              
  Lines        1776     1778       +2     
  Branches       61       59       -2     
==========================================
+ Hits         1246     1248       +2     
  Misses        530      530              
Impacted Files Coverage Δ
...ain/scala/org/scalasteward/core/data/Version.scala 94.52% <100.00%> (+0.15%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 00fef54...8e86513. Read the comment docs.

@fthomas
Copy link
Member Author

fthomas commented Jul 27, 2020

Note that updates like almond-sh/almond#620, which went from 2.1.4-13-fb16e4e to 2.2.0-0-fe5ed67, are prevented now since it is a bump to a pre-release of a different series. Updates like this could be allowed again once #1023 is implemented.

@fthomas fthomas merged commit 53c40df into master Jul 27, 2020
@fthomas fthomas deleted the fix/1260 branch July 27, 2020 15:21
@mzuehlke
Copy link
Member

That PR looks really good and if I would have looked earlier I would have approved it. Easier to understand than before.
Some of the linked PRs look totally ok, some really crazy and some in between:

The other PR you have linked look totally valid to me:

@fthomas
Copy link
Member Author

fthomas commented Jul 27, 2020

from a stable version there should be not upgrade to a pre-release (like #1551: 0.8.0 to 0.8.0-1-d81662.)

That could be "fixed" by recognizing hashes that are only 6 characters long.

a hash as the major version should maybe be ignored ? (#1550: 0.6.3 to 289f9e3aa3f5014a5c64319da8e6ab993947ade2-0-289f9e, betagouv/aplus#684: 2.9.3 to 26962ce-1)

Recognizing 6 char hashes would have also prevented the first but not the second PR.

maybe we should not "upgrade from a RC to a SNAPSHOT / hash ? (scalapb/ScalaPB#885: 2.0.0-RC6-21 to 2.0.0-RC6-23+21-ffe6d4de-SNAPSHOT, softwaremill/correlator#78: 0.21.0-RC5 to 0.21.6+43-2c1c1172-SNAPSHOT)

Yeah. I think the http4s version should have been updated to the latest non-pre-release (0.21.6). This needs more fiddling. :-)

L-space/L-space-NS#78: 3.8 to 3.9.4

That surprised me because it should have happened long before this PR. Something was wrong before that prevented it.

nafg/cloud-logging-logback-scala#70: 0.116.0-alpha to 0.118.1-alpha

That should have been prevented by the "Do not select pre-releases of different series" rule but there is a bug in preReleaseIndex that resulted in this PR. I'll push a fix for this shortly.

fthomas added a commit that referenced this pull request Jul 27, 2020
... and recognize hashes which are only 6 characters long.

`preReleaseIndex` reported the wrong index for versions with components
with a length greater than one.

This is a follow-up #1549.
fthomas added a commit that referenced this pull request Jul 28, 2020
* Fix Version.preReleaseIndex

... and recognize hashes which are only 6 characters long.

`preReleaseIndex` reported the wrong index for versions with components
with a length greater than one.

This is a follow-up #1549.

* Fix off-by-one

* Use foldMap
fthomas added a commit that referenced this pull request Jul 28, 2020
This prevents updates in the same series where the current and new
versions both contain pre-release identifiers and the new version
contains a pre-release identifier with a smaller order than the
pre-release identifer of the current version. It is prevented since the
new version is considered less stable than the current version. We are
preventing updates to pre-releases of a different series for the same
reason.

An example for an update that is prevented by this change is from
2.1.4.0-RC17 to 2.1.4.0-RC17+1-307f2f6c-SNAPSHOT.

This is a follow-up to #1549.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
Only push 1 commit if doing a feature branch release

Fix output of job so we can get the release_type

Updating a tag requires force-pushing, and that feels bad

Comment on PR when a preview release is published

Remove troublesome backticks that confuse bash...

Ideally we would be generating a markdown message with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

### Problems with backticks

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
Only push 1 commit if doing a feature branch release

Fix output of job so we can get the release_type

Updating a tag requires force-pushing, and that feels bad

Comment on PR when a preview release is published

Remove troublesome backticks that confuse bash...

Ideally we would be generating a markdown message with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

### Problems with backticks

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
Only push 1 commit if doing a feature branch release

Fix output of job so we can get the release_type

Updating a tag requires force-pushing, and that feels bad

Comment on PR when a preview release is published

Remove troublesome backticks that confuse bash...

Ideally we would be generating a markdown message with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

### Problems with backticks

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
Only push 1 commit if doing a feature branch release

Fix output of job so we can get the release_type

Updating a tag requires force-pushing, and that feels bad

Comment on PR when a preview release is published

Remove troublesome backticks that confuse bash...

Ideally we would be generating a markdown message with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

### Problems with backticks

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
rtyley added a commit to guardian/gha-scala-library-release-workflow that referenced this pull request Jan 4, 2024
This addresses #10,
providing support for publishing *preview* releases based off feature branches, ie PRs.

The UX of doing a preview release is very similar to the existing process for doing a full
release (https://github.com/guardian/gha-scala-library-release-workflow/blob/main/docs/making-a-release.md),
with only these differences:

* The developer needs to select the PR branch before clicking the green `Run workflow` button
* The version number will be the **upcoming** version number, but with a suffix that clearly
  indicates this is a preview release, eg: `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4`.
  Note that this is _not_ a `-SNAPSHOT` release, the workflow does not support `SNAPSHOT`
  releases.
* No branches are updated by the release (ie, not the PR's feature branch, and not the
  default `main` branch) - the preview release commit exists as its own tagged commit,
  taking the latest PR commit as its parent.
* GitHub release notes will not be created, but instead the PR using that branch will be
  updated with a comment providing details of the new release (version number, etc).

Internally, these 'preview release' changes take place if a non-default branch (ie a feature
branch, not `main`) is used:

* The `🔒 Init` job `release_type` output is `PREVIEW_FEATURE_BRANCH` rather than `FULL_MAIN_BRANCH`
* Only 1 commit is pushed by the workflow, rather than 2, and _not_ onto the branch - the
  single commit exists as a tagged leaf to the side of the PR branch. The 2nd commit normally needed
  by the full release process (incrementing the version number and adding the `-SNAPSHOT`
  suffix) is not needed for preview releases - there are already enough details in the `-PREVIEW`
  version-suffix to keep preview releases unique, even if you do many releases for 1 commit in 1 PR.
* When that 1 commit is pushed, it's initially pushed with a _disposable_ Git tag - not the
  _release_ tag. Pushing _any_ commit requires either a branch or tag for the `git push` command
  to work on (you can't just push a commit id - I've tried), and there is no pre-existing suitable
  branch (we don't want to modify the PR feature branch) or tag (the release tag has an annotation
  message including the hashes of all artifact files generated by the release, and at the point
  when the commit is pushed, those artifacts & their hashes are not available yet), so we have to use
  a new, different, disposable, Git tag instead.

## Choice of version-suffix for preview releases

https://semver.org/#spec-item-9 says:

> 9. A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers MUST NOT include leading zeroes. Pre-release versions have a lower precedence than the associated normal version. A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version. Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
>
> 10. Build metadata MAY be denoted by appending a plus sign and a series of dot separated identifiers immediately following the patch or pre-release version. Identifiers MUST comprise only ASCII alphanumerics and hyphens [0-9A-Za-z-]. Identifiers MUST NOT be empty. Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in the build metadata, have the same precedence. Examples: 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85, 1.0.0+21AF26D3----117B344092BD.

### How can we prevent tooling from thinking our preview releases are stable releases?

If we're not using the `-SNAPSHOT` suffix, there's a risk that tooling will assume that our preview releases are stable releases, and attempt to auto-upgrade to them.

* IntelliJ automatically suggests dependency upgrades - it uses `PackageVersionNormalizer` with specific stability tokens that include 'preview'
* Scala Steward raises dependency upgrade PRs - it uses `isPreRelease` which recognises `Hash` (6+ or 8 hex chars) & specific `Alpha` components that include 'preview'. See also scala-steward-org/scala-steward#1033, scala-steward-org/scala-steward#1549 etc
* Scaladex uses PreRelease.scala - scalacenter/scaladex#614

Consequently, to be certain of being recognised as a pre-release, it seems wise to include these components in the version number:

* 'PREVIEW'
* a commit hash of at least 8 characters

### NPM version numbers...

Some Guardian libraries are released simultaneously for both Scala and other platforms like NPM
(for instance, `content-api-models`, see guardian/content-api-models#229).
Both NPM and sbt/Maven work well with simple three-number semver version numbers, but how well will
NPM handle extended version number like `1.0.7-PREVIEW.feature1.2024-01-04T1230.42ed11d4` ?

### 'PREVIEW', 'BETA', 'ALPHA', or...?

Justin points out the 'PREVIEW' has a particular meaning for the Content Pipeline team ('Preview' vs 'Live'
content) - could potentially cause some confusion there.

I initially chose 'PREVIEW' (from the identifiers that IntelliJ & Scala Steward understand) partially
because both 'BETA' & 'ALPHA' imply some meaning about the stage of development in the software release
cycle that may or may not be appropriate - it's not obvious which one truly reflects what we're doing
when we make an early release from a PR, and it's annoying to have to choose. Additionally, looking at
the Wikipedia article that describes the different stages - the label 'pre-alpha' might even be more
appropriate: https://en.wikipedia.org/wiki/Software_release_life_cycle

## Problems with backticks

Ideally we would be generating a markdown message for the PR comment with lots of backticks
for styling:

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

...like this:

rtyley/sample-project-using-gha-scala-library-release-workflow#1 (comment)

...but they get interpreted by BASH, and cause trouble...

https://github.com/rtyley/sample-project-using-gha-scala-library-release-workflow/actions/runs/7399435634/job/20130944058

...so for the time being this PR avoids them in the generated PR comment.
fthomas added a commit that referenced this pull request Jan 5, 2024
This allows hashes to also be separated with a `.` and `_` from the
preceding component.

Here is for example what `Version.Component.parse("1.0.0+1320.38b57aa")`
returned before this change and what it returns now:
```
before:
Numeric(1), Separator(.), Numeric(0), Separator(.), Numeric(0), Separator(+),
Numeric(1320), Separator(.), Numeric(38), Alpha(b), Numeric(57), Alpha(aa)

now:
Numeric(1), Separator(.), Numeric(0), Separator(.), Numeric(0), Separator(+),
Numeric(1320), Separator(.), Hash(38b57aa))
```

Btw, recognizing hashes was added in #1549 but that PR gives no
explanation why they only could preceded by `-` and `+`.

Closes #3124
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working cat:version-selection
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Next version selection doesn't work for specific versions with hashes
2 participants