FAQ

How do I cut a release?

Create a release on GitHub with a v-prefixed, semantically-versioned tag (or, tag a commit locally and push to GitHub). This will start a CI release. Example tags: v0.4.2, v1.2.3, v1.0.0-M1, v1.2.0-RC2.

It is also possible to run the release process entirely locally by invoking the tlRelease command, assuming that you have correctly configured your PGP keys and Sonatype credentials.

How do I introduce breaking changes intended for my next version?

Bump your tlBaseVersion to the next breaking-version according to early-semver, e.g. 0.7 to 0.8 or 4.2 to 5.0.

What is a base version anyway?

The "base version" is a concept inherited from sbt-spiewak. It is the first two components x.y of your semantic version x.y.z which are used to communicate important information about binary- and source-compatibility of your library relative to previous releases.

If your library is in 0.x, when you open a PR:

If your library is in 1.x or beyond, when you open a PR:

In general, if you attempt to introduce binary-breaking changes without appropriately bumping the base version, your PR will fail in CI due to the MiMa binary-compatibility checks.

How do I indicate the first version that I published Scala 3 artifacts for?

ThisBuild / tlVersionIntroduced := Map("3" -> "0.4.2")

How do I locally prepare my PR for CI?

sbt-typelevel comes with a prePR command, which updates the GitHub workflow, generates headers, runs scalafmt, and clean compiles your code.

You may also want to (globally) install the sbt-rewarn plugin to help you identify and resolve compiler warnings, which by default are fatal in CI.

How do I disable fatal warnings in CI?

If you are using sbt-typelevel fatal warnings are on by default in CI.

ThisBuild / tlFatalWarnings := false

If you are only using sbt-typelevel-ci-release, you are completely in charge of your own scalacOptions, including fatal warnings.

How do I publish snapshots in CI?

// any branches you want snapshots of
ThisBuild / tlCiReleaseBranches := Seq("main")

Make sure to reload sbt and run githubWorkflowGenerate after making a change to this setting.

What happens if I push a tag and commit at the same time?

It Just Works™.

How do I split my CI matrix into separate jobs for JVM, JS, etc?

// Before
val root = project.in(file("."))
  .enablePlugins(NoPublishPlugin)
  .aggregate(
    coreJVM,
    coreJS,
    io.jvm,
    node.js,
    io.js,
    scodec.jvm,
    scodec.js,
    protocols.jvm,
    protocols.js,
    reactiveStreams,
    benchmark
  )

// After
val root = tlCrossRootProject
  .aggregate(core, io, node, scodec, protocols, reactiveStreams, benchmark)

How do I publish to oss.sonatype.org instead of s01.oss.sonatype.org?

Note that oss.sonatype.org is the legacy host and there is an open invitation to migrate to the new host.

ThisBuild / tlSonatypeUseLegacyHost := true

How do I publish a website like this one?

Check out the sbt-typelevel-site plugin.

How do I manage my Scala.js and Scala Native versions?

We recommend explicitly setting your Scala.js and Scala Native versions in project/plugins.sbt.

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.17.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.17")

sbt-typelevel ships with a conservative Scala.js and Scala Native version to enable certain settings. If one of your dependencies requires a newer version you may experience failures in the scalaJSLink or nativeLink CI steps.