Final subproject sbt setup
I am working on some code with several sub-projects, many of which depend on each other. For example, there is a project utils
with various utilities, a project queueing
with some code for managing queues of things, and then a project mainApp
. The project queueing
depends on utils
, but mainApp
depends on as well as utils
on queueing
. There are many more projects out there, but hopefully you get the general idea.
We use the standard sbt submodule setup for this with one build root, many subprojects and standard tools aggregate
and dependsOn
. This worked, but was problematic:
- It would be very slow to create and run tests for the project. Cleaning a building takes about 15 minutes and unit testing takes longer.
- Because of the way the aggregate works, unit testing
mainApp
has caused all tests to run inutils
andqueuing
even if they haven't changed. True, you can do "test-fast", but that stops working when you change git branches, etc., so you run the whole test suite often anyway. - While sbt only allows you to create a subproject, you must be in the root directory and remember to qualify the assembly. For example, you have to remember to run
sbt utils/compile
instead ofsbt compile
.
So we went to a completely separate project and split up the git repos. Each project builds and then deploys the artifact to the Nexus. So to build and test mainApp
, you just build it and it pulls the already compiled .jar files for other projects from the nexus server. This makes it easier to work in just one project, but it becomes more difficult to make changes, for example, in utils, and then use it in mainApp
. In particular, you often want to do something like add a method to utils
, and then immediately test that method in mainApp
to see if it works before pushing the new version utils
. But now for this you need:
- Add your code to utils
- Decrease version number in utils
- Run "sbt publish-loca"
- Change build.sbt to
mainApp
and add-SNAPSHOT
toutils
dependency - Run
sbt update
- Build and Test
mainApp
If this all works, you need to push utils
and mainApp
in the correct order to the continuous build server and remember to wait for the build to complete utils
before pushing mainApp
.
Worse, maintaining versions becomes very difficult. Let's assume we start with all projects in version 1.0 and depending on version 1.0 other projects. Now suppose we find a bug in utils
that affects mainApp
. So we'll fix it utils
, change its version number to 1.1, update mainApp
to depend on 1.1, and rebuild. Suppose the code that corrects the error in mainApp
introduces the error in queue
. The problem is that if you go to queue
and run your tests, they will work against version 1.0 utils
(even if you use ranges, since sbt only re-checks them). However, when building mainApp
onutils
there will be a dependency conflict that will be resolved by sbt. Regardless of how he resolves it, it will be "wrong" for at least one project. We can set the converter to "strict", but then version control becomes very time consuming in 10+ projects.
What I'm really looking for is an assembly that works best for both worlds. In particular:
- I have a root directory with sub-dirs for each project
- If
pwd
is one of these subdirectories, all sbt commands are specific to that project only. So, ifpwd
-queue
, thensbt test
compiles and tests onlyqueue
. - If there is a version of the artifact on the Nexus, it is fetched from there, but if there is more recent code on disk, the dependency is created locally and used instead.
Or something like that. Does anyone know how to install this using sbt?
source to share
No one has answered this question yet
Check out similar questions: