From 403ee15640aa7e268dda5d6e0ee1806494495e70 Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 12:32:54 +0000 Subject: [PATCH 1/6] Take release.yml directly from firehose client. --- .github/workflows/release.yml | 70 +++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..66f1cb2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,70 @@ +name: Release Sonatype + +on: + 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 + - name: Release Snapshot (prerelease) 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 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" + yes | sbt -DRELEASE_TYPE=snapshot "clean" "release cross release-version $VERSION with-defaults" + env: + 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 + - 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 -DRELEASE_TYPE=production "clean" "release cross release-version $VERSION with-defaults" + env: + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} \ No newline at end of file From 0d6699df5b789cce983c18e7359c50f1c7bd3831 Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 14:11:00 +0000 Subject: [PATCH 2/6] Leveling sbt from 1.5 to 1.9 resolves infinite loop during compile --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index baf5ff3..e8a1e24 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.7 +sbt.version=1.9.7 From 0c1a4da6321a7063812fcf59783765ec37bc3a4b Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 14:37:41 +0000 Subject: [PATCH 3/6] Sync release related plugins with firehose project. Looks like sbt-pgp was leveled. --- project/plugins.sbt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 1efcc03..6c2993b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,8 +1,7 @@ -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("com.eed3si9n" % "sbt-buildinfo" % "0.7.0") +addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0") addSbtPlugin("com.twitter" % "scrooge-sbt-plugin" % "22.1.0") From fe7cec81fc485e3e8deec544000f879c81d92c6e Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 15:02:41 +0000 Subject: [PATCH 4/6] Try to align build.sbt with github action enabled firehose client. Dropped Beta feature while trying todo this. Sorry. --- build.sbt | 118 +++++++++--------------------------------------------- 1 file changed, 19 insertions(+), 99 deletions(-) diff --git a/build.sbt b/build.sbt index a823c94..82faef0 100644 --- a/build.sbt +++ b/build.sbt @@ -5,89 +5,32 @@ val contentEntityVersion = "2.2.1" val scroogeVersion = "22.1.0" // remember to also update plugins.sbt if the scrooge version changes val thriftVersion = "0.15.0" // remember to also update package.json if the thrift version changes -val betaReleaseType = "beta" -val betaReleaseSuffix = "-beta.0" - -lazy val versionSettingsMaybe = { - sys.props.get("RELEASE_TYPE").map { - case v if v == betaReleaseType => betaReleaseSuffix - }.map { suffix => - releaseVersion := { - ver => Version(ver).map(_.withoutQualifier.string).map(_.concat(suffix)).getOrElse(versionFormatError(ver)) - } - }.toSeq -} +//https://github.com/xerial/sbt-sonatype/issues/103 +publishTo := sonatypePublishToBundle.value lazy val mavenSettings = Seq( - pomExtra := ( - https://github.com/guardian/content-atom - - - paulmr - Paul Roberts - https://github.com/paulmr - - - LATaylor-guardian - Luke Taylor - https://github.com/LATaylor-guardian - - - mchv - Mariot Chauvin - https://github.com/mchv - - - tomrf1 - Tom Forbes - https://github.com/tomrf1 - - - annebyrne - Anne Byrne - https://github.com/annebyrne - - - regiskuckaertz - Regis Kuckaertz - https://github.com/regiskuckaertz - - - justinpinner - Justin Pinner - https://github.com/justinpinner - - - ), licenses := Seq("Apache V2" -> url("http://www.apache.org/licenses/LICENSE-2.0.html")), publishTo := sonatypePublishToBundle.value, publishConfiguration := publishConfiguration.value.withOverwrite(true) ) -lazy val checkReleaseType: ReleaseStep = ReleaseStep({ st: State => - val releaseType = sys.props.get("RELEASE_TYPE").map { - case v if v == betaReleaseType => betaReleaseType.toUpperCase - }.getOrElse("PRODUCTION") - - SimpleReader.readLine(s"This will be a $releaseType release. Continue? [y/N]: ") match { - case Some(v) if Seq("Y", "YES").contains(v.toUpperCase) => // we don't care about the value - it's a flow control mechanism - case _ => sys.error(s"Release aborted by user!") - } - // we haven't changed state, just pass it on if we haven't thrown an error from above - st -}) +val snapshotReleaseType = "snapshot" lazy val releaseProcessSteps: Seq[ReleaseStep] = { val commonSteps: Seq[ReleaseStep] = Seq( - checkReleaseType, checkSnapshotDependencies, inquireVersions, runClean, - runTest + runTest, + setReleaseVersion + ) + + val snapshotSteps: Seq[ReleaseStep] = Seq( + publishArtifacts, + releaseStepCommand("sonatypeReleaseAll") ) val prodSteps: Seq[ReleaseStep] = Seq( - setReleaseVersion, commitReleaseVersion, tagRelease, publishArtifacts, @@ -95,33 +38,19 @@ lazy val releaseProcessSteps: Seq[ReleaseStep] = { releaseStepCommand("sonatypeBundleRelease"), setNextVersion, commitNextVersion, - pushChanges ) - /* - Beta assemblies can be published to Sonatype and Maven. - To make this work, start SBT with the beta RELEASE_TYPE variable set; - 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.n, 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 betaSteps: Seq[ReleaseStep] = Seq( - setReleaseVersion, - releaseStepCommandAndRemaining("+publishSigned"), - releaseStepCommand("sonatypeBundleRelease"), - setNextVersion + val localPostRelease: Seq[ReleaseStep] = Seq( + pushChanges, ) - commonSteps ++ (sys.props.get("RELEASE_TYPE") match { - case Some(v) if v == betaReleaseType => betaSteps // this enables a release candidate build to sonatype and Maven - case None => prodSteps // our normal deploy route - }) - + (sys.props.get("RELEASE_TYPE"), sys.env.get("CI")) match { + case (Some(v), None) if v == snapshotReleaseType => commonSteps ++ snapshotSteps ++ localPostRelease + case (_, None) => commonSteps ++ prodSteps ++ localPostRelease + case (Some(v), _) if v == snapshotReleaseType => commonSteps ++ snapshotSteps + case (_, _) => commonSteps ++ prodSteps + } } val commonSettings = Seq( @@ -135,7 +64,7 @@ val commonSettings = Seq( scmInfo := Some(ScmInfo(url("https://github.com/guardian/content-atom"), "scm:git:git@github.com:guardian/content-atom.git")), releasePublishArtifactsAction := PgpKeys.publishSigned.value, -) ++ mavenSettings ++ versionSettingsMaybe +) ++ mavenSettings lazy val root = Project(id = "root", base = file(".")) .settings(commonSettings) @@ -175,19 +104,10 @@ lazy val scalaClasses = Project(id = "content-atom-model", base = file("scala")) Compile / scroogePublishThrift := true ) -lazy val npmBetaReleaseTagMaybe = - sys.props.get("RELEASE_TYPE").map { - case v if v == betaReleaseType => - // Why hard-code "beta" instead of using the value of the variable? That's to ensure it's always presented as - // --tag beta to the npm release process provided by the ScroogeTypescriptGen plugin regardless of how we identify - // a beta release here - scroogeTypescriptPublishTag := "beta" - }.toSeq lazy val typescriptClasses = (project in file("ts")) .enablePlugins(ScroogeTypescriptGen) .settings(commonSettings) - .settings(npmBetaReleaseTagMaybe) .settings( name := "content-atom-typescript", scroogeTypescriptNpmPackageName := "@guardian/content-atom-model", From a324760edac05793ed15106c69c53f5e8c47af2b Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 15:59:17 +0000 Subject: [PATCH 5/6] Crib release notes from firehose client and call out temporary need to continue to manually release the npm artifacts. --- README.md | 83 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 57350e5..6989947 100644 --- a/README.md +++ b/README.md @@ -27,40 +27,49 @@ Prior to releasing, you will need to ensure that: - you have the followed the [guide](https://docs.google.com/document/d/1rNXjoZDqZMsQblOVXPAIIOMWuwUKe3KzTCttuqS7AcY/edit) for publishing to Maven and Sonatype -### Releasing - -To release to Maven Central: -```sbtshell -release cross -``` -This will release these artifacts: -- `content-atom-model-thrift-$version.jar` contains only the Thrift files -- `content-atom-model_2.13-$version.jar` contains the Thrift files and Scrooge-generated Scala 2.13 classes -- `content-atom-model_2.12-$version.jar` contains the Thrift files and Scrooge-generated Scala 2.12 classes - -Note that support for scala 2.11 ended with scrooge 21.3, so we won't output -- `content-atom-model_2.11-$version.jar` -any more. - -To release to NPM: -```sbtshell -project typescriptClasses -releaseNpm -``` - -If you need to make a beta release build available for testing elsewhere, start sbt with -``` -$ sbt -DRELEASE_TYPE=beta -``` -then follow the above release steps as usual. You'll be prompted that this is a BETA release -and for a version number that looks like 1.2.3-beta.n where n is the beta version number -you'll specify. This isn't really tracked so make sure it's a new build by checking Maven and NPM first. - -When releasing the typescript classes to NPM, you'll manually type the version number to match what you -released to Sonatype/Maven for Scala. Our `sbt-scrooge-typescript` sbt plugin takes care of applying a `--tag beta` -to the NPM release when the `RELEASE_TYPE=beta` system property is available. - -To cross release locally use -``` -$ sbt '+publishLocal' -``` \ No newline at end of file + +#### Non-production releases: + +The easiest way to release a snapshot version is via the github UI. +[This](https://github.com/guardian/content-api-firehose-client/pull/28/373) PR introduced the ability to use a github action to trigger the release. + +The steps you should take are: +- Push the branch with the changes you want to release to Github. +- [Click here](https://github.com/guardian/content-api-firehose-client/releases/new?prerelease=true) to create prerelease using Github releases. + +- You must then: +- Set the Target to your branch. +- Create a tag for the snapshot release (the tag can be created from this same UI if it doesn't already exist). +- The tag should ideally have format "vX.X.X-SNAPSHOT". +- Double-check that the "Set as pre-release" box is ticket. +- To automatically release the snapshot to sonatype then click the "Publish release" button. + +And then manually release the npm module: +`npm i -g typescript && sbt 'project typescriptClasses; releaseNpm X.X.X-SNAPSHOT'` + + +#### Production releases: + +When your changes are done and tested and you're ready to release a new production version, edit the `version.sbt` file to reflect the version you are about to release. + +Typically this should just require the removal of the -SNAPSHOT part, but check in [maven](https://repo1.maven.org/maven2/com/gu/content-api-firehose-client_2.13/) to make sure nobody else has released this version before you. + +Open a PR. + +When your PR is approved, merge it to `main` and ensure the build actions complete successfully. + +Then, on the [releases](https://github.com/guardian/content-api-firehose-client/releases) page: +- Choose `Draft a new release` +- Create a new tag of the version number e.g. `v1.0.10` +- Set the target to the `main` branch +- Add a release title (the version number again is fine) +- Add an optional description +- Ensure that `Set as pre-release` is **unchecked** +- Click the `Publish release` button + +When the release process has finished, pull the updated `main` branch locally and update the `version.sbt` file to reflect the next build number, e.g. `1.0.11-SNAPSHOT` and commit that directly back to `main` - there's no need to open a PR for that. + +When your release shows up on [maven](https://repo1.maven.org/maven2/com/gu/content-api-firehose-client_2.13/) the updated version can be referenced in client code. + +And then manually release the npm module: +`npm i -g typescript && sbt 'project typescriptClasses; releaseNpm X.X.X'` From a2122bd72f5fd3a9531b910814a1e2dbe6daf105 Mon Sep 17 00:00:00 2001 From: Tony McCrae Date: Thu, 9 Nov 2023 16:14:29 +0000 Subject: [PATCH 6/6] Better align with firehose; use localExtraSteps. Brings in additional ReleaseSteps on snapshot. --- build.sbt | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/build.sbt b/build.sbt index 82faef0..7772963 100644 --- a/build.sbt +++ b/build.sbt @@ -17,39 +17,41 @@ lazy val mavenSettings = Seq( val snapshotReleaseType = "snapshot" lazy val releaseProcessSteps: Seq[ReleaseStep] = { - val commonSteps: Seq[ReleaseStep] = Seq( + val commonSteps:Seq[ReleaseStep] = Seq( checkSnapshotDependencies, inquireVersions, runClean, runTest, - setReleaseVersion + setReleaseVersion, ) - val snapshotSteps: Seq[ReleaseStep] = Seq( - publishArtifacts, - releaseStepCommand("sonatypeReleaseAll") - ) - - val prodSteps: Seq[ReleaseStep] = Seq( + val localExtraSteps:Seq[ReleaseStep] = Seq( commitReleaseVersion, tagRelease, publishArtifacts, - releaseStepCommandAndRemaining("+publishSigned"), - releaseStepCommand("sonatypeBundleRelease"), setNextVersion, - commitNextVersion, + commitNextVersion ) + val snapshotSteps:Seq[ReleaseStep] = Seq( + publishArtifacts, + releaseStepCommand("sonatypeReleaseAll") + ) + + val prodSteps:Seq[ReleaseStep] = Seq( + releaseStepCommandAndRemaining("+publishSigned"), + releaseStepCommand("sonatypeBundleRelease") + ) - val localPostRelease: Seq[ReleaseStep] = Seq( + val localPostRelease:Seq[ReleaseStep] = Seq( pushChanges, ) (sys.props.get("RELEASE_TYPE"), sys.env.get("CI")) match { - case (Some(v), None) if v == snapshotReleaseType => commonSteps ++ snapshotSteps ++ localPostRelease - case (_, None) => commonSteps ++ prodSteps ++ localPostRelease + 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 + case (_, _)=> commonSteps ++ prodSteps } }