build.sbt (205 lines of code) (raw):

import play.sbt.PlayImport.PlayKeys._ import sbt.Package.FixedTimestamp import scala.sys.process._ import scala.util.control.NonFatal import scala.collection.JavaConverters._ import com.typesafe.sbt.packager.debian.JDebPackaging // We need to keep the timestamps to allow caching headers to work as expected on assets. // The below should work, but some problem in one of the plugins (possible the play plugin? or sbt-web?) causes // the option not to be passed correctly // ThisBuild / packageTimestamp := Package.keepTimestamps // Setting as a packageOption seems to bypass that problem, wherever it lies ThisBuild / packageOptions += FixedTimestamp(Package.keepTimestamps) // Currently multiple modules depend on scala-java8-compat, some on 0.8.x, 0.9.x and 1.x.y // These may be binary incompatible, but force the checker to accept them // In the future, check if this override can be removed ThisBuild / libraryDependencySchemes += "org.scala-lang.modules" %% "scala-java8-compat" % VersionScheme.Always val commonSettings = Seq( scalaVersion := "2.13.16", description := "grid", organization := "com.gu", version := "0.1", scalacOptions ++= Seq("-feature", "-deprecation", "-language:higherKinds", "-Xfatal-warnings", "-release:11"), // The Java SDK uses CBOR protocol // We use localstack in TEST. Kinesis in localstack uses kinesislite which requires CBOR to be disabled // This is likely go away soon, see https://github.com/localstack/localstack/issues/1930 Test / envVars := Map("AWS_CBOR_DISABLE" -> "true"), Test / testOptions ++= Seq(Tests.Argument(TestFrameworks.ScalaTest, "-o"), Tests.Argument(TestFrameworks.ScalaTest, "-u", "logs/test-reports")), libraryDependencies ++= Seq( "org.scalatest" %% "scalatest" % "3.2.19" % Test, "org.scalatestplus.play" %% "scalatestplus-play" % "7.0.1" % Test, "org.scalatestplus" %% "mockito-3-4" % "3.1.4.0" % Test, "org.mockito" % "mockito-core" % "2.18.0" % Test, "org.scalamock" %% "scalamock" % "5.1.0" % Test, ), dependencyOverrides += "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.17.2", Compile / doc / sources := Seq.empty, Compile / packageDoc / publishArtifact := false ) //Common projects to all organizations lazy val commonProjects: Seq[sbt.ProjectReference] = Seq(commonLib, restLib, auth, collections, cropper, imageLoader, leases, thrall, kahuna, metadataEditor, usage, mediaApi) lazy val root = project("grid", path = Some(".")) .aggregate((maybeBBCLib.toList ++ commonProjects):_*) addCommandAlias("runAll", "all auth/run media-api/run thrall/run image-loader/run metadata-editor/run kahuna/run collections/run cropper/run usage/run leases/run") addCommandAlias("runMinimal", "all auth/run media-api/run kahuna/run") // Required to allow us to run more than four play projects in parallel from a single SBT shell Global / concurrentRestrictions := Seq( Tags.limit(Tags.CPU, Math.min(1, java.lang.Runtime.getRuntime.availableProcessors - 1)), Tags.limit(Tags.Test, 1), Tags.limitAll(12) ) val awsSdkVersion = "1.12.470" val elastic4sVersion = "8.3.0" val okHttpVersion = "3.12.1" val bbcBuildProcess: Boolean = System.getenv().asScala.get("BUILD_ORG").contains("bbc") //BBC specific project, it only gets compiled when bbcBuildProcess is true lazy val bbcProject = project("bbc").dependsOn(restLib % "compile->compile;test->test") val maybeBBCLib: Option[sbt.ProjectReference] = if(bbcBuildProcess) Some(bbcProject) else None lazy val commonLib = project("common-lib").settings( libraryDependencies ++= Seq( "com.gu" %% "editorial-permissions-client" % "4.0.0", "com.gu" %% "pan-domain-auth-play_3-0" % "9.0.0", "com.amazonaws" % "aws-java-sdk-iam" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-s3" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-ec2" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-cloudwatch" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-cloudfront" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-sqs" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-sns" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-sts" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-dynamodb" % awsSdkVersion, "com.amazonaws" % "aws-java-sdk-kinesis" % awsSdkVersion, "com.sksamuel.elastic4s" %% "elastic4s-core" % elastic4sVersion, "com.sksamuel.elastic4s" %% "elastic4s-client-esjava" % elastic4sVersion, "com.sksamuel.elastic4s" %% "elastic4s-domain" % elastic4sVersion, "com.gu" %% "thrift-serializer" % "5.0.2", "org.scalaz" %% "scalaz-core" % "7.3.8", "org.im4java" % "im4java" % "1.4.0", "com.gu" % "kinesis-logback-appender" % "1.4.4", "net.logstash.logback" % "logstash-logback-encoder" % "5.0", logback, // play-logback; needed when running the scripts "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2", "org.scalacheck" %% "scalacheck" % "1.14.0", "com.typesafe.scala-logging" %% "scala-logging" % "3.9.2", // needed to parse conditional statements in `logback.xml` // i.e. to only log to disk in DEV // see: https://logback.qos.ch/setup.html#janino "org.codehaus.janino" % "janino" % "3.0.6", "org.playframework" %% "play-json-joda" % "3.0.4", "org.scanamo" %% "scanamo" % "2.0.0", // Necessary to have a mix of play library versions due to scala-java8-compat incompatibility ws, "org.testcontainers" % "elasticsearch" % "1.19.2" % Test ), dependencyOverrides += "ch.qos.logback" % "logback-classic" % "1.2.13" % Test ) lazy val restLib = project("rest-lib").settings( libraryDependencies ++= Seq( playCore, filters, pekkoHttpServer, ), ).dependsOn(commonLib % "compile->compile;test->test") lazy val auth = playProject("auth", 9011) lazy val collections = playProject("collections", 9010) lazy val cropper = playProject("cropper", 9006) lazy val imageLoader = playProject("image-loader", 9003).settings { libraryDependencies ++= Seq( "org.apache.tika" % "tika-core" % "1.28.5", "com.drewnoakes" % "metadata-extractor" % "2.19.0" ) } lazy val kahuna = playProject("kahuna", 9005).settings( pipelineStages := Seq(digest, gzip) ) lazy val leases = playProject("leases", 9012) lazy val mediaApi = playProject("media-api", 9001) .dependsOn(commonLib % "compile;test->test") .settings( libraryDependencies ++= Seq( "org.apache.commons" % "commons-email" % "1.5", "org.parboiled" %% "parboiled" % "2.1.7", "org.http4s" %% "http4s-core" % "0.23.17", ) ) lazy val metadataEditor = playProject("metadata-editor", 9007) lazy val thrall = playProject("thrall", 9002) .dependsOn(commonLib % "compile;test->test") .settings( pipelineStages := Seq(digest, gzip), libraryDependencies ++= Seq( "org.codehaus.groovy" % "groovy-json" % "3.0.7", // TODO upgrading kcl to v3? check if you can remove avro override below "software.amazon.kinesis" % "amazon-kinesis-client" % "2.6.1", "com.gu" %% "kcl-pekko-stream" % "0.1.0", "org.testcontainers" % "elasticsearch" % "1.19.2" % Test, "com.google.protobuf" % "protobuf-java" % "3.19.6" ), // amazon-kinesis-client 2.6.0 brings in a critically vulnerable version of apache avro, // but we cannot upgrade amazon-kinesis-client further without performing the v2->v3 upgrade https://docs.aws.amazon.com/streams/latest/dev/kcl-migration-from-2-3.html dependencyOverrides ++= Seq( "org.apache.avro" % "avro" % "1.11.4", "org.apache.pekko" %% "pekko-stream" % "1.0.3" ) ) lazy val usage = playProject("usage", 9009).settings( libraryDependencies ++= Seq( "com.gu" %% "content-api-client-default" % "32.0.0", "com.gu" %% "content-api-client-aws" % "0.7.6", "io.reactivex" %% "rxscala" % "0.27.0", // amazon-kinesis-client brings in a critical vulnerability warning through apache avro, resolved in versions 1.11.4 and 1.12.0. // updating amazon-kinesis-client? check if the override below can be removed "software.amazon.kinesis" % "amazon-kinesis-client" % "3.0.2", "com.google.protobuf" % "protobuf-java" % "3.19.6" ), dependencyOverrides ++= Seq( "org.apache.avro" % "avro" % "1.11.4", ) ) val awsSdkV2Version = "2.15.81" lazy val scripts = project("scripts") .dependsOn(commonLib) .enablePlugins(JavaAppPackaging, UniversalPlugin) .settings( libraryDependencies ++= Seq( // V2 of the AWS SDK as it's easier to use for scripts and won't leak to the rest of the project from here "software.amazon.awssdk" % "s3" % awsSdkV2Version, "software.amazon.awssdk" % "dynamodb" % awsSdkV2Version, // bump jcommander explicitly as AWS SDK is pulling in a vulnerable version "com.beust" % "jcommander" % "1.75", "org.apache.commons" % "commons-compress" % "1.27.1", "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "2.6.4" ) ) def project(projectName: String, path: Option[String] = None): Project = Project(projectName, file(path.getOrElse(projectName))) .settings(commonSettings) def maybeLocalGit(): Option[String] = { try { Some("git rev-parse HEAD".!!.trim) } catch { case NonFatal(e) => None } } val buildInfo = Seq( buildInfoKeys := Seq[BuildInfoKey]( name, BuildInfoKey.constant("gitCommitId", Option(System.getenv("BUILD_VCS_NUMBER")) orElse maybeLocalGit() getOrElse "unknown") ), buildInfoPackage := "utils.buildinfo", buildInfoOptions := Seq( BuildInfoOption.Traits("com.gu.mediaservice.lib.management.BuildInfo"), BuildInfoOption.ToJson ) ) def playProject(projectName: String, port: Int, path: Option[String] = None): Project = { val commonProject = project(projectName, path) .enablePlugins(PlayScala, JDebPackaging, SystemdPlugin, BuildInfoPlugin) .dependsOn(restLib) .settings(commonSettings ++ buildInfo ++ Seq( playDefaultPort := port, debianPackageDependencies := Seq("java11-runtime-headless"), Linux / maintainer := "Guardian Developers <dig.dev.software@theguardian.com>", Linux / packageSummary := description.value, packageDescription := description.value, bashScriptEnvConfigLocation := Some("/etc/environment"), Debian / makeEtcDefault := None, Debian / packageBin := { val originalFileName = (Debian / packageBin).value val (base, ext) = originalFileName.baseAndExt val newBase = base.replace(s"_${version.value}_all","") val newFileName = file(originalFileName.getParent) / s"$newBase.$ext" IO.move(originalFileName, newFileName) println(s"Renamed $originalFileName to $newFileName") newFileName }, Universal / mappings ++= Seq( file("common-lib/src/main/resources/application.conf") -> "conf/application.conf", file("common-lib/src/main/resources/logback.xml") -> "conf/logback.xml" ), Universal / javaOptions ++= Seq( "-Dpidfile.path=/dev/null", s"-Dconfig.file=/usr/share/$projectName/conf/application.conf", s"-Dlogger.file=/usr/share/$projectName/conf/logback.xml", "-J-Xlog:gc*", s"-J-Xlog:gc:/var/log/$projectName/gc.log" ) )) //Add the BBC library dependency if defined maybeBBCLib.fold(commonProject){commonProject.dependsOn(_)} }