Our company is open sourcing Metroline, an in-house CI solution built with Docker, Node, React, MongoDB, Socket.io, D3 and TypeScript. It's self-hosted and works with Gitlab, Gitea and Github.
We're a small team of 2 devs. We have been using Gitlab and Gitlab CI for over 3 years now. We have since looked for alternatives several times with no luck, until a few weeks ago. We initially tried Drone but it doesn't support Gitlab sub-groups which is blocking for us. Gitlab CI is a great tool, but we have had issues with the cache system where we sometimes had to artifact
node_modules to get builds to work properly. In addition, it can be slow due to copying artifacts and preparing job workspaces.
A few months ago I started playing with Docker, Node and React to build a small CI proof of concept. The idea of making a CI myself was quite exciting and I felt driven by this feeling you get when everything comes to life. Surely was I even more excited when my proof of concept started actually working.
I wanted to write a CI that would run jobs inside Docker containers. This has become the standard for all CI platforms and has revolutionized how we build and ship code today. Big ups to Docker for changing our life for the better 👍.
A lot of popular Open Source projects use Go, Ruby, sometimes Node, PHP, etc. I'm a Node and JS fan all the way (I've used Java for 5 years but I'm just way too productive with JS), so the question wasn't really difficult. Plus, I wanted to practice React and keep the backend a pure ExpressJS app. MongoDB is my favorite DB and the integration overhead in Node is almost non-existant using their official driver. I actually haven't used an ORM at all, and it's just so much easier when the number of layers between your API call and the actual DB is low - but that's another story.
I wanted things to be live, so I went with Socket.io, their API is well designed and it's not too hard to get it right the first time.
CIs out there have a lot of ways to display jobs/pipelines. I wanted to be able to model a workflow without constraints (such as using stages in Gitlab CI). To model this, I've played around with D3. I've obtained some pretty good results, but I would love if one of you D3 masters out there can help enhance the graph we have.
After a few evenings and weekends writing the bare bones, I had something working. I could trigger jobs and see live logs.
I showed this to my business partner and we decided that I would work on this full time to get something we could use to replace Gitlab CI inside our company. It's a good learning experience and there are great technical challenges.
So I got to the task. Cleaned up the backend and the UI, added environment management, logging, security, Docker images, parallel jobs, secrets, branch protections, and more. I quickly split the backend into two: server + runner. I haven't worked on multi-machine setup yet, because cross-machine workspace management is still being analyzed, but you can already have multiple runners on the same machine.
I initially used Gitea because it was easy to develop with, but I quickly added Gitlab and Github support and structured the code so that it would be easy to extend to other Git servers (PRs welcome !).
The UI, server and runner as well as docs are all published on Github:
At this stage, the platform has all the features that we use in Gitlab CI, but there are a bunch of things we'd like to add, and plenty of improvements we'd love to make. We've got features planned for pipeline approvals, multi-machine runners, build badges, and a lot more. PRs, issues, questions, all is welcome and will be greatly appreciated.
And, if you ever happen to feel bored, have spare time, have already watched all the pictures of kittens available on the World Wide Web, and if you're so desperate to find something to do, then join us in the extraordinary boredom of writing Jest tests.
In the name of our humble team of two, I sincerely hope you enjoyed this post and that we'll be hearing from you. Let us know on twitter @metrolineio !