This weekend I started to go back and look at a few projects of mine. A few years ago I setup most of those using a mix of Travis CI for building/testing, docker hub for image building/hosting and then somehow wiring this all together with a custom stack. Today this feels outdated and overly complex. As an SRE I’m allergic to complexity. So I spent a few hours checking out the new Github packages and actions.
Pricing
Both packages and actions come with a unlimited option for open source projects and a nice free tier for private repositories. For actions you get 2000 build minutes per month. For packages 500MB in storage is included. There is more fine print for data transfer but that seems really generous and will mostly suffice for any small to medium size project. (Don’t mine bitcoin in the Github actions runner please :-D)
Setup
Github has a somewhat unfair advantage here: their stuff is build right into the UI. But that is exactly why its nice. Github has been amazing at creating clear and understandable user interfaces. Compare to the mess that docker hub is, I can only applaud them for a job well done.
To get started, there is nothing else to do, than write a simple workflow file. If you already have your docker file setup, this can be enabled within 2 minutes. For my CalendarProxy project (written in PHP) I actually created two separate workflows. One for any pull requests to master and one for actual commits on master. First lets take a look at the build file for the pull requests:
name: CI
on:
pull_request:
branches: master
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
- name: Run test suite
run: composer test
The on pull_request
section is the part when this code should trigger. So any time a pull request is targeting the master branch it runs all the jobs defined below. Jobs usually run in parallel and execute independently. This is nice to speed up your build times and run checks faster.
Inside the jobs
section we can see the test
section, which is just the name of that particular build step. runs-on
specifies which host system os to use. This shouldn’t really matter in most cases, but Github offers Ubuntu, macOS and Windows. This is somewhat amazing, as in the past getting macOS runners for TravisCI was not part of the free plan. So building iOS apps was not possible. How can all of this be free? Amazing!
The steps
sections defines individual commands for this build. Its very similar to what we all already know from other CI configurations. There is one difference though which just amazes me: the uses
keyword. This is kind of a plugin architecture, where you can reuse build steps that might be more complex. The actions/checkout@v2
step is basically a “update the repo with the version that we currently want to test” build instruction. Check out the full source code of the action here.
I remember this to be a much more involved thing previously, where you would get a tag/branch name and would manually somehow construct the right git command to get the right repo setup. These actions are a superbly good selling point, as it makes it way easier to build complex pipelines quickly. Bitbucket pipelines have something similar called pipes but when I tried them about a year ago it felt much more complex to configure them correctly.
The rest of the above steps install dependencies, do some basic validation and run the test suite. That is enough to reason, if there are any breaking changes hopefully.
The other workflow I have configured gets triggered, whenever there is a push / merge onto the master branch:
name: CI
on:
push:
branches: master
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v1
- name: Build and push Docker images
uses: docker/build-push-action@v1.1.0
with:
username: ${{ github.actor }}
password: ${{ github.token }}
registry: docker.pkg.github.com
repository: tum-dev/calendarproxy/server
tags: latest
tag_with_ref: true
tag_with_sha: true
add_git_labels: true
Here I use the docker/build-push-action@v1.1.0
action to do all the steps to build and publish the docker image. Again, the action is separate code configured here. Take a look, cause its ridiculously easy to create such actions. The action has a few nice parameters that you can read about here.
One thing that amazed me here: using the default provided env variables in the github
array we don’t need anything else to push to the Github integrated docker repository. No secrets to configure, no nothing. Its that easy.
Outlook
I think Microsoft and Github are doing a great job. The vendor lock in here is getting super strong and not labeling anything here Azure is a good idea to keep away people that dislike it or had bad experiences. These actions and the integrated docker repository make it absolutely easy to do basic CI.
At this point in time there is no excuse to not use such setups for your systems. Anyone still doing git pull
in a random webserver folder should go ahead and automate their work right away. Don’t be lazy, instead go crazy with automation.
I’m interested in how we can make this even simpler. Especially the story around continues deployment and spinning up an environment for each pull request is still something that seems overly complex. I’d hope we figure out better solutions for this in the future. (No I shouldn’t be required to use kubernetes for this)