Jake Rowsell

Github Actions: The end of dedicated CI?

February 08, 2021

Full disclosure, I've not used all the modern CI tools out there. My experience is limited to Jenkins, Circle CI, GoCD and now Github Actions (GHA). My ideas may be based on ignorance and incomplete knowledge of the CI landscape.

For as long as I can remember using CI/CD tools, I remember them being awkward to use. This experience may be colored by the amount of GoCD I've used (Do not try this at home, kids). Resource contention, agents having the wrong/no version of a required dependency installed, resources being generated as route and the agent not being able to clean up its workspace for the next build. You get the picture, and you may be thinking "a lot of this could be avoided by good CI/CD practices. I agree, but would counter that by design some tools make it easier or harder to make poor decisions when setting up a CI/CD process.

I'm a big fan of Infrastructure as code, and by extension pipelines of code. While working in a larger team we had issues with people changing pipelines (or shared templates) and causing problems for others. Having these changes go through Version Control Software means people can scrutinize changes, there is accountability for the changes and most importantly changes are visible. At the same time, the approach GoCD takes puts so much in code that it includes environment variables and secrets. You end up needing to raise a PR to be able to change an environment variable, which goes against the 12 Factor app approach of separating config from code.

By comparison, I like what Jenkins does much better. A Jenkinsfile as code, but with the ability to change environment variables on the Jenkins server. This is similar to what Github does with Github Actions.

What I dislike about Jenkins is managing a plethora of plugins, which seems to be going out of date on a daily basis. Add to that Jenkins needs to be updated and not all versions of plugins and Jenkins work together.

Circle CI on the other hand defines a workflow that references jobs, that consist of a docker container and steps to run inside that. For example, you have a job "build" that references a node Docker image, and the steps may be to run "npm install" and "npm run build". No plugins but Docker images and a config file to define all the steps, nice.

GHA takes a similar approach, but instead of Docker images you can reference existing Actions. Actions are very specific libraries, e.g. "setup-node" makes NodeJS available. It's easy, really easy. It took me about 15 minutes to set up an action to build a bundle and put it in an S3 bucket. This included merging 2 existing actions and debugging mistakes I'd introduced.

Both Circle CI and GHA benefit from being a managed service. If you had asked me a few years ago if I'd go for self-managed or managed service I don't think a managed service would have been my choice for anything. That's no longer my view, and especially in my experience with CI I'd strongly advocate going managed. As previously mentioned, resource contention goes out of the window in a properly isolated environment. It also means you are forced by design to properly declare and isolate dependencies (12 Factor app, we meet again). You don't even have the ability to install jq on your agent as you might in GoCD. If you want to use it, you'd need to add it into a custom Docker container (Circle CI) or you will need to pull in an action that makes it available.

Another benefit of using a managed service is not needing to run dedicated instances. Have I mentioned Circle CI and GHA have a free tier? Okay, maybe that's cool for personal projects, but I'd definitely suggest doing a bit of cost analysis if you have a choice for your team at work. Additionally, I'd estimate conservatively spending at least 5% of my time at work fighting preventable pipeline problems. Going managed will eradicate a whole class of problems. For the record, Circle CI is not giving me commission for writing this post.

Can we start calling it.. deadicated CI? Should I unplug my Jenkins Plugin collection? Maybe that's a bit premature, after all migration itself has a cost. But definitely make sure you give managed CI, and specifically Github Actions a try. My biggest takeaway was that CI can be a pleasant experience.

I'm also approaching this from a fairly simple perspective, generally code I've worked on involves fairly small, self-contained Node Microservices. Github Actions don't look to me like they'd be great for large multi-stage builds. As they are tied to a repository, multi-source builds may also not be suitable.

In conclusion for building a new project I'd strongly advise to use Github actions. Migrating everything over is probably not worth your time, unless your pipelines are giving you a lot of grief. Jenkins is probably still useful for big multi-stage build pipelines. But hopefully this is the end of GoCD.