sbt the easy way

At Codacy, we use Scala for all our core, complemented by Play Framework and built with sbt.

sbt is a great build tool, specially if you want to focus more on coding than compiling :D.

Earlier this month we decided to do a complete separation of our application.
Although we already had several different sbt sub-projects we had to define some structure and rules to keep them in sync.

With all the simplification and ease of creating a project comes great responsibility, we want our build to be kept simple and easy to maintain.

Growing the project

As soon as our project started growing we found ourselves splitting it into multiples sub-projects and even completely breaking it in several completely different projects.

When we split our monolithic app (one app with several sub-projects) in several completely different projects we thought we could just duplicate all the sbt configs and all would be fine.

But obviously when you go easy on something you will end up suffering :(.

How to keep it clean

Bellow I will describe the most important lessons we learned in this process and why they matter to keep your projects maintainable and in sync.

Before we start you can apply this steps for both sbt sub-projects and completely separated sbt project.
If you have sub-project you should create objects in your project/ folder for example Common.scala and Dependencies.scala.
if you are sharing the settings between projects you can use a sbt plugin to import all the settings.

Common settingsRefactor your configurations into a Common object.

Each sbt project needs to have multiple settings and most of them can/must be shared between projects.
Our base settings contains mainly the scalaVersion, the compiler flags:

Common resolverssbt supports Ivy and also Maven style repositories. Since Scala can use Java libraries it is very common to depend on lots of libraries.
To always have the right resolvers you should define them like the common settings:

Unified dependenciesWhen you have lots of dependencies you do not want to write them all in your projects. Not only because it is a lot of text but also because you should keep versions in sync on your sub-projects.

To solve this you should use a object where you define all of them and then you just have to write the value in the project build definition.