The Scala Platform

The Platform sbt plugin

sbt-platform is a SBT plugin that aims at simplifying the maintenance and release of Scala Platform modules. It automates common use cases to speed up developers' workflow and let module maintainers focus on the essential.

Add it to your project (project/plugins.sbt) with:

addSbtPlugin("ch.epfl.scala" % "sbt-platform" % "0.2.0")

The sbt-platform plugin provides a tight integration with the Scala Platform CI server and infrastructure. For now, it covers the following use cases:

  • Automatic release of nightlies.
  • Automatic release of stable versions when a git tag is found.
  • MiMa compatibility checks and PGP signatures for artifacts (with Scala Platform keys).
  • Integration with our Drone setup for writing your own sbt scripts.
  • Automatic detection of cumbersome sbt keys (e.g. scmInfo).
  • Automatic configuration of common sbt plugins:
    • sbt-bintray
    • sbt-pgp
    • sbt-release
    • sbt-mima-plugin
    • sbt-coursier

Together with our CI, the plugin aims to provide a complete developer experience with good error detection.

Next steps

As sbt-platform is still work in progress, we're open to suggestions on improving Scala Platform modules' maintainers. Our potential next steps are:

  • Adding support for Sonatype.
  • Releasing to more than one Maven/Ivy repository (Scala Platform's and your personal one).
  • Extending the default release steps for every process.
  • Adding release processes for release candidates and milestones.
  • Adding smart test execution based on changes in git commits, i.e. instead of running sbt test for all the projects, run it only for the affected subprojects.
  • Improving MiMa binary compatibility checks.
  • Adding source compatibility checks using Scala Meta.

If any of the previous features calls your attention, feel free to help out and make a PR. sbt-platform follows the same CONTRIBUTION guidelines than the Scala Platform process.

We hope to improve the infrastructure and the maintainers support as the Scala Platform grows and the community gets involved. This plugin only provides support for a basic subset of features that improve maintainers' life. We expect to enrich this subset with maintainers' input.

Usage

sbt-platform defines two main commands:

PlatformDescription
releaseNightlyRelease a nightly version of the module.
releaseStableRelease a stable version of the module.

Examples of use

releaseNightly [release-version <version>] [skip-tests] [cross]
releaseStable [release-version <version>] [skip-tests] [cross]

All the arguments are optional and <> represents the parameters.

Release commands are executed by the CI. To set it up, check the CI documentation.

Setup

sbt-platform already comes with a default setup, thought out to get you started as soon as possible. You only need to make sure that the integration with the CI works.

However, you may find interesting changing the value of some sbt keys. The general syntax for this is:

nameOfSbtSettingOrTask := {
  // Write here Scala code that returns a value
  // according to the type of the settings or task
}

Common general settings and tasks

This section includes the most important settings and tasks of the sbt plugins the sbt-platform depends on.

SettingsDescriptionTypeDefault
bintrayRepositoryName of the Bintray repository the artifact will be stored on.StringN/A
bintrayOrganizationName of the Bintray organization the repository is in.String"scalaplatform"
publishArtifact in TestSetting to include the test sources in the final released artifact.Booleanfalse
TasksDescription
bintraySyncMavenCentralSync bintray-published artifacts with maven central

Platform-specific tasks and settings

Aside from reusing the settings and tasks defined by the dependent sbt plugins, sbt-platform defines their own to make easier customize the plugin functionality.

Platform-specific settings

SettingsDescriptionTypeDefault
platformInsideCiChecks if CI is executing the build.Booleanfalse
platformCiEnvironmentGet the Drone environmentOption[CIEnvironment]None
platformReleaseOnMergeRelease on every PR merge.Booleanfalse
platformModuleNameName of the module and the bintray package.StringbintrayPackage.value
platformModuleTagsTags for the bintray module package.Seq[String]bintrayPackageLabels.value
platformTargetBranchBranch used for the platform release.String"platform-release"
platformGitHubTokenToken to publish releases to GitHub.StringN/A
platformReleaseNotesDirDirectory with the markdown release notes.StringbaseDirectory.value / "notes"
platformSignArtifactEnable to sign artifacts with the platform pgp key.Booleantrue
platformPgpRingsFiles that store the pgp public and secret ring respectively.Option[(File, File)]N/A
platformBeforePublishHookA hook to customize all the release processes before publishing to Bintray.Task[Unit]N/A
platformAfterPublishHookA hook to customize all the release processes after publishing to Bintray.Task[Unit]N/A

Platform-specific tasks

TasksDescription
platformValidatePomDataEnsure that all the data is available before generating a POM file.
platformCurrentVersionGet the current version to be released.
platformLatestPublishedVersionFetch latest published stable version.
platformPreviousArtifactsGet mimaPreviousArtifacts or fetch latest artifact to run MiMa.
platformNextVersionFunFunction that decides the next version.
platformRunMiMaRun MiMa and report results based on current version.
platformGetReleaseNotesGet the correct release notes for a release.
platformReleaseToGitHubCreate a release in GitHub.
platformActiveReleaseProcessThe active release process if releaseNightly or releaseStable has been executed.
platformNightlyReleaseProcessThe default nightly release process.
platformStableReleaseProcessThe default stable release process.

Release processes

The release process setup relies on sbt-release and follows the Scala Platform release process. By using it, modules maintainers can be sure that their practices are valid according to the spec.

Platform Bintray repositories

The Scala Platform uses Bintray to store and release all the Scala modules artifacts. Bintray allows maintainers a fine-grained control over their releases and provides instant release time and synchronization with Maven Central. The Bintray Scala Platform organization owns the following repositories:

  1. releases - Stable releases (and, in the future, milestones and RCs).
  2. nightlies - Nightly releases.
  3. tools - Scala Platform maintainers' tools.

How nightlies work

The Scala Platform bot is executed every night and takes care of:

  • Releasing a nightly of every module of the Scala Platform.
  • Warning when:
    • Binary compatibility is broken;
    • Version is invalid;
    • Tests don't pass; and
    • Bintray upload failed.

In case something goes wrong, notifications are sent via email / Gitter / Slack. Nightly releases are available in nightlies.

Stable releases

To cut a stable release, tag the platform-release branch with the appropiate version number and push. When Drone finishes, your release will be available in releases.

Decide the version number for stable releases

You're free to choose the version number of the library as long as the bumped number is consistent with the Scala Platform version your module is targeting. If the latest Scala Platform release was 1.2 and the next one is 1.3, then your stable version is only allowed a minor bump (e.g. 2.3 => 2.4, 1.1 => 1.4).

Decide the Maven coordinates

When releasing stable versions, module maintainers can decide the group id of their maven coordinates. For instance, already existing organizations or individuals may want to preserve their credit in the official artifacts they release.

To enable our infrastructure to release to Maven Central, you need to:

  • Give deploy access to the user scalaplatform in Sonatype by either:

We suggest you to go with the first option. Here you have a useful video in case you're lost.

Make sure that the organization setting in sbt is set to your desired group id. Ultimately, this is the option that sets the Ivy and Maven path.

Modify the release process

The simplest way to modify the default release processes is to use platformBeforePublishHook and platformAfterPublishHook. For instance, let's register a new GitHub release for every nightly, but only after publishing to Bintray (disabled by default).

platformAfterPublishHook := {
    val logger = streams.value.log
    val active = platformActiveReleaseProcess.value  
    if (active.exists(platformNightlyReleaseProcess.value)) {
      logger.info("Cool! Nightlies are now released to GitHub.")
      platformReleaseToGitHub.value
    }
}

The previous code checks that the active release process, set when either releaseStable or releaseNightly is run, corresponds to the defined nightly process and if so creates a release in GitHub, along with your markdown release notes (if any).

On further extensions

sbt-release provides primitives to write release processes from scratch:

  1. releaseStepTask - Run an individual task. Does not aggregate builds.
  2. releaseStepTaskAggregated - Run an aggregated task.
  3. releaseStepInputTask - Run an input task, optionally taking the input to pass to it.
  4. releaseStepCommand - Run a command.

Use them if you want to extend the release process with input tasks, or any other feature that requires more fine-grained control. When you are finished, set your new release process to platformNightlyReleaseProcess or platformStableReleaseProcess.

sbt-platform does not provide good support for advanced use cases yet. We strongly recommend you to check the authoritative sbt-release guide to learn how to extend the release process. As a plus, you can always check sbt-platform's source code.