From df467d95bdb6f2d81c1b8ed92267c14890c1f073 Mon Sep 17 00:00:00 2001 From: Viktor Podzigun Date: Mon, 31 Jan 2022 11:52:00 +0100 Subject: [PATCH] Added GitHub CI action (#9) --- .github/workflows/ci.yml | 97 ++++++++++++++++++ .travis.yml | 44 -------- README.md | 2 +- pgp.sbt | 9 +- project/plugins.sbt | 4 +- project/src/main/scala/common/Libs.scala | 2 +- .../scala/definitions/ScalaJsModule.scala | 7 +- travis/secrets.tar.enc | Bin 5136 -> 0 bytes 8 files changed, 108 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml delete mode 100644 travis/secrets.tar.enc diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ee2ed46 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,97 @@ +name: CI + +on: + push: + branches: [ master ] + tags: + - '*' + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + + - name: Git checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: '12' + + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + java-version: '8' + distribution: 'adopt' + + - 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', 'project/**/*.scala') }} + + - name: Cache node_modules + uses: actions/cache@v2 + with: + path: | + ~/.npm + ~/.nvm + ~/work/scommons-react/scommons-react/core/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/core/target/scala-2.13/scalajs-bundler/test/package-lock.json + ~/work/scommons-react/scommons-react/dom/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/dom/target/scala-2.13/scalajs-bundler/test/package-lock.json + ~/work/scommons-react/scommons-react/redux/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/redux/target/scala-2.13/scalajs-bundler/test/package-lock.json + ~/work/scommons-react/scommons-react/showcase/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/showcase/target/scala-2.13/scalajs-bundler/test/package-lock.json + ~/work/scommons-react/scommons-react/test/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/test/target/scala-2.13/scalajs-bundler/test/package-lock.json + ~/work/scommons-react/scommons-react/test-dom/target/scala-2.13/scalajs-bundler/test/node_modules + ~/work/scommons-react/scommons-react/test-dom/target/scala-2.13/scalajs-bundler/test/package-lock.json + key: ${{ runner.os }}-node_modules-cache-v2-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node_modules-cache-v2- + + - name: Extract Tag Name + run: echo "TAG_NAME=$(echo ${GITHUB_REF##*/})" >> $GITHUB_ENV + if: ${{ startsWith(github.ref, 'refs/tags') }} + + - name: Run tests + run: | + sbt coverage test + sbt coverageAggregate coveralls + if: ${{ env.TAG_NAME == '' }} + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} + + - name: Publish SNAPSHOT + run: sbt clean publish + if: ${{ !github.event.pull_request && env.TAG_NAME == '' }} + env: + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + + - name: Publish RELEASE + run: | + mkdir ./keys + echo $PGP_PUBLIC | base64 --decode > ./keys/pubring.gpg + echo $PGP_SECRET | base64 --decode > ./keys/secring.gpg + VERSION="$(echo "$TAG_NAME" | cut -d'v' -f 2)" + echo "Publish a release version=$VERSION for tag $TAG_NAME" + version=$VERSION sbt clean publishSigned sonatypeBundleRelease + if: ${{ env.TAG_NAME != '' }} + env: + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + PGP_PUBLIC: ${{ secrets.PGP_PUBLIC }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASS: ${{ secrets.PGP_PASS }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b892fd1..0000000 --- a/.travis.yml +++ /dev/null @@ -1,44 +0,0 @@ -language: scala -sudo: false -jdk: -- oraclejdk8 -dist: trusty -env: - global: - - TRAVIS_SBT_VERSION="1.2.8" - - secure: Px1jYCcHrx4Eufto0lOK8QOciiZ72baECbZWYEtz9CZfjpmuFIovfSShNrni2rYCTmxdZmpl2Royq+BhbO7IbVKXXGP3Spq0cxPfVa1VQ+s9GRjbxY7QyXUbXq2Xcs/2xiieBXLihrZwIeRKGW3SXmwiZvypYyPknugezPgx2I0ULIZOJGD3LC2WAKfdY/a5Ok6ErxQj35U01ONif6ey2B97+s3w8D/P1Qw1f2p5dpU5QCr4iXfKQgC4Cje1/A4s+Qk2BIiQbUEmBRLeTWLsAcx501BCmMoFc+t64behU6wDflvcHdDk9pWUfii0ub4PM3QNYPydTBzadlr29rkrZOL/JtXpemcRh6q0aJLcLofmJd4ess7NIzAu7/oPVWe9sv1H989GKtuqDWrZo1fTcGPYT5nmjvssrYCVPl5HCJG/jtyN4EHtNnzpl51OA4p6K3itTqdSm1JwoLdz6ReGsQi30hdloxHTyOmJDYY5AvTz8utIdAnKr8EjSM5xFbN7bApWISDAeRNrk63hCUhJvCrmBWI04PLZrT+lRylhXTieDit09jZOpfbFRHUZCw2eFp7ddhUNZArnOZOn7phphgxqIXnaRpWYDgGaCqJo4d79URJGowssRh5Vs+ozOkSvZfUlE/crQDLwaXnVt25V6EZWrOOMHUSW/kLiWCg8Vqc= - - secure: a8GtpUc81dCfS2D/VKbNKxz3nztcnHyPatS8QHUr2nG2hTMZbL/7O4714EtI1QlBb7Ke64tAhAASaszJqDlWkI9xuMo6G+9U2Ui/FMG/XMe3CiBPoU56jx7bSOP7SG02wsE39hF/pqjuMDTNDSBz9+vSuyB1GnwLP15bej49ityWet/6yDAZac9atwNbLRfeuIfpQa8lfETi9vUw4o8f83gqqg4uG+k0QCTRzGMlMKMXTt9zmTQJQUVwyZrgnGweHCsO9WCpIkkSOwpzphd/6IBfob+RcCnqDPMwfAZEAWVNFs3OLznSUvQdBbyGHKlXktrK2o6johdhq6X+bmezMcxZo9di4PLYcGZiFzW0iMZKv04CVJv8Q5gUScRhH0m6IaqB93p9XPX+EV8WtXNNlSoRuAWlw6x+oyreQ7dYQY1/c5A/WXzxJFDjrITRV4y68zT8zqoTUNpDlpTtK76qXVZgWEb4ErAb0iCsVUegVgzZyodMDviNW4F7w8GvNXKUqbUV4swT0/DP2C0zJglh7U5Pxbnp8UHUNvnvf8HwrlHRUGkRfZRQ+oaFIS3XJk0kCwpETIOwnUeIKVfxVM9F3eZTzKCYCdinYKS0OsWTbtxs98kFl2gBw/Sm572bQEL3LaJTc0k/u7ZpB+bQEK7sEvk6vIr3+M/Yw2YkK/hlwtQ= - - secure: X0pCqLOeXtdnwroruTgx+g89a6C1BvH6YVnlEyLVcPqSSo9pOo145CrwI1O5JX+Sej3t7J+psL6WEW0AmzRlk0MgxUIdhTkIpj7p2cRvyMVtSjI5qTDmnpCec48UbrwFSZ90BfvJddCVeZcB+aDWga7Fe1LzyN1eLc42hmFHq0p1WAfZUisHI0YKb3RzOiBKx+SzlLDN2BW3gl1OFRQl7ZFX6ORbgZhhcmOSEf74VHI3JiWLfDaPOI1KspeR+e1yQ7hSvA7V94rIz2xugv9xRgGyBLg1k9moMPR8VrBj717yn+tfXUxLOOIQUW1GLDhtlt5y/n3+yceQ6zzi9w9Keplx0wmQ29Soi5UfuYvRrSjifmzAkKl+RYZ6coJmvzcGKYatwID022dbDaPM28JQIBKmvT+Hy8j/3eyPaXHDHpThrneDawIXbdQbiT7uH62HM+wWJwb+tQrEdRMwJwlisxNBh1axefqFYV4cSsabtuT41F+oAfZKWObferSD9evlx8zABSKDCQsZfM3/+PUIo2w6WWxlviOOyzbrXIH6Ll65X3CHznh26HtdCwyTjYB3Llqez8qhV0zukIrKcNcAJVzeoiRZIjAS3KHjt8CokE2wetpvhTqbsym0zTI/zXaMZS58ioahrkR6pb+Fa7Pu9wjwhVU1+McZDcf/o9Gn7h0= -before_install: -- nvm install 12 && - nvm use 12 -- node --version && - npm --version -- if [ $TRAVIS_PULL_REQUEST = 'false' ]; then - openssl aes-256-cbc -K $encrypted_e5d9f4dea210_key -iv $encrypted_e5d9f4dea210_iv -in travis/secrets.tar.enc -out travis/secrets.tar -d; - tar xv -C travis -f travis/secrets.tar; - fi -script: -- sbt clean coverage test && - sbt coverageAggregate coveralls && - if [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" -o "$TRAVIS_BRANCH" == "$TRAVIS_TAG" ]; then - if [ -z "$TRAVIS_TAG" ]; then - echo "Publish a snapshot"; - sbt clean publish; - else - echo "Publish a release version=$TRAVIS_TAG"; - version=$TRAVIS_TAG sbt clean publishSigned sonatypeBundleRelease; - fi - else - echo "This is not a master branch commit. Skipping the publish/release step"; - fi -cache: - directories: - - ~/.npm - - ~/.nvm - - "$HOME/.ivy2/cache" - - "$HOME/.sbt" -before_cache: -# Cleanup the cached directories to avoid unnecessary cache updates -- find $HOME/.ivy2/cache -name "ivydata-*.properties" -print -delete -- find $HOME/.sbt -name "*.lock" -print -delete diff --git a/README.md b/README.md index 6696621..91c77af 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -[![Build Status](https://travis-ci.com/scommons/scommons-react.svg?branch=master)](https://travis-ci.com/scommons/scommons-react) +[![CI](https://github.com/scommons/scommons-react/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/scommons/scommons-react/actions/workflows/ci.yml?query=workflow%3Aci+branch%3Amaster) [![Coverage Status](https://coveralls.io/repos/github/scommons/scommons-react/badge.svg?branch=master)](https://coveralls.io/github/scommons/scommons-react?branch=master) [![scala-index](https://index.scala-lang.org/scommons/scommons-react/scommons-react-core/latest.svg)](https://index.scala-lang.org/scommons/scommons-react/scommons-react-core) [![Scala.js](https://www.scala-js.org/assets/badges/scalajs-1.1.0.svg)](https://www.scala-js.org) diff --git a/pgp.sbt b/pgp.sbt index b25983a..5485218 100644 --- a/pgp.sbt +++ b/pgp.sbt @@ -1,7 +1,6 @@ +import java.util.Base64 //see: https://www.scala-sbt.org/sbt-pgp/usage.html - -useGpg := false -pgpPublicRing := file("./travis/pubring.gpg") -pgpSecretRing := file("./travis/secring.gpg") -pgpPassphrase := sys.env.get("PGP_PASS").map(_.toArray) +pgpPublicRing := file("./keys/pubring.gpg") +pgpSecretRing := file("./keys/secring.gpg") +pgpPassphrase := sys.env.get("PGP_PASS").map(p => new String(Base64.getDecoder.decode(p)).toArray) diff --git a/project/plugins.sbt b/project/plugins.sbt index 23d7ec7..48e4fbb 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,8 +1,8 @@ //resolvers += "Typesafe repository" at "https://repo.typesafe.com/typesafe/releases/" resolvers += "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/" -addSbtPlugin(("org.scommons.sbt" % "sbt-scommons-plugin" % "0.8.0-SNAPSHOT").changing()) -//addSbtPlugin("org.scommons.sbt" % "sbt-scommons-plugin" % "0.8.0") +//addSbtPlugin(("org.scommons.sbt" % "sbt-scommons-plugin" % "0.8.0-SNAPSHOT").changing()) +addSbtPlugin("org.scommons.sbt" % "sbt-scommons-plugin" % "0.8.0") addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.5") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.0") diff --git a/project/src/main/scala/common/Libs.scala b/project/src/main/scala/common/Libs.scala index b09ff83..1a1905f 100644 --- a/project/src/main/scala/common/Libs.scala +++ b/project/src/main/scala/common/Libs.scala @@ -6,7 +6,7 @@ import scommons.sbtplugin.project.CommonLibs object Libs extends CommonLibs { - val scommonsNodejsVersion = "0.7.0" + val scommonsNodejsVersion = "0.8.0" private val sjsReactJsVer = "0.17.1" lazy val sjsReactJsCore = Def.setting("org.scommons.shogowada" %%% "scalajs-reactjs-core" % sjsReactJsVer) diff --git a/project/src/main/scala/definitions/ScalaJsModule.scala b/project/src/main/scala/definitions/ScalaJsModule.scala index 1d3e852..47fdac6 100644 --- a/project/src/main/scala/definitions/ScalaJsModule.scala +++ b/project/src/main/scala/definitions/ScalaJsModule.scala @@ -7,7 +7,6 @@ import sbt._ import scalajsbundler.sbtplugin.ScalaJSBundlerPlugin import scommons.sbtplugin.project.CommonNodeJsModule import scoverage.ScoverageKeys.{coverageEnabled, coverageScalacPluginVersion} -import scoverage.ScoverageSbtPlugin._ trait ScalaJsModule extends ReactModule { @@ -24,14 +23,14 @@ trait ScalaJsModule extends ReactModule { }, libraryDependencies ~= { modules => if (scalaJSVersion.startsWith("0.6")) modules - else modules.filter(_.organization != OrgScoverage) + else modules.filter(_.organization != "org.scoverage") }, libraryDependencies ++= { if (coverageEnabled.value) { if (scalaJSVersion.startsWith("0.6")) Nil else Seq( - OrgScoverage %% s"${ScalacRuntimeArtifact}_sjs1" % coverageScalacPluginVersion.value, - OrgScoverage %% ScalacPluginArtifact % coverageScalacPluginVersion.value % ScoveragePluginConfig.name + "org.scoverage" %% "scalac-scoverage-runtime_sjs1" % coverageScalacPluginVersion.value, + "org.scoverage" %% "scalac-scoverage-plugin" % coverageScalacPluginVersion.value % "scoveragePlugin" ) } else Nil diff --git a/travis/secrets.tar.enc b/travis/secrets.tar.enc deleted file mode 100644 index e8654e90a09c661b4d4a7e75b6cb9ca100f06c96..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5136 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