At Mobingi, we’ve been using a single repository (monorepo) to organize mainly our Go-based code, which we fondly call ouchan, for about a year now. I actually uploaded a stripped down version of this repository here as reference. It is stripped down in a sense that it uses a more straightforward script compared to our build tool which, over the months, has been customized for our CI/CD pipeline.
We actually started with two main repositories, backend API (written in PHP) and frontend (JS). These stacks were deployed to AWS using Mobingi ALM (yes, we are also users of our own product). As we added more features, our backend, predictably, became what you essentially call a monolith, handling things like authentication, authorization, notifications, etc, on top of our main business logic. As more and more engineers came in, contributions and changes to the main codebase became a bit of a problem. And so we went with the microservices route.
It was also at this time that we started to write our new services in Go. Rewriting the PHP codebase to Go was out of the question though because our backend was actually relatively stable. Also, supporting two backend languages was good for us from recruitment perspective. So new services came and went as we scaled up and added/updated new features. The number of repos we had rose significantly as well.
Then we started adopting Kubernetes. If you noticed, the image’s (above) description says “…mochi services.” Mochi is what we call our k8s-based clusters which I will probably talk about in a separate post. Anyway, that meant an ocean of repos were needed to be updated to have their CI be able to deploy to mochi. This is when we decided to try and use a monorepo. Mainly to ease mochi deployment.
We actually started ouchan with Bazel as the build system but we felt it was too complicated for our setup. Ouchan’s build system is fairly simple compared to Bazel although we are not closing our doors to Bazel especially that at the moment, adding more languages to ouchan is an ongoing discussion.
So, ouchan. It uses CircleCI with two build containers ($50/month), each container configured to build more than one service concurrently. Ouchan only builds services that are modified in a commit. If the updated codes are under pkg
and/or vendor
, ouchan can also determine the affected services and build those as well. All built services are automatically deployed to mochi. It also supports Slack notifications and is fairly configurable.
At the moment, ouchan is basically Go-centric. PHP-based services (separate repos) are integrated into ouchan by having their own “service” entries, basically just a folder with a Dockerfile, a Makefile, and a deployment script, and some optional support files, if any. Their build flow is a two-step process: 1) commits to a repo will trigger that repo’s own CI (units tests, etc.) and trigger an ouchan build; 2) ouchan kicks a build for that particular service, and deploy that service to mochi.
So far, ouchan is working brilliantly for us although there is still room for improvements. We are also planning to open source it as well if time permits. I would also like to mention that we also have a lot of repos that are not integrated to ouchan: AWS Lambda repos, repos that are using Mobingi ALM (we have a lot of these), etc. but we will talk about them in a separate post.
Thanks for reading. See you in the next post.
Best,
@flowerinthenight
Head of Engineering
For any comments, questions, or feedback, please reach out to us @MobingiTech.