diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cc76eb8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,256 @@ +# 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: Continuous Integration + +on: + pull_request: + branches: ['**', '!update/**'] + push: + branches: ['**', '!update/**'] + 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: + build: + name: Build and Test + strategy: + matrix: + os: [ubuntu-latest] + scala: [2.12.15, 2.13.6, 3.0.2] + java: [temurin@8] + project: [rootJS, rootJVM, rootNative] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Download Java (temurin@8) + id: download-java-temurin-8 + if: matrix.java == 'temurin@8' + uses: typelevel/download-java@v1 + with: + distribution: temurin + java-version: 8 + + - name: Setup Java (temurin@8) + if: matrix.java == 'temurin@8' + uses: actions/setup-java@v2 + with: + distribution: jdkfile + java-version: 8 + jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + + - name: Cache sbt + uses: actions/cache@v2 + with: + path: | + ~/.sbt + ~/.ivy2/cache + ~/.coursier/cache/v1 + ~/.cache/coursier/v1 + ~/AppData/Local/Coursier/Cache/v1 + ~/Library/Caches/Coursier/v1 + key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + + - name: Check that workflows are up to date + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' 'project /' githubWorkflowCheck + + - name: Check headers and formatting + if: matrix.java == 'temurin@8' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' headerCheckAll scalafmtCheckAll 'project /' scalafmtSbtCheck + + - name: scalaJSLink + if: matrix.project == 'rootJS' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/scalaJSLinkerResult + + - name: nativeLink + if: matrix.project == 'rootNative' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/nativeLink + + - name: Test + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' test + + - name: Check binary compatibility + if: matrix.java == 'temurin@8' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' mimaReportBinaryIssues + + - name: Generate API documentation + if: matrix.java == 'temurin@8' + run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' doc + + - name: Make target directories + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') + run: mkdir -p target .js/target core/native/target core/js/target core/jvm/target .jvm/target .native/target project/target + + - name: Compress target directories + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') + run: tar cf targets.tar target .js/target core/native/target core/js/target core/jvm/target .jvm/target .native/target project/target + + - name: Upload target directories + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') + uses: actions/upload-artifact@v2 + with: + 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' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main') + strategy: + matrix: + os: [ubuntu-latest] + scala: [2.13.6] + java: [temurin@8] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Download Java (temurin@8) + id: download-java-temurin-8 + if: matrix.java == 'temurin@8' + uses: typelevel/download-java@v1 + with: + distribution: temurin + java-version: 8 + + - name: Setup Java (temurin@8) + if: matrix.java == 'temurin@8' + uses: actions/setup-java@v2 + with: + distribution: jdkfile + java-version: 8 + jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + + - name: Cache sbt + uses: actions/cache@v2 + with: + path: | + ~/.sbt + ~/.ivy2/cache + ~/.coursier/cache/v1 + ~/.cache/coursier/v1 + ~/AppData/Local/Coursier/Cache/v1 + ~/Library/Caches/Coursier/v1 + key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + + - name: Download target directories (2.12.15, rootJS) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.15-rootJS + + - name: Inflate target directories (2.12.15, rootJS) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.12.15, rootJVM) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.15-rootJVM + + - name: Inflate target directories (2.12.15, rootJVM) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.12.15, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.15-rootNative + + - name: Inflate target directories (2.12.15, rootNative) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.13.6, rootJS) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.6-rootJS + + - name: Inflate target directories (2.13.6, rootJS) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.13.6, rootJVM) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.6-rootJVM + + - name: Inflate target directories (2.13.6, rootJVM) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (2.13.6, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.6-rootNative + + - name: Inflate target directories (2.13.6, rootNative) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.0.2, rootJS) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.0.2-rootJS + + - name: Inflate target directories (3.0.2, rootJS) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.0.2, rootJVM) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.0.2-rootJVM + + - name: Inflate target directories (3.0.2, rootJVM) + run: | + tar xf targets.tar + rm targets.tar + + - name: Download target directories (3.0.2, rootNative) + uses: actions/download-artifact@v2 + with: + name: target-${{ matrix.os }}-${{ matrix.java }}-3.0.2-rootNative + + - name: Inflate target directories (3.0.2, rootNative) + run: | + tar xf targets.tar + rm targets.tar + + - 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 }}' tlRelease diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml new file mode 100644 index 0000000..547aaa4 --- /dev/null +++ b/.github/workflows/clean.yml @@ -0,0 +1,59 @@ +# 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 + 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=/tmp/tmp.$$ + + # 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/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 8837215..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: release -on: - push: - branches: [main] - tags: ["*"] -jobs: - publish: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK - uses: olafurpg/setup-scala@v10 - with: - java-version: adopt@1.11 - - uses: olafurpg/setup-gpg@v3 - - name: Publish - run: | - sbt clean ci-release - env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - PGP_SECRET: ${{ secrets.PGP_SECRET }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} diff --git a/.github/workflows/scala.yml b/.github/workflows/scala.yml deleted file mode 100644 index 081eee1..0000000 --- a/.github/workflows/scala.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: build - -on: [push, pull_request] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - uses: coursier/cache-action@v3 - - name: Set up JDK - uses: olafurpg/setup-scala@v10 - with: - java-version: adopt@1.11 - - name: Cache SBT ivy cache - uses: actions/cache@v1 - with: - path: ~/.ivy2/cache - key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('**/project/**') }}-${{ hashFiles('**/build.sbt') }} - - name: Cache SBT - uses: actions/cache@v1 - with: - path: ~/.sbt - key: ${{ runner.os }}-sbt-${{ hashFiles('**/project/**') }}-${{ hashFiles('**/build.sbt') }} - - name: Run compile - run: sbt scalafmtCheckAll +compile +test diff --git a/build.sbt b/build.sbt index a684d5c..999c899 100644 --- a/build.sbt +++ b/build.sbt @@ -1,5 +1,3 @@ -import sbtcrossproject.CrossPlugin.autoImport.crossProject - val mUnit = "0.7.29" val discipline = "1.1.5" @@ -7,15 +5,15 @@ Global / onChangedBuildSource := ReloadOnSourceChanges inThisBuild( List( - name := "discipline-munit", - organization := "org.typelevel", - scalaVersion := "2.13.6", - crossScalaVersions := Seq("2.12.15", "2.13.6", "3.0.2"), - homepage := Some(url("https://github.com/typelevel/discipline-munit")), - licenses += ("BSD 3-Clause", url( - "http://opensource.org/licenses/BSD-3-Clause" - )), - developers := List( + tlBaseVersion := "1.0", + scalaVersion := "2.13.6", + crossScalaVersions := Seq("2.12.15", "2.13.6", "3.0.2"), + tlVersionIntroduced := Map("3" -> "1.0.9"), + licenses := List( + "BSD-3-Clause" -> url("http://opensource.org/licenses/BSD-3-Clause") + ), + startYear := Some(2020), + developers := List( Developer( "rpiaggio", "Raúl Piaggio", @@ -26,45 +24,19 @@ inThisBuild( ) ) -lazy val root = project - .in(file(".")) - .aggregate(coreJVM, coreJS, coreNative) - .settings( - publish := {}, - publishLocal := {} - ) +lazy val root = tlCrossRootProject.aggregate(core) lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform) .in(file("core")) .settings( - moduleName := "discipline-munit", + name := "discipline-munit", libraryDependencies ++= Seq( "org.scalameta" %%% "munit" % mUnit, "org.scalameta" %%% "munit-scalacheck" % mUnit, "org.typelevel" %%% "discipline-core" % discipline - ), - scmInfo := Some( - ScmInfo( - url("https://github.com/typelevel/discipline-munit"), - "scm:git:git@github.com:typelevel/discipline-munit.git", - Some("scm:git:git@github.com:typelevel/discipline-munit.git") - ) - ), - pomIncludeRepository := { _ => false } - ) - .jsSettings( - scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.CommonJSModule) } + ) ) .nativeSettings( - crossScalaVersions := crossScalaVersions.value.filter(_.startsWith("2.")) + tlVersionIntroduced ++= List("2.12", "2.13").map(_ -> "1.0.5").toMap, + crossScalaVersions := (ThisBuild / crossScalaVersions).value.filter(_.startsWith("2.")) ) - -lazy val coreJVM = core.jvm - -lazy val coreJS = core.js - -lazy val coreNative = core.native - -sonatypeProfileName := "org.typelevel" - -root / packagedArtifacts := Map.empty diff --git a/core/shared/src/main/scala/munit/DisciplineSuite.scala b/core/shared/src/main/scala/munit/DisciplineSuite.scala index db5abfa..b928279 100644 --- a/core/shared/src/main/scala/munit/DisciplineSuite.scala +++ b/core/shared/src/main/scala/munit/DisciplineSuite.scala @@ -1,3 +1,33 @@ +/* + * Copyright (c) 2020, Typelevel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package munit import org.typelevel.discipline.Laws diff --git a/core/shared/src/test/scala/munit/DisciplineSuiteTest.scala b/core/shared/src/test/scala/munit/DisciplineSuiteTest.scala index 515846f..24d37ca 100644 --- a/core/shared/src/test/scala/munit/DisciplineSuiteTest.scala +++ b/core/shared/src/test/scala/munit/DisciplineSuiteTest.scala @@ -1,3 +1,33 @@ +/* + * Copyright (c) 2020, Typelevel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package munit class DisciplineSuiteTest extends DisciplineSuite { diff --git a/core/shared/src/test/scala/munit/laws.scala b/core/shared/src/test/scala/munit/laws.scala index c91a61a..d573625 100644 --- a/core/shared/src/test/scala/munit/laws.scala +++ b/core/shared/src/test/scala/munit/laws.scala @@ -1,3 +1,33 @@ +/* + * Copyright (c) 2020, Typelevel + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + package munit import org.scalacheck.Prop diff --git a/project/build.properties b/project/build.properties index 203e3dc..4ff6415 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.6.1 \ No newline at end of file +sbt.version=1.6.2 \ No newline at end of file diff --git a/project/plugins.sbt b/project/plugins.sbt index 3fdbf6c..da89a67 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,12 +2,6 @@ addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.8.0") addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.2") -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.1.0") +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") -addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.1.0") - -addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.10") - -addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") - -addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.20") +addSbtPlugin("org.typelevel" % "sbt-typelevel" % "0.4.11")