diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 6ee616a..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: andxor -on: - push: - branches: - - master - pull_request: - branches: - - master -jobs: - test: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - scala: [2.13.12, 3.3.1] - java: [8, 11, 17, 21] - steps: - - uses: actions/checkout@v2 - - name: Setup Java ${{ matrix.java }} - uses: actions/setup-java@v2 - with: - distribution: temurin - java-version: ${{ matrix.java }} - - - name: Cache sbt - uses: actions/cache@v2 - with: - path: | - ~/.sbt - ~/.ivy2/cache - ~/.coursier/cache/v1 - ~/.cache/coursier/v1 - key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: sbt test - run: | - scalaV="${{ matrix.scala }}" - cd "scala-${scalaV%%.*}" - sbt "++$scalaV" test diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml new file mode 100644 index 0000000..bfc865d --- /dev/null +++ b/.github/workflows/clean.yml @@ -0,0 +1,60 @@ +# This file was automatically generated by sbt-github-actions using the +# githubWorkflowGenerate task. You should add and commit this file to +# your git repository. It goes without saying that you shouldn't edit +# this file by hand! Instead, if you wish to make changes, you should +# change your sbt build configuration to revise the workflow description +# to meet your needs, then regenerate this file. + +name: Clean + +on: push + +jobs: + delete-artifacts: + name: Delete Artifacts + runs-on: ubuntu-latest + env: + 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 }} + + # A shortcut to call GitHub API. + ghapi() { curl --silent --location --user _:$GITHUB_TOKEN "$@"; } + + # A temporary file which receives HTTP response headers. + TMPFILE=$(mktemp) + + # An associative array, key: artifact name, value: number of artifacts of that name. + declare -A ARTCOUNT + + # Process all artifacts on this repository, loop on returned "pages". + URL=$REPO/actions/artifacts + while [[ -n "$URL" ]]; do + + # Get current page, get response headers in a temporary file. + JSON=$(ghapi --dump-header $TMPFILE "$URL") + + # Get URL of next page. Will be empty if we are at the last page. + URL=$(grep '^Link:' "$TMPFILE" | tr ',' '\n' | grep 'rel="next"' | head -1 | sed -e 's/.*.*//') + rm -f $TMPFILE + + # Number of artifacts on this page: + COUNT=$(( $(jq <<<$JSON -r '.artifacts | length') )) + + # Loop on all artifacts on this page. + for ((i=0; $i < $COUNT; i++)); do + + # Get name of artifact and count instances of this name. + name=$(jq <<<$JSON -r ".artifacts[$i].name?") + ARTCOUNT[$name]=$(( $(( ${ARTCOUNT[$name]} )) + 1)) + + id=$(jq <<<$JSON -r ".artifacts[$i].id?") + size=$(( $(jq <<<$JSON -r ".artifacts[$i].size_in_bytes?") )) + printf "Deleting '%s' #%d, %'d bytes\n" $name ${ARTCOUNT[$name]} $size + ghapi -X DELETE $REPO/actions/artifacts/$id + done + done diff --git a/.github/workflows/scala-2-ci.yml b/.github/workflows/scala-2-ci.yml new file mode 100644 index 0000000..f8bed77 --- /dev/null +++ b/.github/workflows/scala-2-ci.yml @@ -0,0 +1,79 @@ +# This file was automatically generated by sbt-github-actions using the +# githubWorkflowGenerate task. You should add and commit this file to +# your git repository. It goes without saying that you shouldn't edit +# this file by hand! Instead, if you wish to make changes, you should +# change your sbt build configuration to revise the workflow description +# to meet your needs, then regenerate this file. + +name: Scala 2 Continuous Integration + +on: + pull_request: + branches: [master] + push: + branches: [master] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + build: + name: Build and Test + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + scala: [2.13.13] + java: [temurin@8, temurin@11, temurin@17, temurin@21] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Java (temurin@8) + if: matrix.java == 'temurin@8' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 8 + cache: sbt + + - name: Setup Java (temurin@11) + if: matrix.java == 'temurin@11' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 11 + cache: sbt + + - name: Setup Java (temurin@17) + if: matrix.java == 'temurin@17' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + + - name: Setup Java (temurin@21) + if: matrix.java == 'temurin@21' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: sbt + + - name: Check that workflows are up to date + run: cd scala-2 && sbt '++ ${{ matrix.scala }}' githubWorkflowCheck + + - name: Build project + run: cd scala-2 && sbt '++ ${{ matrix.scala }}' test + + - name: Check binary compatibility + if: matrix.java == 'temurin@8' + run: cd scala-2 && sbt '++ ${{ matrix.scala }}' mimaReportBinaryIssues + + - name: Build docs + if: matrix.java == 'temurin@8' + run: cd scala-2 && sbt '++ ${{ matrix.scala }}' docs/mdoc diff --git a/.github/workflows/scala-3-ci.yml b/.github/workflows/scala-3-ci.yml new file mode 100644 index 0000000..8768e71 --- /dev/null +++ b/.github/workflows/scala-3-ci.yml @@ -0,0 +1,79 @@ +# This file was automatically generated by sbt-github-actions using the +# githubWorkflowGenerate task. You should add and commit this file to +# your git repository. It goes without saying that you shouldn't edit +# this file by hand! Instead, if you wish to make changes, you should +# change your sbt build configuration to revise the workflow description +# to meet your needs, then regenerate this file. + +name: Scala 3 Continuous Integration + +on: + pull_request: + branches: [master] + push: + branches: [master] + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + build: + name: Build and Test + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + scala: [3.3.3] + java: [temurin@8, temurin@11, temurin@17, temurin@21] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Java (temurin@8) + if: matrix.java == 'temurin@8' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 8 + cache: sbt + + - name: Setup Java (temurin@11) + if: matrix.java == 'temurin@11' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 11 + cache: sbt + + - name: Setup Java (temurin@17) + if: matrix.java == 'temurin@17' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + + - name: Setup Java (temurin@21) + if: matrix.java == 'temurin@21' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: sbt + + - name: Check that workflows are up to date + run: cd scala-3 && sbt '++ ${{ matrix.scala }}' githubWorkflowCheck + + - name: Build project + run: cd scala-3 && sbt '++ ${{ matrix.scala }}' test + + - name: Check binary compatibility + if: matrix.java == 'temurin@8' + run: cd scala-3 && sbt '++ ${{ matrix.scala }}' mimaReportBinaryIssues + + - name: Build docs + if: matrix.java == 'temurin@8' + run: cd scala-3 && sbt '++ ${{ matrix.scala }}' docs/mdoc diff --git a/CommonBuild.scala b/CommonBuild.scala index c76f5b0..ca0b13f 100644 --- a/CommonBuild.scala +++ b/CommonBuild.scala @@ -1,11 +1,16 @@ import com.typesafe.tools.mima.plugin.MimaKeys.mimaPreviousArtifacts import sbt.* import sbt.Keys.* +import sbtghactions.{JavaSpec, WorkflowStep} +import sbtghactions.GenerativeKeys.* import sbtgitpublish.GitPublishKeys.* package object andxor { val currentVersion = "0.14.0" + val scala2 = "2.13.13" + val scala3 = "3.3.3" + val catsVersion = "2.10.0" val catsCore = "org.typelevel" %% "cats-core" % catsVersion val catsLaws = "org.typelevel" %% "cats-laws" % catsVersion % "test" @@ -21,7 +26,11 @@ package object andxor { val scalariform = ("org.scalariform" %% "scalariform" % "0.2.10").cross(CrossVersion.for3Use2_13) + val javaVersions = Seq(8, 11, 17, 21).map(v => JavaSpec.temurin(v.toString)) + val isJava8 = s"matrix.java == '${javaVersions.find(_.version == "8").get.render}'" + trait CommonBuild { + val relDir: String val baseSettings0: Seq[Setting[_]] final lazy val baseSettings = Seq( @@ -51,6 +60,20 @@ package object andxor { mimaPreviousArtifacts := Set("andxor" %% name.value % "0.14.0"), ) + final lazy val githubActionsSettings = Seq( + ThisBuild / githubWorkflowScalaVersions := Some(crossScalaVersions.value).filter(_.nonEmpty).getOrElse(Seq(scalaVersion.value)), + ThisBuild / githubWorkflowJavaVersions := javaVersions, + ThisBuild / githubWorkflowArtifactUpload := false, + ThisBuild / githubWorkflowBuildMatrixFailFast := Some(false), + ThisBuild / githubWorkflowTargetBranches := Seq("master"), + ThisBuild / githubWorkflowPublishTargetBranches := Seq(), + ThisBuild / githubWorkflowSbtCommand := s"cd $relDir && sbt", + ThisBuild / githubWorkflowBuild ++= Seq( + WorkflowStep.Sbt(List("mimaReportBinaryIssues"), name = Some("Check binary compatibility"), cond = Some(isJava8)), + WorkflowStep.Sbt(List("docs/mdoc"), name = Some("Build docs"), cond = Some(isJava8)), + ), + ) + final lazy val testSettings = Seq(libraryDependencies += scalacheck % "test") def generateBase = Project("generate", file("generate")) diff --git a/both.sh b/both.sh index 9de1d60..ead2afb 100755 --- a/both.sh +++ b/both.sh @@ -51,4 +51,21 @@ function mimaReport() { sbtSequential mimaReportBinaryIssues } + + +function githubWorkflowGenerate() { + sbtParallel githubWorkflowGenerate + + ghdir='.github/workflows' + + mv "scala-2/$ghdir/clean.yml" "$ghdir/clean.yml" + rm "scala-3/$ghdir/clean.yml" + + cat "scala-2/$ghdir/ci.yml" | sed -E 's/^(name:)\s*(Continuous Integration)$/\1 Scala 2 \2/' > "$ghdir/scala-2-ci.yml" + rm "scala-2/$ghdir/ci.yml" + + cat "scala-3/$ghdir/ci.yml" | sed -E 's/^(name:)\s*(Continuous Integration)$/\1 Scala 3 \2/' > "$ghdir/scala-3-ci.yml" + rm "scala-3/$ghdir/ci.yml" +} + $operation diff --git a/common-plugins.sbt b/common-plugins.sbt index 062e40b..7bbf4de 100644 --- a/common-plugins.sbt +++ b/common-plugins.sbt @@ -1,3 +1,4 @@ +addSbtPlugin("com.github.sbt" % "sbt-github-actions" % "0.23.0") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.3") addSbtPlugin("org.typelevel" % "sbt-tpolecat" % "0.5.0") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.5.2") diff --git a/scala-2/build.sbt b/scala-2/build.sbt index d0eefff..05f5ba2 100644 --- a/scala-2/build.sbt +++ b/scala-2/build.sbt @@ -2,6 +2,8 @@ import andxor.Build._ Global / onChangedBuildSource := ReloadOnSourceChanges +githubActionsSettings + lazy val generate: Project = generateBase lazy val core: Project = coreBase @@ -18,11 +20,8 @@ lazy val tests: Project = testsBase .dependsOn(core, scalacheck, argonaut, circe) lazy val root: Project = project.in(file(".")) - .settings(commonSettings) - .settings( - crossScalaVersions := Seq(), - gitRelease := {} - ) + .settings(baseSettings) + .settings(gitRelease := {}) .aggregate(generate, core, argonaut, circe, scalacheck, tests) lazy val docs = project.in(file("andxor-docs")) diff --git a/scala-2/project/Build.scala b/scala-2/project/Build.scala index 1ae9f63..f9ff588 100644 --- a/scala-2/project/Build.scala +++ b/scala-2/project/Build.scala @@ -8,7 +8,8 @@ import sbt.Keys._ import sbtgitpublish.GitPublishKeys._ object Build extends CommonBuild { - val scalaVersions = Seq("2.13.13") + val relDir = "scala-2" + val scalaVersions = Seq(scala2) def scalaVersionSpecificFolders(srcName: String, srcBaseDir: java.io.File, scalaVersion: String): Seq[java.io.File] = CrossVersion.partialVersion(scalaVersion) match { diff --git a/scala-3/build.sbt b/scala-3/build.sbt index b3c3721..681b3cd 100644 --- a/scala-3/build.sbt +++ b/scala-3/build.sbt @@ -2,6 +2,8 @@ import andxor.Build._ Global / onChangedBuildSource := ReloadOnSourceChanges +githubActionsSettings + lazy val generate: Project = generateBase .settings( buildInfoKeys := Seq[BuildInfoKey]("rootDir" -> (ThisBuild / baseDirectory).value.toString), @@ -17,11 +19,8 @@ lazy val tests: Project = testsBase .dependsOn(core, scalacheck) lazy val root: Project = project.in(file(".")) - .settings(commonSettings) - .settings( - crossScalaVersions := Seq(), - gitRelease := {} - ) + .settings(baseSettings) + .settings(gitRelease := {}) .aggregate(core, scalacheck, tests) lazy val docs = project.in(file("andxor-docs")) diff --git a/scala-3/project/Build.scala b/scala-3/project/Build.scala index 98308d2..a6de048 100644 --- a/scala-3/project/Build.scala +++ b/scala-3/project/Build.scala @@ -6,7 +6,8 @@ import sbt.Keys.* import sbtgitpublish.GitPublishKeys.* object Build extends CommonBuild { - val scalaVersions = Seq("3.3.3") + val relDir = "scala-3" + val scalaVersions = Seq(scala3) val lintOpts = Seq( "-Wunused:unsafe-warn-patvars",