From c9656b3234f3bb4107d35751e354a469641ca907 Mon Sep 17 00:00:00 2001 From: Tobias Binna Date: Mon, 3 Jun 2024 18:29:59 +0800 Subject: [PATCH] Migrate to Play 3 - Update dependencies, SBT version - Update to Play version 3 - Update Akka imports to Pekko imports - Update to the latest Java LTS version 21 Closes #82 --- .github/workflows/ci.yml | 2 +- build.sbt | 6 +-- .../jwt/ForgeRemoteJWKSourceProvider.scala | 7 +-- .../connect/play/events/EventBus.scala | 4 +- .../connect/play/events/EventBusSpec.scala | 19 ++++--- ...PlayWsAtlassianConnectHttpClientSpec.scala | 49 ++++++++++--------- modules/core/test/resources/logback-test.xml | 33 ++++++------- project/Dependencies.scala | 22 ++++----- project/build.properties | 2 +- project/plugins.sbt | 4 +- 10 files changed, 79 insertions(+), 69 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa4bf84..7613414 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/setup-java@v3 with: distribution: 'temurin' - java-version: '11' + java-version: '21' cache: 'sbt' - name: Compile, test run: sbt clean coverage test coverageReport diff --git a/build.sbt b/build.sbt index 10fe602..0af446f 100644 --- a/build.sbt +++ b/build.sbt @@ -2,11 +2,11 @@ import ReleaseTransformations._ val commonSettings = Seq( organization := "io.toolsplus", - scalaVersion := "2.13.5", + scalaVersion := "2.13.14", versionScheme := Some("early-semver"), resolvers ++= Seq( - "Typesafe repository releases" at "https://repo.typesafe.com/typesafe/releases/", - "Bintary JCenter" at "https://jcenter.bintray.com" + Resolver.typesafeRepo("releases"), + Resolver.jcenterRepo ) ) diff --git a/modules/core/app/io/toolsplus/atlassian/connect/play/auth/frc/jwt/ForgeRemoteJWKSourceProvider.scala b/modules/core/app/io/toolsplus/atlassian/connect/play/auth/frc/jwt/ForgeRemoteJWKSourceProvider.scala index 28cdac3..ed68eca 100644 --- a/modules/core/app/io/toolsplus/atlassian/connect/play/auth/frc/jwt/ForgeRemoteJWKSourceProvider.scala +++ b/modules/core/app/io/toolsplus/atlassian/connect/play/auth/frc/jwt/ForgeRemoteJWKSourceProvider.scala @@ -4,7 +4,7 @@ import com.nimbusds.jose.jwk.source.{JWKSource, JWKSourceBuilder} import com.nimbusds.jose.util.DefaultResourceRetriever import io.toolsplus.atlassian.connect.play.models.AtlassianForgeProperties -import java.net.URL +import java.net.{URI, URL} import javax.inject.Inject import ForgeRemoteJWKSourceProvider._ @@ -28,10 +28,11 @@ class ForgeRemoteJWKSourceProvider @Inject()( JWKSourceBuilder .create[ForgeInvocationContext]( - new URL(jwkSetUrl), + new URI(jwkSetUrl).toURL, new DefaultResourceRetriever(remoteJWKSetHttpConnectTimeoutMs, remoteJWKSetHttpReadTimeoutMs, - remoteJWKSetHttpEntitySizeLimitByte)) + remoteJWKSetHttpEntitySizeLimitByte) + ) .retrying(true) .build() } diff --git a/modules/core/app/io/toolsplus/atlassian/connect/play/events/EventBus.scala b/modules/core/app/io/toolsplus/atlassian/connect/play/events/EventBus.scala index b652cfc..830b21d 100644 --- a/modules/core/app/io/toolsplus/atlassian/connect/play/events/EventBus.scala +++ b/modules/core/app/io/toolsplus/atlassian/connect/play/events/EventBus.scala @@ -1,7 +1,7 @@ package io.toolsplus.atlassian.connect.play.events -import akka.event.{ActorEventBus, SubchannelClassification} -import akka.util.Subclassification +import org.apache.pekko.event.{ActorEventBus, SubchannelClassification} +import org.apache.pekko.util.Subclassification import io.toolsplus.atlassian.connect.play.api.events.AppEvent /** diff --git a/modules/core/test/io/toolsplus/atlassian/connect/play/events/EventBusSpec.scala b/modules/core/test/io/toolsplus/atlassian/connect/play/events/EventBusSpec.scala index 1a9cf47..537608a 100644 --- a/modules/core/test/io/toolsplus/atlassian/connect/play/events/EventBusSpec.scala +++ b/modules/core/test/io/toolsplus/atlassian/connect/play/events/EventBusSpec.scala @@ -1,16 +1,23 @@ package io.toolsplus.atlassian.connect.play.events -import akka.actor.{Actor, ActorSystem, Props} -import akka.testkit.TestProbe +import org.apache.pekko.actor.{Actor, ActorSystem, Props} +import org.apache.pekko.testkit.TestProbe import io.toolsplus.atlassian.connect.play.TestSpec -import io.toolsplus.atlassian.connect.play.api.events.{AppEvent, AppInstalledEvent, AppUninstalledEvent} +import io.toolsplus.atlassian.connect.play.api.events.{ + AppEvent, + AppInstalledEvent, + AppUninstalledEvent +} import io.toolsplus.atlassian.connect.play.generators.AtlassianHostGen import org.scalatestplus.play.guice.GuiceOneAppPerSuite import scala.concurrent.duration._ import scala.language.postfixOps -class EventBusSpec extends TestSpec with GuiceOneAppPerSuite with AtlassianHostGen { +class EventBusSpec + extends TestSpec + with GuiceOneAppPerSuite + with AtlassianHostGen { "Given an EventBus" when { @@ -58,7 +65,7 @@ class EventBusSpec extends TestSpec with GuiceOneAppPerSuite with AtlassianHostG "handle multiple event" in new Context { val listener = system.actorOf(Props(new Actor { def receive = { - case e @ AppInstalledEvent(_) => testProbe.ref ! e + case e @ AppInstalledEvent(_) => testProbe.ref ! e case e @ AppUninstalledEvent(_) => testProbe.ref ! e } })) @@ -106,7 +113,7 @@ class EventBusSpec extends TestSpec with GuiceOneAppPerSuite with AtlassianHostG /** * Play actor system. */ - lazy implicit val system = app.injector.instanceOf[ActorSystem] + lazy implicit val system: ActorSystem = app.injector.instanceOf[ActorSystem] /** * Test probe. diff --git a/modules/core/test/io/toolsplus/atlassian/connect/play/request/ws/PlayWsAtlassianConnectHttpClientSpec.scala b/modules/core/test/io/toolsplus/atlassian/connect/play/request/ws/PlayWsAtlassianConnectHttpClientSpec.scala index b9e93cb..3e56482 100644 --- a/modules/core/test/io/toolsplus/atlassian/connect/play/request/ws/PlayWsAtlassianConnectHttpClientSpec.scala +++ b/modules/core/test/io/toolsplus/atlassian/connect/play/request/ws/PlayWsAtlassianConnectHttpClientSpec.scala @@ -1,12 +1,10 @@ package io.toolsplus.atlassian.connect.play.request.ws -import java.net.URI -import akka.util.ByteString import io.toolsplus.atlassian.connect.play.TestSpec import io.toolsplus.atlassian.connect.play.api.models.AtlassianHost import io.toolsplus.atlassian.connect.play.auth.jwt.symmetric.JwtGenerator -import io.toolsplus.atlassian.connect.play.request.ws.PlayWsAtlassianConnectHttpClient import io.toolsplus.atlassian.connect.play.request.ws.jwt.JwtSignatureCalculator +import org.apache.pekko.util.ByteString import org.scalacheck.Shrink import org.scalatestplus.play.guice.GuiceOneAppPerSuite import play.api.http.HeaderNames.{AUTHORIZATION, USER_AGENT} @@ -15,11 +13,15 @@ import play.api.libs.ws.WSClient import play.api.mvc._ import play.api.test.{Helpers, TestServer, WsTestClient} +import java.net.URI import scala.concurrent.{Future, Promise} -class PlayWsAtlassianConnectHttpClientSpec extends TestSpec with GuiceOneAppPerSuite { +class PlayWsAtlassianConnectHttpClientSpec + extends TestSpec + with GuiceOneAppPerSuite { - val action: DefaultActionBuilder = app.injector.instanceOf[DefaultActionBuilder] + val action: DefaultActionBuilder = + app.injector.instanceOf[DefaultActionBuilder] val parser: PlayBodyParsers = app.injector.instanceOf[PlayBodyParsers] val testServerPort = 44444 @@ -31,7 +33,8 @@ class PlayWsAtlassianConnectHttpClientSpec extends TestSpec with GuiceOneAppPerS "successfully return a WSRequest with resolved host URL" in WsTestClient .withClient { client => - val httpClient = new PlayWsAtlassianConnectHttpClient(client, jwtGenerator) + val httpClient = + new PlayWsAtlassianConnectHttpClient(client, jwtGenerator) forAll(rootRelativePathGen, atlassianHostGen) { (path, host) => val absoluteRequestUri = URI.create(s"${host.baseUrl}$path") val request = httpClient.authenticatedAsAddon(path)(host) @@ -43,25 +46,27 @@ class PlayWsAtlassianConnectHttpClientSpec extends TestSpec with GuiceOneAppPerS implicit val doNotShrinkStrings: Shrink[String] = Shrink.shrinkAny forAll(atlassianHostGen) { host => val path = "foo" - forAll(symmetricJwtCredentialsGen(host, subject = "bar")) { credentials => - val absoluteRequestUri = - URI.create(s"http://localhost:$testServerPort/$path") + forAll(symmetricJwtCredentialsGen(host, subject = "bar")) { + credentials => + val absoluteRequestUri = + URI.create(s"http://localhost:$testServerPort/$path") - (jwtGenerator - .createJwtToken(_: String, _: URI, _: AtlassianHost)) - .expects("GET", absoluteRequestUri, host) - .returning(Right(credentials.rawJwt)) + (jwtGenerator + .createJwtToken(_: String, _: URI, _: AtlassianHost)) + .expects("GET", absoluteRequestUri, host) + .returning(Right(credentials.rawJwt)) - val (request, _, _) = receiveRequest { hostUrl => wsClient => - val httpClient = new PlayWsAtlassianConnectHttpClient(wsClient, jwtGenerator) + val (request, _, _) = receiveRequest { hostUrl => wsClient => + val httpClient = + new PlayWsAtlassianConnectHttpClient(wsClient, jwtGenerator) - httpClient.authenticatedAsAddon(s"$hostUrl/$path")(host).get() - } - request.headers(AUTHORIZATION).startsWith("JWT ") mustBe true - request - .headers(AUTHORIZATION) - .drop("JWT ".length) mustBe credentials.rawJwt - request.headers(USER_AGENT) mustBe JwtSignatureCalculator.userAgent + httpClient.authenticatedAsAddon(s"$hostUrl/$path")(host).get() + } + request.headers(AUTHORIZATION).startsWith("JWT ") mustBe true + request + .headers(AUTHORIZATION) + .drop("JWT ".length) mustBe credentials.rawJwt + request.headers(USER_AGENT) mustBe JwtSignatureCalculator.userAgent } } } diff --git a/modules/core/test/resources/logback-test.xml b/modules/core/test/resources/logback-test.xml index 7229ee8..d716880 100644 --- a/modules/core/test/resources/logback-test.xml +++ b/modules/core/test/resources/logback-test.xml @@ -1,29 +1,26 @@ + + + + - - - - + + %coloredLevel %logger{15} - %message%n%xException{10} - - - - + + + - + - - - - - - - - - + + + + + \ No newline at end of file diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 938c298..f0cd7bd 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -17,24 +17,24 @@ object Dependencies { Library.scalaMock % "test", Library.scalaCheck % "test", Library.atlassianJwtGenerators % "test", - Library.akkaTestKit % "test" + Library.pekkoTestKit % "test" ) } object Version { - val atlassianJwt = "0.2.1" - val cats = "2.10.0" + val atlassianJwt = "0.3.0" + val cats = "2.12.0" val circe = "0.14.7" - val playCirce = "2814.4" + val playCirce = "3014.1" val scalaUri = "4.0.3" val sttp = "3.9.6" - val nimbusJoseJwt = "9.39" + val nimbusJoseJwt = "9.39.3" val scalaTest = "3.2.18" - val scalaTestPlusPlay = "5.1.0" - val scalaTestPlusScalaCheck = "3.2.11.0" - val scalaMock = "5.1.0" + val scalaTestPlusPlay = "7.0.1" + val scalaTestPlusScalaCheck = "3.2.18.0" + val scalaMock = "6.0.0" val scalaCheck = "1.18.0" - val akkaTestKit = "2.6.21" + val pekkoTestKit = "1.0.2" } object Library { @@ -49,9 +49,9 @@ object Library { val sttp = "com.softwaremill.sttp.client3" %% "core" % Version.sttp val nimbusJoseJwt = "com.nimbusds" % "nimbus-jose-jwt" % Version.nimbusJoseJwt val scalaTest = "org.scalatest" %% "scalatest" % Version.scalaTest - val scalaTestPlusScalaCheck = "org.scalatestplus" %% "scalacheck-1-15" % Version.scalaTestPlusScalaCheck + val scalaTestPlusScalaCheck = "org.scalatestplus" %% "scalacheck-1-17" % Version.scalaTestPlusScalaCheck val scalaTestPlusPlay = "org.scalatestplus.play" %% "scalatestplus-play" % Version.scalaTestPlusPlay val scalaMock = "org.scalamock" %% "scalamock" % Version.scalaMock val scalaCheck = "org.scalacheck" %% "scalacheck" % Version.scalaCheck - val akkaTestKit = "com.typesafe.akka" %% "akka-testkit" % Version.akkaTestKit + val pekkoTestKit = "org.apache.pekko" %% "pekko-testkit" % Version.pekkoTestKit } diff --git a/project/build.properties b/project/build.properties index 19479ba..081fdbb 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.5.2 +sbt.version=1.10.0 diff --git a/project/plugins.sbt b/project/plugins.sbt index f259dce..0929242 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,5 +1,5 @@ -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.8.20") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.6.1") +addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.3") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.12") addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.0") addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.2")