A sane set of common build settings.
Note: global plugin removed
Since version 1.6.0 the global plugin has been merged back into the per-project plugin. If you used that dependency, remove it from your .sbt files in
For each project where you'd like to use the build settings, add the following your
addSbtPlugin("com.softwaremill.sbt-softwaremill" % "sbt-softwaremill" % "1.8.3")
Now you can add
smlBuildSettings to any set of build settings in your
lazy val commonSettings = smlBuildSettings ++ Seq( // your settings, which can override some of smlBuildSettings )
If you only want to import a subset of settings, you can select from:
lazy val smlBuildSettings = commonSmlBuildSettings ++ // compiler flags splainSettings ++ // gives rich output on implicit resolution errors dependencyUpdatesSettings ++ // check dependency updates on startup (max once per 12h) wartRemoverSettings ++ // warts acyclicSettings ++ // check circular dependencies between packages ossPublishSettings // configures common publishing process for all OSS libraries
Adding more ignored Warts
If you are annoyed by some Wartremover warnings and you'd like to extend the default set of ignored warnings, you can define them like:
.settings( wartremoverWarnings in (Compile, compile) --= Seq( Wart.DefaultArguments, Wart.JavaSerializable ), wartremoverWarnings in (Test, compile) --= Seq( Wart.Var, Wart.MutableDataStructures ), wartremoverWarnings in (IntegrationTest, compile) := Warts.all // custom scope .diff(smlWartremoverTestCompileExclusions) // default set .diff(Seq(Wart.Var, Wart.MutableDataStructures)) )
sbt-softwaremill comes with:
Releasing your library
sbt-softwaremill exposes a default configuration suitable for releasing open source libraries.
ossPublishSettingsto your project's settings
- Ensure you have configured your repository credentials, for example you may need to add
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")to
~/.sbt/1.0/cred.sbtor use other method.
- Run the
releasecommand Consider that:
- You need an OSS Sonatype account and sbt-pgp plugin properly configured with generated and published keys.
docsdirectory will be parsed for
"[organization]" %(%) "artifactId" % "someVersion"and that version value will be bumped.
- If you a have multi-module project, you may need to add
publishArtifact := falseto your root project's settings.
Releasing your library using Travis
To use, you'll need to include
com.softwaremill.PublishTravis.publishTravisSettings in the settings of your
root project only:
lazy val rootProject = (project in file(".")) .settings(publishTravisSettings)
Moreover, you should include
ossPublishSettings in the settings of all the projects you'd like to publish. You might need to customise settings such as
developers etc. For example:
val commonSettings = ossPublishSettings ++ Seq( sonatypeProfileName := "com.example" )
The release process is broken into two steps:
sbt commitRelease. This sbt command prepares the next release: runs the tests, updates
version.sbt, creates the git tag, commits the changes and finally asks the user to push the changes.
sbt publishRelease. This sbt command should be run on Travis, triggered when a new tag is pushed. It publishes the artifacts to sonatype, and invokes repository release.
PublishTravis for details on how the release steps are defined in both cases.
To run the release, travis needs to know the keypair to sign the artifacts, as well as the username/password to access
oss.sonatype.org. These values all need to be prepared in file locally, then packaged, encrypted using a secret that's only known to travis, and committed.
Here's how to do that:
pubring.ascfiles with the PGP private/public keys
- create a
credentials.sbtfile with the following content:
credentials += Credentials("Sonatype Nexus Repository Manager", "oss.sonatype.org", "SONATYPE_USERNAME", "SONATYPE_PASSWORD") pgpPassphrase := Some("KEY_PASSWORD").map(_.toArray)
- create an archive:
tar cvf secrets.tar secring.asc pubring.asc credentials.sbt
- login to travis:
travis login(you'll need the travis CLI to do that)
- encrypt the archive:
travis encrypt-file secrets.tar --add
This should have two effects:
- an encrypted file should be created in the top-level directory:
secrets.tar.enc. This file should be committed. Take care not to commit
secrets.tar, though :).
before_installsegment should be added to
travis.yml. This segment decrypts the secrets file, using environmental variables provided by travis
before_install section, there should also be an entry unpacking the secrets file:
tar xvf secrets.tar.
If you are doing a matrix build, the release should happen during one of the runs - as the release releases for all cross-versions.
language: scala scala: - 2.12.8 - 2.13.0 before_install: - openssl aes-256-cbc -K $encrypted_f7a2d53f3383_key -iv $encrypted_f7a2d53f3383_iv -in secrets.tar.enc -out secrets.tar -d - tar xvf secrets.tar before_cache: - du -h -d 1 $HOME/.ivy2/ - du -h -d 2 $HOME/.sbt/ - du -h -d 4 $HOME/.coursier/ - find $HOME/.sbt -name "*.lock" -type f -delete - find $HOME/.ivy2/cache -name "ivydata-*.properties" -type f -delete - find $HOME/.coursier/cache -name "*.lock" -type f -delete cache: directories: - "$HOME/.sbt/1.0" - "$HOME/.sbt/boot/scala*" - "$HOME/.sbt/cache" - "$HOME/.sbt/launchers" - "$HOME/.ivy2/cache" - "$HOME/.coursier" script: - sbt ++$TRAVIS_SCALA_VERSION test deploy: - provider: script script: sbt publishRelease skip_cleanup: true on: all_branches: true condition: $TRAVIS_SCALA_VERSION = "2.12.8" && $TRAVIS_TAG =~ ^v[0-9]+\.[0-9]+(\.[0-9]+)?