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

Adopt gha-scala-library-release process #32

Merged
merged 5 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI
on:
workflow_dispatch:
pull_request:

# triggering CI default branch improves caching
# see https://docs.github.com/en/free-pro-team@latest/actions/guides/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: corretto
java-version: 11
cache: sbt
- name: Build and Test
run: sbt compile
- name: Test Summary
uses: test-summary/action@v2
with:
paths: "test-results/**/TEST-*.xml"
if: always()
36 changes: 36 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Release

on:
workflow_dispatch:

jobs:
scala-maven-release:
name: Maven Release
uses: guardian/gha-scala-library-release-workflow/.github/workflows/reusable-release.yml@main
permissions: { contents: write, pull-requests: write }
secrets:
SONATYPE_PASSWORD: ${{ secrets.AUTOMATED_MAVEN_RELEASE_SONATYPE_PASSWORD }}
PGP_PRIVATE_KEY: ${{ secrets.AUTOMATED_MAVEN_RELEASE_PGP_SECRET }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.AUTOMATED_MAVEN_RELEASE_GITHUB_APP_PRIVATE_KEY }}

typescript-npm-release:
name: NPM Release
needs: scala-maven-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: corretto
java-version: 11
cache: sbt
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
registry-url: https://registry.npmjs.org
- name: Release Typescript to NPM
run: |
sbt "project typescript" "releaseNpm ${{ needs.scala-maven-release.outputs.RELEASE_VERSION }}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the typescript project is called typescriptClasses in this project, for some reason!

lazy val typescriptClasses = (project in file("ts"))

env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
RELEASE_TYPE: ${{ needs.scala-maven-release.outputs.RELEASE_TYPE }}
148 changes: 32 additions & 116 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,133 +1,49 @@
import sbtrelease._
import ReleaseStateTransformations._
import sbtrelease.ReleaseStateTransformations._
import sbtversionpolicy.withsbtrelease.ReleaseVersion

val scroogeVersion = "22.1.0"
val thriftVersion = "0.15.0"
val thriftVersion = "0.19.0"
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
}

lazy val mavenSettings = Seq(
pomExtra := (
<url>https://github.com/guardian/content-entity</url>
<developers>
<developer>
<id>LATaylor-guardian</id>
<name>Luke Taylor</name>
<url>https://github.com/LATaylor-guardian</url>
</developer>
<developer>
<id>tomrf1</id>
<name>Tom Forbes</name>
<url>https://github.com/tomrf1</url>
</developer>
<developer>
<id>justinpinner</id>
<name>Justin Pinner</name>
<url>https://github.com/justinpinner</url>
</developer>
</developers>
),
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
})

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

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

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

To make this work, start SBT with the candidate 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
)

commonSteps ++ (sys.props.get("RELEASE_TYPE") match {
case Some(v) if v == betaReleaseType => betaSteps // this enables a beta build to sonatype and Maven
case None => prodSteps // our normal deploy route
})

}

val commonSettings = Seq(
val artifactProductionSettings = Seq(
organization := "com.gu",
scalaVersion := "2.13.2",
scalaVersion := "2.13.12",
// scrooge 21.3.0: Builds are now only supported for Scala 2.12+
// https://twitter.github.io/scrooge/changelog.html#id11
crossScalaVersions := Seq("2.12.11", scalaVersion.value),
crossScalaVersions := Seq("2.12.18", scalaVersion.value),
releaseCrossBuild := true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line needs to be moved down into the root project!

Suggested change
releaseCrossBuild := true,

releaseCrossBuild lives with releaseVersion and releaseProcess on the root-level aggregating project, not on the artifact-producing modules!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good spot, I will correct it now 👍

scmInfo := Some(ScmInfo(url("https://github.com/guardian/content-entity"),
"scm:git:git@github.com:guardian/content-entity.git")),
releasePublishArtifactsAction := PgpKeys.publishSigned.value
) ++ mavenSettings ++ versionSettingsMaybe
scalacOptions ++= Seq("-release:11"),// do we need these as well? - ("-feature", "-deprecation", "-unchecked", "-Xfatal-warnings")
licenses := Seq(License.Apache2),
Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-u", s"test-results/scala-${scalaVersion.value}", "-o")
)

