diff options
Diffstat (limited to 'integration/test/resources/play-json/build.sc')
-rw-r--r-- | integration/test/resources/play-json/build.sc | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/integration/test/resources/play-json/build.sc b/integration/test/resources/play-json/build.sc new file mode 100644 index 00000000..e5222ae1 --- /dev/null +++ b/integration/test/resources/play-json/build.sc @@ -0,0 +1,371 @@ +import mill._, mill.scalalib._, mill.scalalib.publish._, mill.scalajslib._ +import $file.version +import $file.reformat +import reformat.Scalariform +import $file.mima +import mima.MiMa +import $file.headers +import $file.jmh +import jmh.Jmh +import headers.Headers +import com.typesafe.tools.mima.core._ + +import ammonite.ops._ +import mill.define.Task + +val ScalaVersions = Seq("2.10.7", "2.11.12", "2.12.4", "2.13.0-M3") + +trait BaseModule extends CrossSbtModule with Scalariform with Headers + +trait PlayJsonModule extends BaseModule with PublishModule with MiMa { + + def pomSettings = PomSettings( + description = artifactName(), + organization = "com.typesafe.play", + url = "https://github.com/playframework/play-json", + licenses = Seq(License.`Apache-2.0`), + versionControl = VersionControl.github("playframework", "play-json"), + developers = Seq( + Developer( + id = "playframework", + name = "Play Framework Team", + url = "https://github.com/playframework" + ) + ) + ) + + trait Tests extends super.Tests with Scalariform with Headers { + val specs2Core = T { + val v = Lib.scalaBinaryVersion(scalaVersion()) match { + case "2.10" => "3.9.1" + case _ => "4.0.2" + } + ivy"org.specs2::specs2-core:$v" + } + } + + def scalacOptions = Seq("-deprecation", "-feature", "-unchecked", "-encoding", "utf8") + def javacOptions = Seq("-encoding", "UTF-8", "-Xlint:-options") + + def publishVersion = version.current +} + +abstract class PlayJson(val platformSegment: String) extends PlayJsonModule { + def crossScalaVersion: String + def millSourcePath = pwd / "play-json" + def artifactName = "play-json" + + def sources = T.sources( + millSourcePath / platformSegment / "src" / "main", + millSourcePath / "shared" / "src" / "main" + ) + + def ivyDeps = Agg( + ivy"org.scala-lang:scala-reflect:${scalaVersion()}", + ivy"org.typelevel::macro-compat::1.1.1" + ) + + private val macroParadise = ivy"org.scalamacros:::paradise:2.1.0" + + def compileIvyDeps = Agg( + macroParadise, + ivy"org.scala-lang:scala-compiler:${scalaVersion()}" + ) + + def scalacPluginIvyDeps = Agg(macroParadise) + + def mimaBinaryIssueFilters = Seq( + // AbstractFunction1 is in scala.runtime and isn't meant to be used by end users + ProblemFilters.exclude[MissingTypesProblem]("play.api.libs.json.JsArray$"), + ProblemFilters.exclude[MissingTypesProblem]("play.api.libs.json.JsObject$"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultWrites.BigIntWrites"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultWrites.BigIntegerWrites"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultReads.BigIntReads"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultReads.BigIntegerReads"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultWrites.BigIntWrites"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultWrites.BigIntegerWrites"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultReads.BigIntReads"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.DefaultReads.BigIntegerReads"), + ProblemFilters.exclude[ReversedMissingMethodProblem]("play.api.libs.json.JsonConfiguration.optionHandlers") + ) + + def generatedSources = T { + import ammonite.ops._ + + val dir = T.ctx().dest + mkdir(dir / "play-json") + val file = dir / "play-json" / "Generated.scala" + + val (writes, reads) = (1 to 22).map { i => + def commaSeparated(s: Int => String) = (1 to i).map(s).mkString(", ") + + def newlineSeparated(s: Int => String) = (1 to i).map(s).mkString("\n") + + val writerTypes = commaSeparated(j => s"T$j: Writes") + val readerTypes = commaSeparated(j => s"T$j: Reads") + val typeTuple = commaSeparated(j => s"T$j") + val written = commaSeparated(j => s"implicitly[Writes[T$j]].writes(x._$j)") + val readValues = commaSeparated(j => s"t$j") + val readGenerators = newlineSeparated(j => s"t$j <- implicitly[Reads[T$j]].reads(arr(${j - 1}))") + ( + s""" + implicit def Tuple${i}W[$writerTypes]: Writes[Tuple${i}[$typeTuple]] = Writes[Tuple${i}[$typeTuple]]( + x => JsArray(Array($written)) + ) + """, + s""" + implicit def Tuple${i}R[$readerTypes]: Reads[Tuple${i}[$typeTuple]] = Reads[Tuple${i}[$typeTuple]]{ + case JsArray(arr) if arr.size == $i => + for{ + $readGenerators + } yield Tuple$i($readValues) + + case _ => + JsError(Seq(JsPath() -> Seq(JsonValidationError("Expected array of $i elements")))) + } + """) + }.unzip + + write(file, s""" + package play.api.libs.json + + trait GeneratedReads { + ${reads.mkString("\n")} + } + + trait GeneratedWrites{ + ${writes.mkString("\n")} + } + """) + + Seq(PathRef(dir)) + } +} + +object playJsonJvm extends Cross[PlayJsonJvm](ScalaVersions:_*) +class PlayJsonJvm(val crossScalaVersion: String) extends PlayJson("jvm") { + def moduleDeps = Seq(playFunctionalJvm(crossScalaVersion)) + + val jacksonVersion = "2.9.3" + + def ivyDeps = super.ivyDeps() ++ Agg( + ivy"joda-time:joda-time:2.9.9", + ivy"com.fasterxml.jackson.core:jackson-core:$jacksonVersion", + ivy"com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion", + ivy"com.fasterxml.jackson.core:jackson-databind:$jacksonVersion", + ivy"com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion", + ivy"com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonVersion" + ) + + object test extends Tests { + def ivyDeps = + Agg( + ivy"org.scalatest::scalatest:3.0.5-M1", + ivy"org.scalacheck::scalacheck:1.13.5", + ivy"com.chuusai::shapeless:2.3.3", + ivy"ch.qos.logback:logback-classic:1.2.3", + specs2Core() + ) + + def sources = { + val docSpecs = ls.rec(millSourcePath / up / "docs" / "manual" / "working" / "scalaGuide").filter(_.isDir).filter(_.last=="code").map(PathRef(_)) + T.sources( + docSpecs ++ + Seq( + PathRef(millSourcePath / platformSegment / "src" / "test"), + PathRef(millSourcePath / "shared" / "src" / "test") + ) + ) + } + + def testFrameworks = Seq( + "org.scalatest.tools.Framework", + "org.specs2.runner.Specs2Framework" + ) + } + +} + +object playJsonJs extends Cross[PlayJsonJs](ScalaVersions:_*) +class PlayJsonJs(val crossScalaVersion: String) extends PlayJson("js") with ScalaJSModule { + def moduleDeps = Seq(playFunctionalJs(crossScalaVersion)) + + def scalaJSVersion = "0.6.22" + + // TODO: remove super[PlayJson].Tests with super[ScalaJSModule].Tests hack + object test extends super[PlayJson].Tests with super[ScalaJSModule].Tests with Scalariform with Headers { + def ivyDeps = + Agg( + ivy"org.scalatest::scalatest::3.0.5-M1", + ivy"org.scalacheck::scalacheck::1.13.5", + ivy"com.chuusai::shapeless::2.3.3" + ) + + def sources = T.sources( + millSourcePath / platformSegment / "src" / "test", + millSourcePath / "shared" / "src" / "test" + ) + + def testFrameworks = Seq( + "org.scalatest.tools.Framework" + ) + } +} + +trait PlayFunctional extends PlayJsonModule { + def millSourcePath = pwd / "play-functional" + def artifactName = "play-functional" +} + +object playFunctionalJvm extends Cross[PlayFunctionalJvm](ScalaVersions:_*) +class PlayFunctionalJvm(val crossScalaVersion: String) extends PlayFunctional + +object playFunctionalJs extends Cross[PlayFunctionalJs](ScalaVersions:_*) +class PlayFunctionalJs(val crossScalaVersion: String) extends PlayFunctional with ScalaJSModule { + def scalaJSVersion = "0.6.22" +} + +object playJoda extends Cross[PlayJoda](ScalaVersions:_*) +class PlayJoda(val crossScalaVersion: String) extends PlayJsonModule { + def moduleDeps = Seq(playJsonJvm(crossScalaVersion)) + + def millSourcePath = pwd / "play-json-joda" + def artifactName = "play-json-joda" + + def ivyDeps = Agg( + ivy"joda-time:joda-time:2.9.9" + ) + + object test extends Tests { + def ivyDeps = Agg(specs2Core()) + + def testFrameworks = Seq( + "org.specs2.runner.Specs2Framework" + ) + } + +} + +object benchmarks extends Cross[Benchmarks](ScalaVersions:_*) +class Benchmarks(val crossScalaVersion: String) extends BaseModule with Jmh { + def moduleDeps = Seq(playJsonJvm(crossScalaVersion)) + + def millSourcePath = pwd / "benchmarks" +} + +// TODO: we should have a way to "take all modules in this build" +val testModules = Seq( + playJsonJvm("2.12.4").test, + playJsonJs("2.12.4").test, + playJoda("2.12.4").test +) + +val sourceModules = Seq( + playJsonJvm("2.12.4"), + playJsonJs("2.12.4"), + playJoda("2.12.4"), +) + +val allModules = testModules ++ sourceModules + +def reportBinaryIssues() = T.command { + Task.traverse(sourceModules) { module => + module.mimaReportBinaryIssues.map(issues => module.millModuleSegments.render -> issues) + }.map { issues => + val issuesByModules = issues.flatMap { case (moduleName, issues) => + val messageForModule = issues.foldLeft(Seq.empty[String]) { case (acc, (artifact, problems)) => + val elem = if(problems.nonEmpty) { + Some( + s"""Compared to artifact: ${artifact} + |found ${problems.size} binary incompatibilities: + |${problems.mkString("\n")} + """.stripMargin + ) + } else { + None + } + acc ++ elem + } + if(messageForModule.nonEmpty) { + Some( + s""" + |For module: ${moduleName}: + |${messageForModule.mkString("\n")} + """.stripMargin + ) + } else { + None + } + } + + if(issuesByModules.nonEmpty) { + sys.error(issuesByModules.mkString("\n")) + } + } +} + +def validateCode() = T.command { + Task.traverse(allModules)(_.checkCodeFormat()).zip(Task.traverse(allModules)(_.headerCheck())) +} + +/** + * Release steps are: + * 1) clean + * 2) run tests + * 3) set release version + * 4) commit release version + * 5) make release tag + * 6) publish all modules to sonatype + * 7) set next version + * 8) commit next version + * 9) push everything to git + */ +object release extends Module { + + implicit val wd = pwd + + val versionFile = wd / "version.sc" + + private val ReleaseVersion = raw"""(\d+)\.(\d+)\.(\d+)""".r + private val MinorSnapshotVersion = raw"""(\d+)\.(\d+)\.(\d+)-SNAPSHOT""".r + + private val releaseVersion = version.current match { + case MinorSnapshotVersion(major, minor, patch) => + s"${major}.${minor}.${patch.toInt}" + case ReleaseVersion(major, minor, patch) => + s"${major}.${minor}.${patch.toInt}" + } + + private val nextVersion = version.current match { + case v@MinorSnapshotVersion(major, minor, patch) => v + case ReleaseVersion(major, minor, patch) => + s"${major}.${minor}.${patch.toInt + 1}-SNAPSHOT" + } + + def setReleaseVersion = T { + T.ctx.log.info(s"Setting release version to ${releaseVersion}") + + write.over( + versionFile, + s"""def current = "${releaseVersion}" + | + """.stripMargin + ) + + %%("git", "commit", "-am", s"Setting release version to ${releaseVersion}") + %%("git", "tag", s"$releaseVersion") + } + + def setNextVersion = T { + T.ctx.log.info(s"Setting next version to ${nextVersion}") + + write.over( + versionFile, + s"""def current = "${nextVersion}"""" + ) + + %%("git", "commit", "-am", s"Setting next version to ${nextVersion}") + %%("git", "push", "origin", "master", "--tags") + } + +} |