A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/ShiftLeftSecurity/sbt-ci-release-early below:

ShiftLeftSecurity/sbt-ci-release-early: Sbt plugin for fully automated releases, without SNAPSHOT and git sha's in the version. A remix of the best ideas from sbt-ci-release and sbt-release-early. For local CI and/or sonatype/maven central.

sbt plugin for fully automated releases, without SNAPSHOT and git sha's in the version. You can easily create e.g. daily or weekly releases, or even release every single commit on your main branch. A remix of sbt-ci-release and sbt-release-early with a spin.

projects/plugins.sbt:

addSbtPlugin("io.shiftleft" % "sbt-ci-release-early" % "<version>")

Note

If you don't have any previous versions tagged in git, the plugin will automatically create a v0.1.0 tag for you. Alternatively you can manually create an initial version tag (e.g. git tag v0.0.1) and the plugin will take it from there. The same applies if you want to use a different versioning scheme, e.g. v1, v0.1 or v0.0.0.1. All that matters is that they must start with v (by convention).

Setup for a custom repository (e.g. jfrog artifactory)

In your build.sbt do not define the version setting, and configure your repository in the publishTo setting:

ThisBuild/publishTo := Some("releases" at "https://shiftleft.jfrog.io/shiftleft/libs-release-local")

In your release pipeline run:

sbt ciReleaseSkipIfAlreadyReleased ciReleaseTagNextVersion ciRelease

Note

cross builds (for multiple scala versions) work seamlessly (the plugin just calls +publishSigned)

Setup for Sonatype / Maven central

Sonatype central (which syncs to maven central) imposes additional constraints on the published artifacts, so the setup becomes a little more involved. These steps assume you're using github actions, but it'd be similar on other build servers.

If you don't have a Sonatype account yet, follow the instructions in https://central.sonatype.org/register/central-portal/ to create one.

In your build.sbt do not define the version setting and ensure the following settings are configured:

Example: https://github.com/mpollmeier/sbt-ci-release-early-usage/blob/master/build.sbt

Note

For a multi-project build, you likely want to define those settings in your root build.sbt and prefix them with ThisBuild/, e.g. ThisBuild/publishTo := sonatypePublishToBundle.value. That way they'll apply to all subprojects.

echo '/gnupg-*' >> .gitignore

Sonatype requires all artifacts to be signed. Since it doesn't matter which key it's signed with, and we need to share the private key with the build server (e.g. github actions), we will simply create a new one specifically for this project:

At the end you'll see output like this

pub   rsa2048 2018-06-10 [SC] [expires: 2022-11-13]
      $LONG_ID
uid                      $PROJECT_NAME bot <$EMAIL>

Take note of $LONG_ID, make sure to replace this ID from the code examples below. The ID will look something like 499FD7755EC30DDAF43089355E00EC8C822C6A2A.

export LONG_ID=499FD7755EC30DDAF43089355E00EC8C822C6A2A

Optional: if you would like to make the key never expire:

gpg --edit-key $LONG_ID
expire #follow prompt
key 1
expire #follow prompt
save

Now submit the public key to a keyserver (shouldn't matter which one, keyservers synchronize their keys with each other):

gpg --keyserver keyserver.ubuntu.com --send-keys $LONG_ID
Secrets to share with Github actions

So that Github Actions can release on your behalf, we need to share some secrets via environment variables with github actions. You can either do that for your project or an entire organization. Sonatype requires you to authorize your deployment artifacts with an access token, which you can get retrieve from sonatype and share with github actions as follows:

Now you can share those for your entire github organization's github actions or only for a single project as follows:

# macOS
gpg --armor --export-secret-keys $LONG_ID | base64 | pbcopy
# Ubuntu (assuming GNU base64)
gpg --armor --export-secret-keys $LONG_ID | base64 -w0 | xclip
# Arch
gpg --armor --export-secret-keys $LONG_ID | base64 | sed -z 's;\n;;g' | xclip -selection clipboard -i
# FreeBSD (assuming BSD base64)
gpg --armor --export-secret-keys $LONG_ID | base64 | xclip
# Windows
gpg --armor --export-secret-keys %LONG_ID% | openssl base64

Your secrets settings should look like this:

The final step is to configure your github actions workflow. There's many ways to do this, but most builds can probably take the below setup as is. It configures two workflows: one for pull requests which only runs the tests, and one for master builds, which also releases a new version. Both are configured with a cache to avoid downloading all your dependencies for every build.

<project_root>/.github/workflows/pr.yml

name: pr
on: pull_request
jobs:
  pr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 1
      - name: Setup JDK
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 21
          cache: sbt
      - uses: sbt/setup-sbt@v1
      - run: sbt +test

<project_root>/.github/workflows/release.yml

name: release
concurrency: release
on:
  push:
    branches: [master, main]
    tags: ["*"]
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Setup JDK
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 21
          cache: sbt
      - uses: sbt/setup-sbt@v1
      - run: sudo apt update && sudo apt install -y gnupg
      - run: echo $PGP_SECRET | base64 --decode | gpg --batch --import
        env:
          PGP_SECRET: ${{ secrets.PGP_SECRET }}
      - run: sbt +test ciReleaseSkipIfAlreadyReleased ciReleaseTagNextVersion ciReleaseSonatype
        env:
          SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
          SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}

That's all. Here's a demo repo: https://github.com/mpollmeier/sbt-ci-release-early-usage

By installing sbt-ci-release-early the following sbt plugins are also brought in:

How can determine the latest released version?

Other than manually looking at Sonatype/Maven central or git tags, you can use the following snippet that remotely gets the git tags that start with v and have (in this version) three decimals separated by ., and returns the highest version.

git ls-remote --tags $REPO | awk -F"/" '{print $3}' | grep '^v[0-9]*\.[0-9]*\.[0-9]*' | grep -v {} | sort --version-sort | tail -n1
My Sonatype staging repos seems to be in a broken state

When a build is e.g. interrupted, or didn't satisfy the Sonatype requirements for publishing, it is likely that these artifacts are still lying around in the Sonatype staging area. You can log into https://central.sonatype.com/ and clean it up, or just do it from within sbt, locally on your machine:

Why not just use SNAPSHOT dependencies instead?

SNAPSHOT dependencies have major downsides:

How do I release a specific version?

To keep things simple I decided to not add that feature to this plugin. If you want to release a specific version you have to do that yourself:

// in sbt:
set version := "1.2.3"
+publishSigned
sonatypeBundleRelease

// on the terminal:
git tag v1.2.3
git push origin v1.2.3

Note to future self: this would have added complexity because to trigger it we would rely on git tags, and we need a foolproof way to check if a given tag has already been released. My intial thought was to tag anything released with _released_1.0.1_, but it was getting quite complicated for handling an edge case.

How do I disable publishing in certain projects?

Add the following to the project settings:

What if my build contains subprojects?

If the build defines a dependency on the subproject (e.g. dependsOn(subProjectName)) then it's automatically included in the release. Otherwise you can just append subProjectName/publish to your build pipeline, the version is already set for you :)

Can I use my releases immediately?

As soon as Sonatype "closes" the staging repository they become available on Sonatype/releases and will be synchronized to maven central within ~10mins. If you want to use them immediately, add a Sonatype resolver to the build that uses the released artifact:

resolvers += Resolver.sonatypeRepo("releases")
Can I publish sbt plugins?

Yes. This plugin is published with a previous version of itself :)

There exist great alternatives to sbt-ci-release-early that may work better for your setup.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4