summaryrefslogtreecommitdiff
path: root/integration/test/resources/play-json/build.sc
diff options
context:
space:
mode:
authorNikolay Tatarinov <5min4eq.unity@gmail.com>2018-03-28 01:33:11 +0300
committerGitHub <noreply@github.com>2018-03-28 01:33:11 +0300
commit83aeb8976d90ad1637243953a9af37e6d4206c52 (patch)
tree346e52db0d80c7fb7bdab8013acb38ef8be55fbb /integration/test/resources/play-json/build.sc
parenta796f0a1381632560b6251a93466957319065966 (diff)
downloadmill-83aeb8976d90ad1637243953a9af37e6d4206c52.tar.gz
mill-83aeb8976d90ad1637243953a9af37e6d4206c52.tar.bz2
mill-83aeb8976d90ad1637243953a9af37e6d4206c52.zip
WIP: Play json build (#182)
* play json build * build progress * add check task * try to make play json js build * scalariform and mima plugins in separate files. check mima * better error message for mima compatibility check * fix scala 2.10 compilation * license headers support * add jmh support * fix reformat on compile; fix code validation; extract base module * remove scala 2.13 from cross versions * include play-json in integration tests * add example .travis.yml * bring back scala 2.13 support * make reformat target, not command * add release task * update mill version in travis.yml * update release script * update release process * add README.md for play json build
Diffstat (limited to 'integration/test/resources/play-json/build.sc')
-rw-r--r--integration/test/resources/play-json/build.sc371
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")
+ }
+
+}