diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a5c33101 --- /dev/null +++ b/.github/workflows/release.yml @@ -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 }} diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 00000000..3d325430 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.8.0 diff --git a/README.md b/README.md index 78567f9b..eb528e7e 100644 --- a/README.md +++ b/README.md @@ -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 // 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 diff --git a/build.sbt b/build.sbt index 371b5458..9c154eb2 100644 --- a/build.sbt +++ b/build.sbt @@ -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 + } } /** diff --git a/project/plugins.sbt b/project/plugins.sbt index fc550847..c7913800 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -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") diff --git a/version.sbt b/version.sbt deleted file mode 100644 index ce0695bf..00000000 --- a/version.sbt +++ /dev/null @@ -1 +0,0 @@ -ThisBuild / version := "17.8.1-SNAPSHOT"