diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08d7269..3833e1f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,18 +23,19 @@ jobs: strategy: matrix: os: [ubuntu-latest] - scala: [2.13.11, 3.3.0] + scala: [2_13, 3_0] java: [temurin@11] + scalaPlatform: [jvm] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Java (temurin@11) if: matrix.java == 'temurin@11' - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 @@ -49,19 +50,10 @@ jobs: run: gem install jekyll -v 4.1.1 - name: Check that workflows are up to date - run: sbt '++ ${{ matrix.scala }}' githubWorkflowCheck + run: sbt githubWorkflowCheck - name: Build project - run: sbt '++ ${{ matrix.scala }}' test makeMicrosite publishLocal - - - name: Compress target directories - run: tar cf targets.tar modules/benchmarks/target target modules/munit/target docs/target modules/weaver/target modules/scalatest/target modules/core/target modules/cats/target modules/coretest/target project/target - - - name: Upload target directories - uses: actions/upload-artifact@v3 - with: - name: target-${{ matrix.os }}-${{ matrix.scala }}-${{ matrix.java }} - path: targets.tar + run: sbt 'test_${{ matrix.scala }}_${{ matrix.scalaPlatform }}' 'publishLocal_${{ matrix.scala }}_${{ matrix.scalaPlatform }}' makeMicrosite publish: name: Publish Artifacts @@ -75,38 +67,18 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Java (temurin@11) if: matrix.java == 'temurin@11' - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 cache: sbt - - name: Download target directories (2.13.11) - uses: actions/download-artifact@v3 - with: - name: target-${{ matrix.os }}-2.13.11-${{ matrix.java }} - - - name: Inflate target directories (2.13.11) - run: | - tar xf targets.tar - rm targets.tar - - - name: Download target directories (3.3.0) - uses: actions/download-artifact@v3 - with: - name: target-${{ matrix.os }}-3.3.0-${{ matrix.java }} - - - name: Inflate target directories (3.3.0) - run: | - tar xf targets.tar - rm targets.tar - - name: Setup ruby uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml index 547aaa4..bfc865d 100644 --- a/.github/workflows/clean.yml +++ b/.github/workflows/clean.yml @@ -17,6 +17,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Delete artifacts + shell: bash {0} run: | # Customize those three lines with your repository and credentials: REPO=${GITHUB_API_URL}/repos/${{ github.repository }} @@ -25,7 +26,7 @@ jobs: ghapi() { curl --silent --location --user _:$GITHUB_TOKEN "$@"; } # A temporary file which receives HTTP response headers. - TMPFILE=/tmp/tmp.$$ + TMPFILE=$(mktemp) # An associative array, key: artifact name, value: number of artifacts of that name. declare -A ARTCOUNT diff --git a/build.sbt b/build.sbt index abfe3ea..df937e8 100644 --- a/build.sbt +++ b/build.sbt @@ -1,22 +1,24 @@ +import sbt.internal.ProjectMatrix import sbtghactions.JavaSpec +import complete.DefaultParsers._ +import sbt.Reference.display val munitVersion = "0.7.29" val catsVersion = "2.9.0" val scalatestVersion = "3.2.16" val weaverVersion = "0.8.3" -val scala213 = "2.13.11" -val scala3 = "3.3.0" - val isScala3 = Def.setting { // doesn't work well with >= 3.0.0 for `3.0.0-M1` scalaVersion.value.startsWith("3") } +val mainScalaVersion = Build.Scala213 +val jvmScalaVersions = Seq(Build.Scala213, Build.Scala3) + inThisBuild( List( - scalaVersion := scala213, - crossScalaVersions := Seq(scala213, scala3), + scalaVersion := mainScalaVersion, organization := "com.github.jatcwang", homepage := Some(url("https://github.com/jatcwang/difflicious")), licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")), @@ -28,16 +30,21 @@ inThisBuild( url("https://almostfunctional.com"), ), ), + commands ++= Build.createBuildCommands(allModules), ), ) +lazy val allModules = Seq(core, coretest, munit, scalatest, weaver, cats, benchmarks, docs).flatMap(_.projectRefs) + lazy val difflicious = Project("difflicious", file(".")) - .aggregate(core, coretest, benchmarks, cats, docs, munit, scalatest, weaver) + .aggregate(allModules: _*) .settings(commonSettings, noPublishSettings) -lazy val core = Project("difflicious-core", file("modules/core")) +lazy val core = projectMatrix + .in(file("modules/core")) .settings(commonSettings) .settings( + name := "difflicious-core", libraryDependencies ++= Seq( "dev.zio" %% "izumi-reflect" % "2.3.8", "com.lihaoyi" %% "fansi" % "0.4.0", @@ -46,7 +53,7 @@ lazy val core = Project("difflicious-core", file("modules/core")) } else Seq( "com.softwaremill.magnolia1_2" %% "magnolia" % "1.0.0", - "org.scala-lang" % "scala-reflect" % scala213, + "org.scala-lang" % "scala-reflect" % Build.Scala213, )), Compile / sourceGenerators += Def.task { val file = (Compile / sourceManaged).value / "difflicious" / "TupleDifferInstances.scala" @@ -54,38 +61,50 @@ lazy val core = Project("difflicious-core", file("modules/core")) Seq(file) }.taskValue, ) + .jvmPlatform(jvmScalaVersions) -lazy val munit = Project("difflicious-munit", file("modules/munit")) +lazy val munit = projectMatrix + .in(file("modules/munit")) .dependsOn(core) .settings(commonSettings) .settings( + name := "difflicious-munit", libraryDependencies ++= Seq( "org.scalameta" %% "munit" % munitVersion, ), ) + .jvmPlatform(jvmScalaVersions) -lazy val scalatest = Project("difflicious-scalatest", file("modules/scalatest")) +lazy val scalatest = projectMatrix + .in(file("modules/scalatest")) .dependsOn(core) .settings(commonSettings) .settings( + name := "difflicious-scalatest", libraryDependencies ++= Seq( "org.scalatest" %% "scalatest-core" % scalatestVersion, ), ) + .jvmPlatform(jvmScalaVersions) -lazy val weaver = Project("difflicious-weaver", file("modules/weaver")) +lazy val weaver = projectMatrix + .in(file("modules/weaver")) .dependsOn(core) .settings(commonSettings) .settings( + name := "difflicious-weaver", libraryDependencies ++= Seq( "com.disneystreaming" %% "weaver-core" % weaverVersion, ), ) + .jvmPlatform(jvmScalaVersions) -lazy val cats = Project("difflicious-cats", file("modules/cats")) +lazy val cats = projectMatrix + .in(file("modules/cats")) .dependsOn(core, coretest % "test->test") .settings(commonSettings) .settings( + name := "difflicious-cats", libraryDependencies ++= Seq( "org.typelevel" %% "cats-core" % catsVersion, ), @@ -93,11 +112,14 @@ lazy val cats = Project("difflicious-cats", file("modules/cats")) "org.typelevel" %% "cats-laws" % catsVersion, ).map(_ % Test), ) + .jvmPlatform(jvmScalaVersions) -lazy val coretest = Project("coretest", file("modules/coretest")) +lazy val coretest = projectMatrix + .in(file("modules/coretest")) .dependsOn(core) .settings(commonSettings, noPublishSettings) .settings( + name := "coretest", libraryDependencies ++= Seq( "org.typelevel" %% "cats-core" % catsVersion, ), @@ -107,11 +129,13 @@ lazy val coretest = Project("coretest", file("modules/coretest")) "org.scalameta" %% "munit-scalacheck" % munitVersion, ).map(_ % Test), ) + .jvmPlatform(jvmScalaVersions) -lazy val docs: Project = project +lazy val docs: ProjectMatrix = projectMatrix .dependsOn(core, coretest, cats, munit, scalatest, weaver) .enablePlugins(MicrositesPlugin) .settings( + name := "docs", commonSettings, publish / skip := true, ) @@ -157,12 +181,15 @@ lazy val docs: Project = project (opts ++ extraOpts).filterNot(removes) }, ) + .jvmPlatform(Seq(Build.Scala213)) -lazy val benchmarks = Project("benchmarks", file("modules/benchmarks")) +lazy val benchmarks = projectMatrix + .in(file("modules/benchmarks")) .dependsOn(coretest) .enablePlugins(JmhPlugin) .settings(commonSettings) .settings(noPublishSettings) + .jvmPlatform(jvmScalaVersions) lazy val commonSettings = Seq( scalacOptions --= { @@ -213,15 +240,25 @@ val setupJekyllSteps = Seq( ), ) +ThisBuild / githubWorkflowBuildMatrixAdditions += ("scalaPlatform", List("jvm")) + ThisBuild / githubWorkflowBuildPreamble ++= setupJekyllSteps ThisBuild / githubWorkflowPublishPreamble ++= setupJekyllSteps +ThisBuild / githubWorkflowScalaVersions := Seq("2_13", "3_0") + +ThisBuild / githubWorkflowBuildSbtStepPreamble := Seq.empty + +ThisBuild / githubWorkflowArtifactUpload := false + // Add makeMicrosite to the build step ThisBuild / githubWorkflowBuild ~= { steps => steps.map { case w: WorkflowStep.Sbt if w.commands == List("test") => - w.copy(commands = List("test", "makeMicrosite", "publishLocal")) + w.copy(commands = + List("test", "publishLocal").map(_ + "_${{ matrix.scala }}_${{ matrix.scalaPlatform }}") :+ "makeMicrosite", + ) case w => w } } diff --git a/project/Build.scala b/project/Build.scala new file mode 100644 index 0000000..0bd9dfa --- /dev/null +++ b/project/Build.scala @@ -0,0 +1,79 @@ +import sbt._ +import sbt.Keys._ +import com.jsuereth.sbtpgp.PgpKeys._ +import sbt.internal.LogManager +import sbt.internal.util.BufferedAppender +import java.io.PrintStream +import sbt.internal.ProjectMatrix +import sbtprojectmatrix.ProjectMatrixPlugin.autoImport.virtualAxes + +object Build { + + val Scala213 = "2.13.11" + val Scala3 = "3.3.0" + + // copied from: https://github.com/disneystreaming/smithy4s/blob/21a6fb04ab3485c0a4b40fe205a628c6f4750813/project/Smithy4sBuildPlugin.scala#L508 + def createBuildCommands(projects: Seq[ProjectReference]) = { + case class Doublet(scala: String, platform: String) + + val scala3Suffix = VirtualAxis.scalaABIVersion(Scala3).idSuffix + val scala213Suffix = VirtualAxis.scalaABIVersion(Scala213).idSuffix + val jsSuffix = VirtualAxis.js.idSuffix + val nativeSuffix = VirtualAxis.native.idSuffix + + val all: List[(Doublet, Seq[String])] = + projects + .collect { case lp: LocalProject => + var projectId = lp.project + + val scalaAxis = + if (projectId.endsWith(scala3Suffix)) { + projectId = projectId.dropRight(scala3Suffix.length) + "3_0" + } else "2_13" + + val platformAxis = + if (projectId.endsWith(jsSuffix)) { + projectId = projectId.dropRight(jsSuffix.length) + "js" + } else if (projectId.endsWith(nativeSuffix)) { + projectId = projectId.dropRight(nativeSuffix.length) + "native" + } else { + "jvm" + } + + Doublet(scalaAxis, platformAxis) -> lp.project + } + .groupBy(_._1) + .mapValues(_.map(_._2)) + .toList + + // some commands, like test and compile, are setup for all modules + val any = (t: Doublet) => true + // things like scalafix and scalafmt are only enabled on jvm 2.13 projects + val jvm2_13 = (t: Doublet) => t.scala == "2_13" && t.platform == "jvm" + + val jvm = (t: Doublet) => t.platform == "jvm" + + val desiredCommands: Map[String, (String, Doublet => Boolean)] = Map( + "test" -> ("test", any), + "compile" -> ("compile", any), + "publishLocal" -> ("publishLocal", any), + ) + + val cmds = all.flatMap { case (doublet, projects) => + desiredCommands.filter(_._2._2(doublet)).map { case (name, (cmd, _)) => + Command.command( + s"${name}_${doublet.scala}_${doublet.platform}", + ) { state => + projects.foldLeft(state) { case (st, proj) => + s"$proj/$cmd" :: st + } + } + } + } + + cmds + } +} diff --git a/project/plugins.sbt b/project/plugins.sbt index 72aa07a..f6ff925 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,5 +4,6 @@ addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.9.3") addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.5.7") addSbtPlugin("com.47deg" % "sbt-microsites" % "1.3.4") -addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.15.0") +addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.23.0") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.0") // override mdoc version from microsite +addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.9.1")