Why I choose to use a mono-repo for a large Gradle project
Tags: productivity, github, java, kotlin
Published: 2020-06-18 22:50:32

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:

```groovy
plugins {
    id "org.jetbrains.kotlin.jvm" version "1.3.61"
}
```

And in another repository:

```groovy
plugins {
      id "org.jetbrains.kotlin.jvm" version "1.3.52"
}
```

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](https://github.com/features/security). _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:

```bash
git subtree add --prefix=projects/service-A git://github.com/my-company/service-A.git master
```

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
 		- ...
```

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:

```groovy
file("projects").eachDir { p ->
    include p.name
    project(":${p.name}").projectDir = p
}
```

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 !