DEV Community

Sylvain Corsini
Sylvain Corsini

Posted on

Why I choose to use a mono-repo for a large Gradle project

First of all, mono-repo doesn’t mean monolithic, even if monolithic means mono-repo ;)
And this post didn’t apply for Gradle project only.

I'm the only one developer in my company and working on a very large project. I have to quickly publish new features, fixes and other things.. When I'm vacant or when I'm busy on a feature, the project is directly impacted. I have to rapidly manage the whole project, be sure everything is robust because I can't waste time in trivialities.

I go through the multi-repo pattern. I split my project into different repositories. I quickly got dozens of repos and more as the project grows.

Multi-repo is not the best solution when you're the only one developer and you don't have the workload to manage everything. I will explain you why with my short-story.

The issue with multi-repo

Managing dependencies inside all my different repository became hard

One day I tried using a Kotlin feature I already used in another repository and it didn't work... What's missing in my project to use that simple feature introducing in the 1.3.60 version... Oh, I understand.

I saw that:

plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.61"
Enter fullscreen mode Exit fullscreen mode

And in another repository:

plugins {
      id "org.jetbrains.kotlin.jvm" version "1.3.52"
Enter fullscreen mode Exit fullscreen mode

Ok... I forgot to update my Kotlin version in the repository... Oups.

After investigations, a lot of dependencies through all repositories were out-dated and not only dependencies but also plugins. Updating the dependencies in all repository was very boring and difficult.

One day, a new GitHub feature appears : Dependabot. Look here. I will talk about it in another post.

I did add it in every repository to help me managing the dependencies version. Every week, I had to do the exact same thing through all my repositories... Bump dependencies version and be sure it wont break anything.

So time-consuming.. I'm alone and I waste time with dependencies... Frustrating.

Sharing code between repository is painful

The bad story began when I wanted to use something from a repo to another... I start copy-pasting the needed code through the repositories. Thinking, I will manage that later. We all know code duplication is a very bad idea.

I did a breaking change in that shared part, a very breaking one, and... A little repository lost in the big sea of repositories did not received its update. You know what ? Everything did blow. I quickly fix that of course but... What if my project was over-used like Facebook ?

This issue finished me. I said stop. Stop copy-pasting code, it's hell. I start publishing all my repo in a private maven repository. I quickly go through the free-tier but I will certainly found a solution for that.

Managing packages is very time-consuming. Really ! When I did publish a repo somewhere, I have to update it everywhere. And.... The same pattern did appear. I forgot to change the version in one repository and bugs appears again.

Publishing private repository was not the solution. (even with Dependabot since it didn't have read access to my private repository).

Multi-repositories = multiples projects in the IDE and hard to fix issues

When I have to add a new feature, I sometimes have to modify multiple services, since one change may have impact in others.

When I got a bug, it was sometimes difficult to know each part is really affected and which one create the bug. It may arrive that an issue comes from multiple services or we have to fix it in different services. Issue-tracking is hard through dozen of repository.

Managing all the different projects under my IntelliJ IDEA became difficult. I often had multiple window opened.

Mono-repo, my answer

You understand I did waste a lot of time with a lot of trivial things... Instead of being focused on features, I was focused on managing repositories and dependencies.

I dive into a mono-repo project. It was quite difficult at the first steps. I did lost some days and then.. I manage to have a mono-repo with all my repositories without losing commits. With one simple git command:

git subtree add --prefix=projects/service-A git:// master
Enter fullscreen mode Exit fullscreen mode

By doing this for every repository, I finally got a directory (projects) with all my services.

The philosophy here is: one build.gradle to rule them all.

All dependencies and plugins are managed by the root build.gradle and every micro-services are splited into two project x-service and x-shared. And I can easily include the x-shared project from any other projects inside my mono-repo. I don't have to deal with maven packages and any other time-consuming thing.

I so have something like:

 - build.gradle
 - settings.gradle
 - projects
        - first-service
        - first-shared
        - second-service
        - third-service
        - thrid-shared
        - ...
Enter fullscreen mode Exit fullscreen mode

The root build.gradle is managing everything for every sub-projects thanks to the allproject and subprojects component.

Since I got a lot of sub-projects, instead of included them all, I did a easy script in my root settings.gradle file:

file("projects").eachDir { p ->
    project(":${}").projectDir = p
Enter fullscreen mode Exit fullscreen mode

It includes every sub-projects from the projects directory and rename them to be :first-service instead of :projects:first-service which is awkward.

Merging everything in one repository is also so good for my IDE. Everything fall in my hand quickly when clicking on classes through the whole services.

A final note

Mono-repo comes with other complications. But I manage to deal with all of them and now, mono-repo help me a lot in my daily job. I can finally focus on my code.

Of course, mono-repo is not a solution for everyone. It's a case-by-case. Just : think about it, it's not a absurd, unstable or unviable solution as some peoples says.

I will explain how I manage dependencies, plugins, CI/CD and everything else with a Gradle mono-repo in others posts. Don't forgot to follow me to see what's coming next.

I will be glad to hear about your experiences in the comments !

Top comments (4)

ama profile image
Adrian Matei • Edited

Quite the same applies to my project - To separate or not to separate frontend and backend?, but as you said it's a case by case thing...

scorsi profile image
Sylvain Corsini

I also use the same repo for the front since the deployment is quite the same. I use the serverless framework for both the front and micro-services. I can recycle the same CI/CD pipeline.
But here, it’s quite more discutable since the front end is managed by NPM.
I pretty like your post btw.

mahyarmlk profile image
Mahyar Maleki

Thanks for sharing your experience
I tried to create mono repository by 'gradle init' and it created a build.gradle for each of my subproject but you said that you have only one build.gradle
I'm confused BTW :)

scorsi profile image
Sylvain Corsini

I have a build.gradle file for each subprojects, but it is only the main build.gradle file in the root directory of the repository which manages the dependencies. I never created the second post of that series, the one talking about dependencies.