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

Release via GHA #229

Merged
merged 11 commits into from
Nov 30, 2023
91 changes: 91 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Publish to Sonatype and NPM

on:
workflow_dispatch:
release:
types: [published]

jobs:
release_snapshot_sonatype:
if: "github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
base: main #see https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#pull-request-events
- uses: actions/setup-java@v3
with:
distribution: corretto
java-version: 11
cache: sbt
- uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
# We cannot cache our environment, as it is dynamically generated by the plugin
- name: Get tags
run: git fetch --tags origin
- name: Release pre-release version to Sonatype and NPM
run: |
VERSION=$(git describe --tags | cut -f2 -d"@")
if [[ ${VERSION:0:1} == "v" ]] ; then
VERSION=${VERSION:1}
fi
if [[ ${VERSION: -9} != "-SNAPSHOT" ]] ; then
echo "Version must end in -SNAPSHOT. Adding -SNAPSHOT suffix"
VERSION="$VERSION-SNAPSHOT"
fi
echo $PGP_SECRET | base64 --decode | gpg --batch --import
export GPG_TTY=$(tty)
echo "Releasing version $VERSION Sonatype as snapshot"

# No need to support NPM releases – there's no direct analogue to a SNAPSHOT release.
# Beta releases are classed as 'production' releases.
sbt -J-Xss32M -DRELEASE_TYPE=snapshot "clean" "release cross release-version $VERSION with-defaults"

env:
# We use armour formatted files for keys, but we know the newlines they contain don't survive
# passing through environment vars, so this secret should be an armour-formatted PGP key passed
# through base64.
PGP_SECRET: ${{ secrets.PGP_SECRET }}
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}

release_production_sonatype:
#if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
base: main #see https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.md#pull-request-events
- uses: actions/setup-java@v3
with:
distribution: corretto
java-version: 11
cache: sbt
- uses: actions/setup-node@v3
with:
node-version-file: .nvmrc
registry-url: https://registry.npmjs.org
- name: Release Production to Sonatype
run: |
VERSION=$(git describe --tags | cut -f2 -d"@")
if [[ ${VERSION:0:1} == "v" ]] ; then
VERSION=${VERSION:1}
fi

if [[ ${VERSION: -9} == "-SNAPSHOT" ]] ; then
echo "Version must NOT end in -SNAPSHOT."
exit 1
fi

echo $PGP_SECRET | base64 --decode | gpg --batch --import
export GPG_TTY=$(tty)
echo "Releasing version $VERSION Sonatype as production"
yes | sbt -J-Xss32M "clean" "release cross release-version $VERSION with-defaults" "project typescript" "releaseNpm $VERSION"
env:
PGP_SECRET: ${{ secrets.PGP_SECRET }}
PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
20.8.0
53 changes: 11 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,20 @@
### 17.0.0
* This release imports the `sbt-scrooge-typescript 1.4.0` sbt plugin which has the potential to introduce some [breaking changes](https://github.com/apache/thrift/blob/master/CHANGES.md#breaking-changes-2) for generated typescript mappings via thrift 0.13.0, specifically related to the [handling of `Int64`](https://issues.apache.org/jira/browse/THRIFT-4675) data.

## Releasing
# Publishing a new release

Ensure the version is composed of three parts (`1.2.3`) as NPM doesn't accept shorter versions such as `1.2`.
This repository has a Github Action that will create new releases for Sonatype and NPM when a new release is created in Github.

The `release cross` command will publish to [Maven Central](http://search.maven.org/) via Sonatype. You will need Sonatype credentials and a PGP key. It can take up to 2hrs to show up in search.
- Push the branch with the changes you want to release to Github.
- Begin creating a new release (here's a [quick link.](https://github.com/guardian/flexible-model/releases/new))
- Set the `Target` to your branch.
- Create a tag:
- - For a production release, the tag should be the new version number, e.g. `vX.X.X`. Beta releases are production releases – for example `v1.0.0-beta.0`.
- - For a snapshot release, the tag should ideally have the format `vX.X.X-SNAPSHOT`.
- **If you are intending to release a snapshot,** double-check that the "Set as pre-release" box is ticked.
- Click the "Publish release" button. The action will trigger, and your release should be on its way.

`release NPM` will release the typescript package to NPM. Ensure you have an NPM account, part of the [@guardian](https://www.npmjs.com/org/guardian) org with a [configured token](https://docs.npmjs.com/creating-and-viewing-authentication-tokens)

To release, in the SBT repl:
```sbtshell
release cross // will release the scala / thrift projects
project typescript
releaseNpm <version> // you have to specify the version again i.e releaseNpm 1.0.0
```

If you see the message `Cannot run program "tsc"` you will need to install TypeScript:
```
npm install -g typescript
```

It is worth noting that different teams follow different practices for model releases. In CAPI, we always release from master/main, so when you are happy with your local release, you can go ahead and make your PR. Once that is merged into main, you can publish your release to Maven. Two consecutive commits will automatically be made to master/main updating the next version number.

### Releasing SNAPSHOT or beta versions

It's also possible to release a snapshot build to Sonatype's snapshot repo with no promotion to Maven Central. This can be useful for trialling a test or upgraded dependency internally.

To do this, start sbt with a RELEASE_TYPE variable;

`sbt -DRELEASE_TYPE=snapshot`

Then, when you run `release cross`, you'll be asked to confirm that you intend to make a SNAPSHOT release, and if you proceed will be prompted to complete the snapshot version details. Whatever you specify here will be written back to the `version.sbt` but this won't be automatically committed back to github.

You are able to re-release the same snapshot version repeatedly (which is handy if you're having GPG-related issues etc.)

Making a beta release is also possible by using the appropriate RELEASE_TYPE variable;

`sbt -DRELEASE_TYPE=beta`

Here, the main differences are that the version number is expected to be of the format 1.2.3-beta.n, and the release will be promoted to Maven Central.

As with the snapshot release process you'll be prompted to confirm and specify the version number you need to use, and changes applied to `version.sbt` will not be automatically committed to github etc.

Unlike a production release, these alternatives are useful for testing/developing with another team or application and can be executed from a branch so there's no need to have everything merged into main/master branches prior to making your changes available.

**Note:** `releaseNpm` (provided by our sbt-scrooge-typescript plugin) has been updated to apply a beta tag to the release, just be sure to use the `x.y.z-beta.n` version number format or NPM may reject it.
To release a package from your local machine, follow the instructions for [publishing a new version to Maven Central via Sonatype](https://docs.google.com/document/d/1rNXjoZDqZMsQblOVXPAIIOMWuwUKe3KzTCttuqS7AcY/edit#).

## Information about built bundles

Expand Down
66 changes: 20 additions & 46 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -126,68 +126,42 @@ lazy val checkReleaseType: ReleaseStep = ReleaseStep({ st: State =>
})

lazy val releaseProcessSteps: Seq[ReleaseStep] = {
val commonSteps = Seq(
checkReleaseType,
val commonSteps:Seq[ReleaseStep] = Seq(
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest
runTest,
setReleaseVersion,
)

val prodSteps: Seq[ReleaseStep] = Seq(
setReleaseVersion,
val localExtraSteps:Seq[ReleaseStep] = Seq(
commitReleaseVersion,
tagRelease,
releaseStepCommandAndRemaining("+publishSigned"),
releaseStepCommand("sonatypeBundleRelease"),
publishArtifacts,
setNextVersion,
commitNextVersion,
pushChanges
commitNextVersion
)

/*
SNAPSHOT versions are published directly to Sonatype snapshot repo and no local bundle is assembled
Also, we cannot use `sonatypeBundleUpload` or `sonatypeRelease` commands which are usually wrapped up
within a call to `sonatypeBundleRelease` (https://github.com/xerial/sbt-sonatype#publishing-your-artifact).

Therefore SNAPSHOT versions are not promoted to Maven Central and clients will have to ensure they have the
appropriate resolver entry in their build.sbt, e.g.

resolvers += Resolver.sonatypeRepo("snapshots")

*/
val snapshotSteps: Seq[ReleaseStep] = Seq(
setReleaseVersion,
releaseStepCommandAndRemaining("+publishSigned"),
setNextVersion
val snapshotSteps:Seq[ReleaseStep] = Seq(
publishArtifacts,
releaseStepCommand("sonatypeReleaseAll")
)

/*
Beta assemblies can be published to Sonatype and Maven.

To make this work, start SBT with the candidate releaseType;
sbt -DRELEASE_TYPE=beta

This gets around the "problem" of sbt-sonatype assuming that a -SNAPSHOT build should not be delivered to Maven.

In this mode, the version number will be presented as e.g. 1.2.3-beta.0, but the git tagging and version-updating
steps are not triggered, so it's up to the developer to keep track of what was released and manipulate subsequent
release and next versions appropriately.
*/
val candidateSteps: Seq[ReleaseStep] = Seq(
setReleaseVersion,
val prodSteps:Seq[ReleaseStep] = Seq(
releaseStepCommandAndRemaining("+publishSigned"),
releaseStepCommand("sonatypeBundleRelease"),
setNextVersion
releaseStepCommand("sonatypeBundleRelease")
)

// remember to set with sbt -DRELEASE_TYPE=snapshot|candidate if running a non-prod release
commonSteps ++ (sys.props.get("RELEASE_TYPE") match {
case Some(v) if v == snapshotReleaseType => snapshotSteps // this deploys -SNAPSHOT build to sonatype snapshot repo only
case Some(v) if v == betaReleaseType => candidateSteps // this enables a beta build to sonatype and Maven
case None => prodSteps // our normal deploy route
})
val localPostRelease:Seq[ReleaseStep] = Seq(
pushChanges,
)

(sys.props.get("RELEASE_TYPE"), sys.env.get("CI")) match {
case (Some(v), None) if v == snapshotReleaseType => commonSteps ++ localExtraSteps ++ snapshotSteps ++ localPostRelease
case (_, None) => commonSteps ++ localExtraSteps ++ prodSteps ++ localPostRelease
case (Some(v), _) if v == snapshotReleaseType => commonSteps ++ snapshotSteps
case (_, _)=> commonSteps ++ prodSteps
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0")
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")
addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.1.2")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10")
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.5")

Expand Down
1 change: 0 additions & 1 deletion version.sbt

This file was deleted.