Continuous Integration With GitHub Actions

Github actions allow you to start workflows triggered by events like pushing, issue creation, or new releases. One super common thing they allow you to do is build and test your code using hosted runners (or local runners if you prefer) whenever you push code to your remote repository, and then display a pretty badge indicating the status of those workflows.

As David Scott Bernstein puts it in Beyond Legacy Code, “If software is to be used it will need to be changed, so it must be written to be changeable.” And whats the best way to make sure you haven’t broken everything by changing your code? You got it, automated unit and integration tests. Bernstein in fact dedicates nearly half of Beyond Legacy Code to the notions of continuous integration and testing with 4 of his 9 practices to avoid creating legacy code being “Integrate Continuously”, “Write the Test First”, “Specify Behaviors With Tests” and “Refactor Legacy Code”.

Let’s Make a Workflow!

Let’s use my super simple simple_example_projects repo as the example here, where I’ve already created some pretty basic gtests for the TicTacToe game. To create a new workflow, simply head over to the “Actions” tab, and click “New Workflow”.

I then chose the “C/C++ with Make” starter workflow, under the “Continuous integration workflows” heading as my starting point. This gives you a basic boilerplate YAML file to start your action from.

This will then show you a YAML that’s populated like this:

We’ll go ahead and modify it a bit so that we’re installing gtest every time a runner kicks off:

You don’t need to see all the implementation details since you can just go right to my github to take a look at it, but what we’ve done is named this particular action “Unit Tests”, told it to execute when we push to main or submit a pull request to main, that it runs on ubuntu-latest, and then specified 4 individual steps for it to perform:

  1. Install gtest manually
  2. Configure (invokes cmake)
  3. make
  4. Run tests

These are the names that are used when you check on your workflow status.

You can then easily expand each of these items to see what occurred and what the output was:

Finally, adding those fancy badges is as simple as going to your README.md file and inserting the following:

![CMake and Test](https://github.com/EVictorson/simple_example_projects/actions/workflows/cmake.yml/badge.svg)

The thing to note here is the pattern that should be used for displaying your badge:
![<name_to_be_displayed](https://github/com/<user_name>/<repo_name>/actions/workflows/<workflow_file_name>/badge.svg

You can also use some of the fancy generated badges that Shields provides, as I’ve done in my repo (and you can see in my README file).

And there you have it! A fast, easy way to provide automated builds using a remote server provided by Github.

Billing for GitHub Actions

One final thing to note is that GitHub Actions usage is free for both public repositories and self-hosted runners, at least at the time of writing this as per here. For private repositories, each GitHub account receives a certain amount of free minutes and storage, depending on the product used with the account. To see how long your actions are taking, simply take a look at your workflows page:

If you are using GitHub Free you’ll be allowed 500MB of storage and 2,000 minutes per month, whereas if you’re using Pro or Team, you’ll be afforded 1 GB of storage and 3,000 minutes per month.

One final gotcha is that jobs run on Windows and macOS runners that GitHub hosts consume minutes at 2 and 10 times the rate that jobs on Linux runners consume. So, if you using 1,000 Windows minutes you will have consumed 2,000 of your allotted minutes, if you use 1,000 macOS minutes, you will have consumed 10,000 of your allotted minutes.

If you go over your allocated minutes in a month they’ll start charging you extra (if you’ve allowed for this, by default it’s disabled unless you pay by invoice), but the price is relatively low (0.8 cents per minute on Linux) and the allowed minutes for most users is higher than they’d need unless they’re in a professional setting.