A real-time game from scratch - CI/CD [5]
March 15, 2021
Previous Entries
Introduction
Up until now, the development of Cabin Fever has all happened on my personal machine, running on localhost. Showing a demo to someone either involves physical proximity to demo it (which is not a good idea given the ongoing pandemic) or recording a video and uploading it to YouTube.
Alternatively, I could push both the back-end and front-end to a server or VPS and allow potentially anyone on the internet to try it out.
By the end of this article, my aim is to have automated the full process of building the software and pushing it out to the server, rather than having to perform those steps manually. I will be applying the DevOos discipline of CI/CD to achieve this.
CI & CD
CI and CD here refer to the following:
- Continuous Integration
- Continuous Deployment
Continuous Integration
Whenever anyone wants to work on a piece of code, it is a good idea to keep track of the changes using a Version Control System (VCS) such as git. This is software which allows us to keep different versions of the same code, switch between these versions and even bring different versions together.
The idea behind Continuous Integration is to automate checks and balances that the differences between our different version (or branch as git calls it) are still compatible with the original version we branched off from and that the logic of our application still behaves as expected.
In our case, it would involve the following steps:
- Check that the code is still valid and can be compiled.
- Run automated tests to ensure our code still implements our logic as we expect it to.
The result of this process will either be a compiled binary, ready to be used/deployed, which means we have successfully integrated our code changes. Doing this continuously avoids large changes from piling up which increases the risk of the process failing. By automating it, we take the tedium and human element out of it.
If any of the above steps fail then we should expect some sort of report stating why. This could be that our integration failed, or our new code changes cannot be compiled, or even that some of the tests failed. It is more ideal for us to catch these issues at integration stage rather than when we have already pushed the code out to our production environment.
I plan on tackling the Continuous Deployment part in a future article
DevOps before it was cool
I like to say I did DevOps before DevOps was cool. I’m a DevOps Hipster if you will.
I started my first internship a whole month before the other students. This is because my exams finished sooner and rather than sit and stare at home, the company too me in anyway.
On one of my first days, the Technical Architect outlined one of my first tasks: “Take this thing called Jenkins and link it to this thing called GitLab”. Being a very green programmer, this was my kind of challenge: no idea what I’m doing and no idea where to start from! Nowadays this task takes maybe ten minutes to complete, but circa 5-6 years ago it was not as trivial.
Jenkins
Jenkins is the automation software that the company was using for its Continuous Integration. I decided to use Jenkins again for Cabin Fever as I had already revisited it as I was improving my DevOps skills. I was pleasently happy to find Jenkins had become more versatile over these past several years along with still being as usable as the day I first used it.
Jenkinsfile
The Jenkinsfile is a file describing the pipeline of automated steps that we want to perform. In this case, we would want to perform the following:
- Build and package the server binary
- Build a production bundle of the frontend
- (In the next article): deploy the server and the frontend to a server accessible by our players
Focusing on the first two steps were not particularly difficult as I had setup similar pipelines in the past. It involved:
- Starting up a docker container containing the build tools I require (for the server: GoLang and for the frontend: NodeJS)
- Running the tests against the built code (if there are any)
- Running a command to build the code
- Archiving the resulting binary/bundle for later use
I involved docker to keep my builds isolated and repeatable. This means that they do not rely on having toolchains present or configured on the machine that Jenkins is installed on, making it easier to reproduce even if I had to run my Jenkins on another machine.
Conclusion
It took some back and forth because I tried running the server compilation within an alpine image, but after eight attempts I finally completed the Jenkinsfile, meaning I can now build all of Cabin Fever on my personal Jenkins server after every push to the git repository.
Right now the assets are just sitting there, archived within Jenkins, so they aren’t particularly useful. My next article will focus on the Continuous Deployment part - the aim being deploying the latest version of Cabin Fever to my personal server using Jenkins to enable quick playtesting without always running it on my development machine.
Next Entry