djspiewak / sbt-spiewak

A plugin which represents my personal SBT project baseline
Apache License 2.0
53 stars 20 forks source link

sbt-spiewak

This plugin basically just exists to allow me to more conveniently setup my baseline SBT configuration, which has evolved somewhat over the years, and is also becoming quite unwieldy when solely represented in giter8 format. If you want to use this plugin with a new project, you should probably start from that template.

If you generally agree with my opinions on how projects should be set up, though, then this is probably a really excellent plugin to base on! Between this plugin and my giter8 template, you can get a new Scala project up and running and publishing to Sonatype within about five minutes. As an example, check out this quick screencast:

sbt-spiewak demo

TLDR, it's really really easy.

Usage

Put one of the following into your plugins.sbt:

// for stock functionality (no publication defaults)
addSbtPlugin("com.codecommit" % "sbt-spiewak" % "<version>")

// publishing to sonatype
addSbtPlugin("com.codecommit" % "sbt-spiewak-sonatype" % "<version>")

Then, in your build.sbt, make sure you set a value for baseVersion, organization, publishGithubUser and publishFullName:

ThisBuild / organization := "com.codecommit"

ThisBuild / baseVersion  := "0.1"

ThisBuild / publishGithubUser := "djspiewak"
ThisBuild / publishFullName   := "Daniel Spiewak"

Or something like that.

If you have a multi-module build and need a subproject to not publish (as is commonly done with the root project), enable the NoPublishPlugin. For example:

lazy val root = project
  .aggregate(core, sonatype)
  .in(file("."))
  .settings(name := "root")
  .enablePlugins(NoPublishPlugin)

Release automatically with GitHub Actions CI

If you would like your releases to be published by your CI process in GitHub Actions, rather than locally, you will probably benefit from the SonatypeCiReleasePlugin plugin (part of sbt-spiewak-sonatype). This makes some assumptions about your secrets and general build configuration, applies the settings to the sbt-github-actions-generated workflow, and generally takes care of everything for you.

To use, add the following to the root level of your build.sbt:

enablePlugins(SonatypeCiReleasePlugin)

Then, generate the initial GitHub Actions in .github/workflows with the githubWorkflowGenerate SBT task (see tasks for sbt-github-actions).

After that, configure the following encrypted secrets within GitHub Actions (go to Settings -> Secrets -> New secret; see GitHub Encrypted Secrets documentation for more detail):

You can obtain the PGP_SECRET by running gpg --export-secret-keys | base64. Please make sure that this key is not password protected in the export (GitHub Actions itself will encrypt it).

Once this is done, decide whether you would like snapshots to be published on every master build. By default, releases will only be published on version tags. If you wish to override this, set the following:

ThisBuild / spiewakCiReleaseSnapshots := true

If you do set the above to true, you should probably also make sure to set your primary branch as below:

ThisBuild / spiewakMainBranches := Seq("main")

You can also simply add additional branches, if you're publishing snapshots on more than one at a time.

With all of these steps out of the way, you should have some nice, reliable, CI-driven releases going forward!

Caveat: If you are publishing snapshots on your primary branch, you will need to be careful to ensure that new tags are fully built on the primary branch before you push the tag to the upstream. The reason for this is the fact that tags are visible to the primary branch builds, meaning that if you push a new commit to master and a tag which points to it, that commit and tag will build and release under the same name simultaneously. The workaround is to push master, wait for the snapshot release to complete, and then push the tag. I'll get around to fixing this someday...

Features

Sonatype Requirements

You will need to define the following settings:

ThisBuild / homepage := Some(url("https://github.com/djspiewak/sbt-spiewak"))

ThisBuild / scmInfo := Some(ScmInfo(url("https://github.com/djspiewak/sbt-spiewak"),
  "git@github.com:djspiewak/sbt-spiewak.git"))

Defaults Which You May Wish to Override...

You may consider overriding any of the following keys, which are hard-coded to defaults that I believe are reasonable: