Bazel & Introductions: Part Four – The Monorepo

Flash back to MVRT Build Season, 2016.

The people in this conversation are fictionalized and not meant to represent any members of Valkyrie Robotics.

Mee: Larcus, we should migrate to a single, giant repository for all of our needs!

Larcus: What? Why would we do that?! It’s such a terrible idea to keep all your code in one place!

Mee: Don’t you think engineers at Facebook and Google are familiar with smaller repositories and still prefer a huge repo for:

Organization

If a group decides to use multiple repositories, it typically takes the form of a single project in each repository, or of a lot of related projects stuck together. This has actually caused problems in the past, where robot code depends on interchange, but it’d be weird to put interchange in with the robot code. Especially, this sort of organization means we must discuss what exactly describes a ‘project,’ and how do we group them? In a monorepo, it doesn’t matter; you don’t have to organize a project one way because you have to in order to maintain your logical groupings.

Switching projects and building a different one is usually as easy as cd; bazel build .... It’s very hard to get this sort of setup in a series of multiple repositories.

Dependencies

For those who worked on robot code last year, you may remember having to add json, or interchange, or whatever to a .xml file in order to get it to deploy to the robot. Then we have to make sure our version of the NavX library is at the right version, and that no one introduced a breaking change in interchange, etc etc.

Also from a selfish point of view, this way I can build controve/pion modularly and don’t have to build it all into a single, gigantic library to distribute. Think about it: Let’s say we build a web display for the RoboRIO, and want to use it across multiple years. Instead of having to pick a version number and use it as a dependency, we can continuously evolve the tool without having to copy paste code. Want a networking setup for Tegra? Add a few lines to a file. Want a camera to broadcast to the driver station? Few more lines. It’s much saner.

Yes, you could concievably make this kind of dependency management possible using maven, or whatever, but you end up with versioning issues. With a monorepo, HEAD will always point to a valid version, so you don’t have to pay attention to inter-team versioning.

Also, cross-project testing and searching is far easier in a single repository.

Changes across different projects

Let’s say you have an API. And this API is used by three of your projects. Say, in fact, that I want to rename a method from controve::Time::in_us() to controve::common::Time::in_us(). With a repository for each year of robot code, I’m screwed! It’ll take forever to hack together the sed commands or scripts to make this take less than 24 hours. With a monorepo, I can just use typical refactoring tools.

Consider this quote from David Turner, who worked on Twitter’s migration to a monorepo.

I needed to update [Project A], but to do that, I needed my colleague to fix one of its dependencies, [Project B]. The colleague, in turn, needed to fix [Project C]. If I had had to wait for C to do a release, and then B, before I could fix and deploy A, I might still be waiting. But since everything’s in one repo, my colleague could make his change and commit, and then I could immediately make my change.

I guess I could do that if everything were linked by git versions, but my colleague would still have had to do two commits. And there’s always the temptation to just pick a version and “stabilize” (meaning, stagnate). That’s fine if you just have one project, but when you have a web of projects with interdependencies, it’s not so good.

[In the other direction,] Forcing dependees to update is actually another benefit of a monorepo.

Tracking projects is much easier too, as tools such as git bisect do not typically work usually across multiple repos, and contributors must rigorously follow some meta regulation to maintain sanity.

Larcus: exit scene right, goosestepping


Today, I almost talked about Bazel. In the next post, I’ll actually talk about Bazel.