lazy val root = (project in file("."))
.settings(commonSettings)
.settings(artifactProductionSettings)
.aggregate(thrift, scalaClasses)
.settings(
publishArtifact := false,
releaseProcess := releaseProcessSteps
publish / skip := true,
releaseVersion := ReleaseVersion.fromAggregatedAssessedCompatibilityWithLatestRelease().value,
releaseProcess := Seq[ReleaseStep](
checkSnapshotDependencies,
inquireVersions,
runClean,
runTest,
setReleaseVersion,
commitReleaseVersion,
tagRelease,
setNextVersion,
commitNextVersion
)
)

lazy val scalaClasses = (project in file("scala"))
.settings(commonSettings)
.settings(artifactProductionSettings)
.settings(
name := "content-entity-model",
description := "Scala library built from Content-entity thrift definition",

Compile / scroogeThriftSourceFolder := baseDirectory.value / "../thrift/src/main/thrift",
Compile / scroogeThriftOutputFolder := sourceManaged.value,
Compile / scroogePublishThrift := true,
Expand All @@ -136,19 +52,19 @@ lazy val scalaClasses = (project in file("scala"))
libraryDependencies ++= Seq(
"org.apache.thrift" % "libthrift" % thriftVersion,
"com.twitter" %% "scrooge-core" % scroogeVersion,
"org.scalacheck" %% "scalacheck" % "1.14.0" % "test"
"org.scalacheck" %% "scalacheck" % "1.17.0" % "test"
)
)

lazy val thrift = (project in file("thrift"))
.settings(commonSettings)
.settings(artifactProductionSettings)
.disablePlugins(ScroogeSBT)
.settings(
name := "content-entity-thrift",
description := "Content entity model Thrift files",
crossPaths := false,
packageDoc / publishArtifact := false,
packageSrc / publishArtifact := false,
packageDoc / publishArtifact := false, //do we need to remove this? also because if root is using "publish / skip := true" instead?
packageSrc / publishArtifact := false, //do we need to remove this? also because if root is using "publish / skip := true" instead?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting - it looks like we've never published the thrift project as an artifact, so actually it would be right to put publish / skip := true on this submodule too!

Compile / unmanagedResourceDirectories += { baseDirectory.value / "src/main/thrift" }
)

Expand All @@ -163,10 +79,10 @@ lazy val npmBetaReleaseTagMaybe =

lazy val typescriptClasses = (project in file("ts"))
.enablePlugins(ScroogeTypescriptGen)
.settings(commonSettings)
.settings(npmBetaReleaseTagMaybe)
.settings(artifactProductionSettings)
.settings(npmBetaReleaseTagMaybe)//do we need to remove this?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we need to remove npmBetaReleaseTagMaybe, along with betaReleaseType & betaReleaseSuffix, etc!

.settings(
publishArtifact := false,
publishArtifact := false, //do we need to remove this? also because if root is using "publish / skip := true" instead?
name := "content-entity-typescript",
scroogeTypescriptNpmPackageName := "@guardian/content-entity-model",
Compile / scroogeDefaultJavaNamespace := scroogeTypescriptNpmPackageName.value,
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.5.7
sbt.version=1.9.8
7 changes: 3 additions & 4 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
addSbtPlugin("com.gu" % "sbt-scrooge-typescript" % "1.6.0")

addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0")
addSbtPlugin("com.github.sbt" % "sbt-release" % "1.4.0")

addSbtPlugin("com.jsuereth" % "sbt-pgp" % "2.0.1")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.10")
addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.10.0")

addSbtPlugin("ch.epfl.scala" % "sbt-version-policy" % "3.2.0")