diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41bcb0e..d58c587 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,12 +9,17 @@ name: Continuous Integration on: pull_request: - branches: ['**'] + branches: ['**', '!update/**', '!pr/**'] push: - branches: ['**'] + branches: ['**', '!update/**', '!pr/**'] tags: [v*] env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_CREDENTIAL_HOST: ${{ secrets.SONATYPE_CREDENTIAL_HOST }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jobs: @@ -25,6 +30,7 @@ jobs: os: [ubuntu-latest] scala: [2.12.17, 2.13.10, 3.2.2] java: [temurin@8] + project: [rootJVM] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) @@ -63,35 +69,55 @@ jobs: - name: Check that workflows are up to date run: sbt githubWorkflowCheck - - name: Build project - run: sbt '++ ${{ matrix.scala }}' validate + - name: Check headers and formatting + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-latest' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck + + - name: Test + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' test + + - name: Check binary compatibility + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-latest' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' mimaReportBinaryIssues + + - name: Generate API documentation + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-latest' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc + + - name: Check README + if: matrix.scala != '3.2.2' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' readme/mdoc + + - name: Generate coverage report + if: matrix.scala != '3.2.2' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' coverage test coverageReport - name: Codecov uses: codecov/codecov-action@v3 - name: Make target directories - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) - run: mkdir -p target modules/cron4s/.jvm/target modules/readme/target modules/core/.jvm/target modules/calev/.jvm/target project/target + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') + run: mkdir -p target .js/target modules/cron4s/.jvm/target .jvm/target .native/target modules/readme/target modules/core/.jvm/target modules/calev/.jvm/target project/target - name: Compress target directories - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) - run: tar cf targets.tar target modules/cron4s/.jvm/target modules/readme/target modules/core/.jvm/target modules/calev/.jvm/target project/target + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') + run: tar cf targets.tar target .js/target modules/cron4s/.jvm/target .jvm/target .native/target modules/readme/target modules/core/.jvm/target modules/calev/.jvm/target project/target - name: Upload target directories - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') uses: actions/upload-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }} + name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }}-${{ matrix.project }} path: targets.tar publish: name: Publish Artifacts needs: [build] - if: github.event_name != 'pull_request' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v')) + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') strategy: matrix: os: [ubuntu-latest] - scala: [2.12.17] + scala: [2.13.10] java: [temurin@8] runs-on: ${{ matrix.os }} steps: @@ -128,40 +154,46 @@ jobs: ~/Library/Caches/Coursier/v1 key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - name: Download target directories (2.12.17) + - name: Download target directories (2.12.17, rootJVM) uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17 + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootJVM - - name: Inflate target directories (2.12.17) + - name: Inflate target directories (2.12.17, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.10) + - name: Download target directories (2.13.10, rootJVM) uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10 + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootJVM - - name: Inflate target directories (2.13.10) + - name: Inflate target directories (2.13.10, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.2) + - name: Download target directories (3.2.2, rootJVM) uses: actions/download-artifact@v3 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.2 + name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.2-rootJVM - - name: Inflate target directories (3.2.2) + - name: Inflate target directories (3.2.2, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Publish JARs - env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - PGP_SECRET: ${{ secrets.PGP_SECRET }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} - run: sbt ci-release + - name: Import signing key + if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == '' + run: echo $PGP_SECRET | base64 -di | gpg --import + + - name: Import signing key and strip passphrase + if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE != '' + run: | + echo "$PGP_SECRET" | base64 -di > /tmp/signing-key.gpg + echo "$PGP_PASSPHRASE" | gpg --pinentry-mode loopback --passphrase-fd 0 --import /tmp/signing-key.gpg + (echo "$PGP_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1) + + - name: Publish + run: sbt '++ ${{ matrix.scala }}' tlCiRelease diff --git a/.mergify.yml b/.mergify.yml index 2225314..edebdb2 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -17,9 +17,9 @@ pull_request_rules: - name: merge scala-steward's PRs conditions: - author=scala-steward - - status-success=Build and Test (ubuntu-latest, 2.12.17, temurin@8) - - status-success=Build and Test (ubuntu-latest, 2.13.10, temurin@8) - - status-success=Build and Test (ubuntu-latest, 3.2.2, temurin@8) + - status-success=Build and Test (ubuntu-latest, 2.12.17, temurin@8, rootJVM) + - status-success=Build and Test (ubuntu-latest, 2.13.10, temurin@8, rootJVM) + - status-success=Build and Test (ubuntu-latest, 3.2.2, temurin@8, rootJVM) actions: merge: method: squash diff --git a/build.sbt b/build.sbt index 983cdf7..8468fae 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,3 @@ -import com.github.sbt.git.SbtGit.GitKeys import sbtcrossproject.{CrossProject, CrossType, Platform} import org.typelevel.sbt.gha.JavaSpec.Distribution.Temurin @@ -19,31 +18,35 @@ val moduleCrossPlatformMatrix: Map[String, List[Platform]] = Map( "calev" -> List(JVMPlatform) ) -/// sbt-github-actions configuration -ThisBuild / crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3) -ThisBuild / githubWorkflowTargetTags ++= Seq("v*") -ThisBuild / githubWorkflowPublishTargetBranches := Seq( - RefPredicate.Equals(Ref.Branch("master")), - RefPredicate.StartsWith(Ref.Tag("v")) +/// global settings + +ThisBuild / organization := groupId +ThisBuild / tlBaseVersion := "0.8" +ThisBuild / startYear := Some(2018) +ThisBuild / licenses := Seq(License.Apache2) +ThisBuild / developers := List( + tlGitHubDev("fthomas", "Frank S. Thomas") ) -ThisBuild / githubWorkflowPublish := Seq( - WorkflowStep.Run( - List("sbt ci-release"), - name = Some("Publish JARs"), - env = Map( - "PGP_PASSPHRASE" -> "${{ secrets.PGP_PASSPHRASE }}", - "PGP_SECRET" -> "${{ secrets.PGP_SECRET }}", - "SONATYPE_PASSWORD" -> "${{ secrets.SONATYPE_PASSWORD }}", - "SONATYPE_USERNAME" -> "${{ secrets.SONATYPE_USERNAME }}" - ) +ThisBuild / tlSkipIrrelevantScalas := true +ThisBuild / scalaVersion := Scala_2_13 +ThisBuild / crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3) +ThisBuild / tlCiReleaseBranches := Seq("master") +ThisBuild / githubWorkflowBuild ++= Seq( + WorkflowStep.Sbt( + commands = List("readme/mdoc"), + name = Some("Check README"), + cond = Some(s"matrix.scala != '$Scala_3'") + ), + WorkflowStep.Sbt( + commands = List("coverage", "test", "coverageReport"), + name = Some("Generate coverage report"), + cond = Some(s"matrix.scala != '$Scala_3'") + ), + WorkflowStep.Use( + ref = UseRef.Public("codecov", "codecov-action", "v3"), + name = Some("Codecov") ) ) -ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec(Temurin, "8")) -ThisBuild / githubWorkflowBuild := - Seq( - WorkflowStep.Sbt(List("validate"), name = Some("Build project")), - WorkflowStep.Use(UseRef.Public("codecov", "codecov-action", "v3"), name = Some("Codecov")) - ) ThisBuild / mergifyPrRules := { val authorCondition = MergifyCondition.Custom("author=scala-steward") Seq( @@ -60,27 +63,13 @@ ThisBuild / mergifyPrRules := { ) } -/// global settings - -ThisBuild / versionScheme := Some("early-semver") - /// projects -lazy val root = project - .in(file(".")) - .aggregate(coreJVM) - .aggregate(cron4sJVM) - .aggregate(calevJVM) - .aggregate(readme) - .settings(commonSettings) - .settings(noPublishSettings) - .settings( - crossScalaVersions := Nil - ) +lazy val root = tlCrossRootProject + .aggregate(calev, core, cron4s, readme) lazy val core = myCrossProject("core") .settings( - crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3), libraryDependencies ++= Seq( Dependencies.fs2Core ) @@ -91,15 +80,12 @@ lazy val coreJVM = core.jvm lazy val cron4s = myCrossProject("cron4s") .dependsOn(core) .settings( - crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3), + crossScalaVersions := List(Scala_2_12, Scala_2_13), libraryDependencies ++= Seq( - Dependencies.cron4s - .cross(CrossVersion.for3Use2_13) - .excludeAll(ExclusionRule("org.typelevel")), + Dependencies.cron4s, Dependencies.fs2Core, Dependencies.scalaTest % Test ), - publish / skip := scalaBinaryVersion.value == "3", initialCommands := s""" import $rootPkg._ import cats.effect.unsafe.implicits.global @@ -115,7 +101,6 @@ lazy val cron4sJVM = cron4s.jvm lazy val calev = myCrossProject("calev") .dependsOn(core) .settings( - crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3), libraryDependencies ++= Seq( Dependencies.calevCore, Dependencies.scalaTest % Test @@ -132,26 +117,19 @@ lazy val calev = myCrossProject("calev") ) lazy val calevJVM = calev.jvm -val runMdoc2 = taskKey[Unit]("Run mdoc only for scala 2.x") + lazy val readme = project .in(file("modules/readme")) - .enablePlugins(MdocPlugin) - .dependsOn(cron4sJVM, calevJVM) + .enablePlugins(MdocPlugin, NoPublishPlugin) + .dependsOn(calevJVM, cron4sJVM) .settings(commonSettings) - .settings(noPublishSettings) .settings( crossScalaVersions := List(Scala_2_12, Scala_2_13), - runMdoc2 := Def.taskDyn { - val t = mdoc.inputTaskValue - if ((coreJVM / scalaBinaryVersion).value == "3") - Def.task(streams.value.log("readme").info("Skip readme generation")) - else Def.inputTask(t.evaluated).toTask("") - }.value, scalacOptions -= "-Xfatal-warnings", mdocIn := baseDirectory.value / "README.md", mdocOut := (LocalRootProject / baseDirectory).value / "README.md", mdocVariables := Map( - "VERSION" -> latestVersion.value + "VERSION" -> tlLatestVersion.value.get ) ) @@ -167,47 +145,16 @@ def myCrossProject(name: String): CrossProject = lazy val commonSettings = Def.settings( compileSettings, - metadataSettings, - scaladocSettings + metadataSettings ) lazy val compileSettings = Def.settings( - scalaVersion := Scala_2_13 + scalaVersion := Scala_2_13, + crossScalaVersions := List(Scala_2_12, Scala_2_13, Scala_3) ) lazy val metadataSettings = Def.settings( - name := projectName, - organization := groupId, - homepage := Some(url(s"https://github.com/$gitHubOwner/$projectName")), - startYear := Some(2018), - licenses := List("Apache-2.0" -> url("http://www.apache.org/licenses/LICENSE-2.0")), - headerLicense := Some(HeaderLicense.ALv2("2018-2021", s"$projectName contributors")), - developers := List( - Developer( - id = "fthomas", - name = "Frank S. Thomas", - email = "", - url("https://github.com/fthomas") - ) - ) -) - -lazy val noPublishSettings = Def.settings( - publish / skip := true -) - -lazy val scaladocSettings = Def.settings( - Compile / doc / scalacOptions ++= { - val tree = - if (isSnapshot.value) GitKeys.gitHeadCommit.value - else GitKeys.gitDescribedVersion.value.map("v" + _) - Seq( - "-doc-source-url", - s"${scmInfo.value.get.browseUrl}/blob/${tree.get}€{FILE_PATH}.scala", - "-sourcepath", - (LocalRootProject / baseDirectory).value.getAbsolutePath - ) - } + headerLicense := Some(HeaderLicense.ALv2("2018-2021", s"$projectName contributors")) ) /// commands @@ -215,27 +162,10 @@ lazy val scaladocSettings = Def.settings( def addCommandsAlias(name: String, cmds: Seq[String]) = addCommandAlias(name, cmds.mkString(";", ";", "")) -addCommandsAlias( - "validate", - Seq( - "clean", - "headerCheck", - "scalafmtCheckAll", - "scalafmtSbtCheck", - "coverage", - "test", - "coverageReport", - "readme/runMdoc2", - "doc", - "package", - "packageSrc" - ) -) - addCommandsAlias( "fmt", Seq( - "headerCreate", + "headerCreateAll", "scalafmtAll", "scalafmtSbt" ) diff --git a/latestVersion.sbt b/latestVersion.sbt deleted file mode 100644 index 17cdbba..0000000 --- a/latestVersion.sbt +++ /dev/null @@ -1 +0,0 @@ -ThisBuild / latestVersion := "0.8.0" diff --git a/modules/calev/src/test/scala/eu/timepit/fs2cron/calev/CalevSchedulerTest.scala b/modules/calev/src/test/scala/eu/timepit/fs2cron/calev/CalevSchedulerTest.scala index 30d7dd3..f44c572 100644 --- a/modules/calev/src/test/scala/eu/timepit/fs2cron/calev/CalevSchedulerTest.scala +++ b/modules/calev/src/test/scala/eu/timepit/fs2cron/calev/CalevSchedulerTest.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018-2021 fs2-cron contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package eu.timepit.fs2cron.calev import cats.effect.IO diff --git a/modules/cron4s/src/test/scala-2/eu/timepit/fs2cron/cron4s/Cron4sSchedulerTest.scala b/modules/cron4s/src/test/scala-2/eu/timepit/fs2cron/cron4s/Cron4sSchedulerTest.scala index d49a75f..26b7625 100644 --- a/modules/cron4s/src/test/scala-2/eu/timepit/fs2cron/cron4s/Cron4sSchedulerTest.scala +++ b/modules/cron4s/src/test/scala-2/eu/timepit/fs2cron/cron4s/Cron4sSchedulerTest.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018-2021 fs2-cron contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package eu.timepit.fs2cron.cron4s import cats.effect.IO diff --git a/project/LatestVersion.scala b/project/LatestVersion.scala deleted file mode 100644 index 797c33e..0000000 --- a/project/LatestVersion.scala +++ /dev/null @@ -1,8 +0,0 @@ -import sbt._ - -object LatestVersion extends AutoPlugin { - object autoImport { - lazy val latestVersion: SettingKey[String] = - settingKey[String]("latest released version") - } -} diff --git a/project/plugins.sbt b/project/plugins.sbt index 8f8b1ff..4f44ad9 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,17 +1,11 @@ -addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.11") - -addSbtPlugin("de.heikoseeberger" % "sbt-header" % "5.9.0") - -addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.4.2") - addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.0") addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7") -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.0") - addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.7") +addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.4.19") + addSbtPlugin("org.typelevel" % "sbt-typelevel-mergify" % "0.4.19") diff --git a/scripts/release.sh b/scripts/release.sh index 4df9387..c61cc92 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -5,13 +5,9 @@ if [ -z "$VERSION" ]; then exit 1 fi -cat << EOF > latestVersion.sbt -ThisBuild / latestVersion := "$VERSION" -EOF - +git tag -a -s v$VERSION -m "Releasing $VERSION" sbt readme/mdoc - git commit -a -m "Setting version to $VERSION" -git tag -a -s v$VERSION -m "Releasing $VERSION" + git push git push --tags