From 14236209ce4ea4f5818d182bb1ea4906a79e1842 Mon Sep 17 00:00:00 2001 From: Bekir Oguz Date: Thu, 26 Sep 2024 08:41:37 +0200 Subject: [PATCH] CI pipeline with build test and publish jobs (#1762) * use ci-release plugin for automated publish and release * Fix conditional statement in ci.yml for publishing releases * temporarily run CI publish also for PRs * disable automated release note publishing * remove sonatype release command override * publish to sonatype central using temporary account * Update Publish.scala to use sonatypePublishToBundle for publishing * add sonatypeRepository * add sonatype s01 host config * publish using ci-release plugin * trigger pipeline on test branch * Update organization in Publish.scala * override default sonatype central deployment name * Refactor Publish.scala to update sonatypeCentralDeploymentName * update publish settings to fix publish path and sonatype profile name * update sonatypeProfileName to match sonatype account settings * adds pomExtra config * support publish to Azure * reorganize ci pipeline and add write permissions to ci job * upgrade release-drafter version * fix azure credentials script * add some debugging * fix multi-line credentials file * temporarily remove ci dependency in the pipeline * test azure credentials * remove cat line * enable all steps in ci pipeline * publish to sonatype only when manually triggered and for new tags * publish all modules of baker --- .github/release-drafter.yml | 33 ++++++ .github/workflows/ci.yml | 129 +++++++++++++++++++++++ .github/workflows/dependency-graph.yml | 31 ------ .github/workflows/publish.yml | 42 -------- .github/workflows/tests-and-coverage.yml | 31 ------ .scala-steward.conf | 2 + build.sbt | 6 +- get-version.sh | 3 - project/Publish.scala | 72 +++---------- project/plugins.sbt | 8 +- set-version.sh | 11 -- version.sbt | 1 - 12 files changed, 181 insertions(+), 188 deletions(-) create mode 100644 .github/release-drafter.yml create mode 100644 .github/workflows/ci.yml delete mode 100644 .github/workflows/dependency-graph.yml delete mode 100644 .github/workflows/publish.yml delete mode 100644 .github/workflows/tests-and-coverage.yml delete mode 100755 get-version.sh delete mode 100755 set-version.sh delete mode 100644 version.sbt diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 000000000..e692eee5f --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,33 @@ +name-template: 'v$RESOLVED_VERSION 🌈' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + labels: + - 'chore' + - 'dependency' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +template: | + ## Changes + + $CHANGES \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..3387438a6 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,129 @@ +name: CI +on: + workflow_dispatch: + pull_request: + branches: ["master"] + push: + branches: ["master"] + tags: ["v*"] + +permissions: + contents: read + +jobs: + ci: + name: Build and test + permissions: + contents: write + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + - name: Run tests and coverage + run: |- + cp .jvmopts-ci .jvmopts + sbt coverage test coverageReport && bash <(curl -s https://codecov.io/bash) + - name: Prepare draft release notes + continue-on-error: true + uses: release-drafter/release-drafter@v6 + with: + config-name: release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + publish-sonatype: + permissions: + contents: write + pull-requests: write + name: Publish to Sonatype + # Publish to Sonatype only on tags starting with 'v' and on workflow_dispatch + if: | + github.event_name == 'workflow_dispatch' || + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) + needs: [ci] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + - name: Publish to Sonatype + run: sbt ci-release + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + publish-azure: + permissions: + contents: write + pull-requests: write + name: Publish to Azure + needs: [ci] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + - name: Publish to Azure + run: |- + echo "Prepare credentials" + CONTENTS=$(cat << EOF + realm=pkgs.dev.azure.com + host=pkgs.dev.azure.com + user=$AZURE_FEEDUSER + password=$AZURE_FEEDPASSWORD + EOF + ) + echo "$CONTENTS" > ~/.credentials + + sbt "clean; +aetherDeploy; project interaction-example-make-payment-and-ship-items; +aetherDeploy; project interaction-example-reserve-items; +aetherDeploy; project bakery-client-example; +aetherDeploy; project bakery-kafka-listener-example; +aetherDeploy" + + rm ~/.credentials + env: + AZURE_FEEDUSER: ${{ secrets.AZURE_FEEDUSER }} + AZURE_FEEDPASSWORD: ${{ secrets.AZURE_FEEDPASSWORD }} + AZURE_FEEDURL: ${{ secrets.AZURE_FEEDURL }} + dependency-submission: + name: Submit dependency graph + continue-on-error: true + needs: [ci] + # run on 1) master branch + # do not run on pull requests + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + - name: Submit dependency graph + uses: scalacenter/sbt-dependency-submission@v2 + \ No newline at end of file diff --git a/.github/workflows/dependency-graph.yml b/.github/workflows/dependency-graph.yml deleted file mode 100644 index 05936bad2..000000000 --- a/.github/workflows/dependency-graph.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Upload dependency graph - -on: - push: - branches: [ "master" ] - -permissions: - contents: write # needed to submit dependency graph to github - -jobs: - upload-dependency-graph: - name: Upload dependency graph - runs-on: ubuntu-22.04 - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # we don't know what commit the last tag was it's safer to get entire repo so previousStableVersion resolves - fetch-depth: 0 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: 'sbt' - - # Optional: This step uploads information to the GitHub dependency graph and unblocking Dependabot alerts for the repository - - name: Upload dependency graph - uses: scalacenter/sbt-dependency-submission@ab086b50c947c9774b70f39fc7f6e20ca2706c91 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index ac1ffac56..000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Publish - -on: - workflow_dispatch: - -permissions: - contents: read - -jobs: - sbt: - name: sbt publish - runs-on: ubuntu-22.04 - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # we don't know what commit the last tag was it's safer to get entire repo so previousStableVersion resolves - fetch-depth: 0 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: 'sbt' - - - name: Publish - run: |- - cp .jvmopts-ci .jvmopts - export SourceBranchName=`echo "$GITHUB_REF" | cut -b 12-` # cuts the first 12 characters, namely "refs/heads/" - echo "Will build on branch $SourceBranchName." - git checkout "$SourceBranchName" - git config --global user.email "bakery-release@github.com" - git config --global user.name "baker release pipeline" - git remote set-url origin "https://github.com/ing-bank/baker" - - sbt "release cross with-defaults" - env: - # PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - # PGP_SECRET: ${{ secrets.PGP_SECRET }} - USERNAME: ${{ secrets.PUBLISH_USERNAME }} - PASSWORD: ${{ secrets.PUBLISH_PASSWORD }} diff --git a/.github/workflows/tests-and-coverage.yml b/.github/workflows/tests-and-coverage.yml deleted file mode 100644 index e319e6e92..000000000 --- a/.github/workflows/tests-and-coverage.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Tests & Coverage - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -jobs: - tests-and-coverage: - name: Tests & Coverage - runs-on: ubuntu-22.04 - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # we don't know what commit the last tag was it's safer to get entire repo so previousStableVersion resolves - fetch-depth: 0 - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: 'sbt' - - - name: Run tests and generate coverage report - run: |- - cp .jvmopts-ci .jvmopts - sbt coverage test coverageReport && bash <(curl -s https://codecov.io/bash) diff --git a/.scala-steward.conf b/.scala-steward.conf index a28843ac6..bc7de9034 100644 --- a/.scala-steward.conf +++ b/.scala-steward.conf @@ -1,5 +1,7 @@ # PRs are created only again after 7 days since the last PR has passed pullRequests.frequency = "7 days" +# Add custom labels to PRs to be used by the automated release process +pullRequests.customLabels = [ "dependency" ] # group all patches, and typelevel updates pullRequests.grouping = [ { name = "patches", "title" = "Patch updates", "filter" = [{"version" = "patch"}] }, diff --git a/build.sbt b/build.sbt index e18944975..e47f70f23 100644 --- a/build.sbt +++ b/build.sbt @@ -115,9 +115,7 @@ lazy val crossBuildSettings: Seq[Setting[_]] = Seq( crossScalaVersions := supportedScalaVersions ) -lazy val defaultModuleSettings212: Seq[Setting[_]] = commonSettings ++ dependencyOverrideSettings - -lazy val defaultModuleSettings: Seq[Setting[_]] = crossBuildSettings ++ defaultModuleSettings212 +lazy val defaultModuleSettings: Seq[Setting[_]] = crossBuildSettings ++ commonSettings ++ dependencyOverrideSettings lazy val yPartialUnificationSetting: Seq[Setting[_]] = Seq( Compile / scalacOptions ++= { @@ -650,7 +648,7 @@ lazy val `bakery-integration-tests`: Project = project.in(file("bakery/integrati scalaCheck ) ) - .dependsOn( + .dependsOn( `baker-http-client`, `bakery-client-example`, `interaction-example-make-payment-and-ship-items`, diff --git a/get-version.sh b/get-version.sh deleted file mode 100755 index 95b46e941..000000000 --- a/get-version.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -DIR=$(dirname $0) -cat $DIR/version.sbt | sed 's/ThisBuild \/ version := \"\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1.\2.\3/' diff --git a/project/Publish.scala b/project/Publish.scala index ffe8a327d..181594134 100644 --- a/project/Publish.scala +++ b/project/Publish.scala @@ -1,14 +1,13 @@ import sbt._ import Keys._ -import sbtrelease.ReleasePlugin.autoImport._ -import sbtrelease.ReleaseStateTransformations._ import xerial.sbt.Sonatype.SonatypeKeys._ +import sbtdynver.DynVerPlugin.autoImport._ object Publish { - lazy val settings = - if (sys.env.contains("FEEDURL")) StableToAzureFeed - else if ( (sys.env.contains("USERNAME"))) ReleaseToSonatype + lazy val settings = + if (sys.env.contains("AZURE_FEEDURL")) PublishToAzure + else if ( (sys.env.contains("SONATYPE_USERNAME"))) ReleaseToSonatype else SuppressJavaDocs import aether.AetherKeys._ @@ -19,41 +18,20 @@ object Publish { packageSrc / publishArtifact := true ) - val StableToAzureFeed = Seq( + val PublishToAzure = inThisBuild(List( + dynverSeparator := "-" + )) ++ List( credentials += Credentials(Path.userHome / ".credentials"), - publishTo := Some("pkgs.dev.azure.com" at sys.env.getOrElse("FEEDURL", "")), - publishMavenStyle := true, - aetherDeploy / logLevel := Level.Info + publishTo := Some("pkgs.dev.azure.com" at sys.env.getOrElse("AZURE_FEEDURL", "")), + publishMavenStyle := true ) - protected def isSnapshot(s: String) = s.trim endsWith "SNAPSHOT" - - protected val nexus = "https://oss.sonatype.org/" - protected val ossSnapshots = "Sonatype OSS Snapshots" at nexus + "content/repositories/snapshots/" - protected val ossStaging = "Sonatype OSS Staging" at nexus + "service/local/staging/deploy/maven2/" - - val ReleaseToSonatype = Seq( - credentials ++= Seq( - Credentials( - "Sonatype Nexus Repository Manager", - "oss.sonatype.org", - sys.env.getOrElse("USERNAME", ""), - sys.env.getOrElse("PASSWORD", "") - ), - Credentials( - "GnuPG Key ID", - "gpg", - "303489A85EBB77F6E93E2A254CCF1479F92AE2B7", // key identifier - "ignored" // this field is ignored; passwords are supplied by pinentry - ) - ), - releaseIgnoreUntrackedFiles := true, - sonatypeProfileName := "com.ing", - licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT")), + val ReleaseToSonatype = inThisBuild(List( homepage := Some(url("https://github.com/ing-bank/baker")), - scmInfo := Some(ScmInfo( - browseUrl = url("https://github.com/ing-bank/baker"), - connection = "scm:git@github.com:ing-bank/baker.git")), + licenses := List(License.MIT), + dynverSeparator := "-", + )) ++ List( + sonatypeProfileName := "com.ing", pomExtra := ( @@ -61,28 +39,6 @@ object Publish { Squad Apollo - ), - publishMavenStyle := true, - publishTo := version((v: String) => Some(if (isSnapshot(v)) ossSnapshots else ossStaging)).value, - Test / publishArtifact := false, - packageDoc / publishArtifact := true, - packageSrc / publishArtifact := true, - pomIncludeRepository := (_ => false), - releaseCrossBuild := true, - releaseProcess := Seq[ReleaseStep]( - releaseStepCommand("sonatypeDropAll"), - checkSnapshotDependencies, - inquireVersions, - runClean, - runTest, - setReleaseVersion, - commitReleaseVersion, - tagRelease, - releaseStepCommandAndRemaining("+publish"), - setNextVersion, - commitNextVersion, - releaseStepCommand("sonatypeReleaseAll"), - pushChanges ) ) } diff --git a/project/plugins.sbt b/project/plugins.sbt index 2dba3d51a..dfdc71f9b 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,17 +1,11 @@ -addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.1") - addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.2.0") -addSbtPlugin("com.github.sbt" % "sbt-release" % "1.4.0") +addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.6.1") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.2.0") -addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.11.3") - addSbtPlugin("net.vonbuchholtz" % "sbt-dependency-check" % "5.1.0") -addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.2.1") - addSbtPlugin("com.github.sbt" % "sbt-multi-jvm" % "0.6.0") addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4") diff --git a/set-version.sh b/set-version.sh deleted file mode 100755 index c13c21bb8..000000000 --- a/set-version.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -DIR=$(dirname $0) -# bump this manually whenever breaking change occurs -SEM_VERSION=$($DIR/get-version.sh) - -DATE=$(date +"%y%m%d%H%M%S") -COMMIT=$( git log --pretty=format:'%h' -n 1) -VERSION="${SEM_VERSION}-${DATE}-${COMMIT}" - -echo "ThisBuild / version := \"${VERSION}\"" > ./version.sbt diff --git a/version.sbt b/version.sbt deleted file mode 100644 index 895ae6915..000000000 --- a/version.sbt +++ /dev/null @@ -1 +0,0 @@ -ThisBuild / version := "4.1.0-SNAPSHOT"