A couple weeks ago I got a coveted invitation into the GitHub Actions beta. It looks extremely impressive, and seem to boil down to one fundamental principle:

You can do anything by chaining different Docker containers together.

Really, that's about it. Though, given the sparse documentation so far, I haven't quite figured out how much to make of it just yet.

So far I've been focusing on trying out the sort of standard CI/CD workflow, i.e.:

  • When code is pushed, build it and run tests.
  • When code is pushed to the master branch, once it passes all tests, deploy it.

GitHub Actions uses a .workflow file to define the workflow which uses HashiCorp Configuration Language (HCL), but GitHub also provide a visual editor, and you can drag-and-drop to create links between tasks.

There's not much documentation so far on the standard tasks, so I've had to dig into the implementation of the existing (open-source) ones to figure out how to use them.

Launching a Workflow

Workflows run when certain events happen. I don't quite know what they are because the UI only provides programmatic names, not readable names, but at a guess I'd reckon they map over to the WebHook documentation.

(Initially, for public repositories, only the push event is supported. More events are supported on private repositories.)

Editing a Workflow definition in GitHub Actions

There doesn't currently seem to be a way to manually run a workflow, or retry a failed one.

Constructing a Workflow

Workflows are constructed from a series of tasks or actions, which each represent an individual Docker container. For example, to create and publish a Docker container, my workflow consists of 5 actions:

  • Build a container using the "GitHub Action for Docker" action, which wraps Docker itself.
  • Exit if we're on a branch other than master, otherwise continue. (Yes, a simple if condition is an action unto itself, and is actually handled by running an entire container.)
  • Tag the new container with the commit ID and branch name.
  • Log in to Docker Hub
  • Push my new container to Docker Hub

Each of these actions are performed in their own container (most using Docker-in-Docker) and have individual logs. The visual editor makes this quite clear, when providing parameters you can only supply:

  • Environment variables
  • Secrets - environment variables with encrypted values
  • An option to override the original Dockerfile's ENTRYPOINT
  • An option to override the original Dockerfile's CMD.
Configuring a GitHub Action

Creating a custom Action

Since actions are just containers, all you need to do is supply a Docker container, and GitHub can run it a part of a workflow to do whatever you want it to do. There are several custom labels that GitHub wants from your Dockerfile, but otherwise it's fairly straightforward:

LABEL "com.github.actions.name"=".NET Core Test Runner"
LABEL "com.github.actions.description"="Builds a repository and runs tests for .NET Core"
LABEL "com.github.actions.icon"="terminal"
LABEL "com.github.actions.color"="purple"

LABEL "repository"="https://github.com/yaakov-h/github-action-dotnet-test"
LABEL "homepage"="https://github.com/yaakov-h/github-action-dotnet-test"
LABEL "maintainer"="Yaakov <git@yaakov.online>"

This is an example from a test one that I put together. I haven't found a full list of icon names or color names and have had to scrounge around and look at existing implementations to find possible values.

Once you push your custom container to a registry, you can then use it by providing a custom URI to your container:

Configuring a custom GitHub Action

I believe you can also use a container defined within the current repository - I've seen the option for it in the UI, but haven't tried it yet. When this option did show up in the UI, it had the correct colour and icon, too.


So far it's quite good.

Unfortunately, the consistency is extremely eventual. Immediately after creating your first workflow definition, the Actions tab will still say "hey you have no actions why not try creating one" for a good couple minutes. Similarly, when an Action starts, the tab says "hey there was a problem starting this workflow, your definition might be invalid" until the action actually kicks off.

Another issue is the lack of clear documentation. I've had to look into the implementations of several containers to figure out which arguments I need to provide, and I cannot find any documentation for some things like what icons are available for custom definitions.

I'm also not quite sure how to test a new workflow before committing it to master. I'll have to try a Pull Request and see if it uses the PR branch's workflow or the master branch's version.


Issues aside, it seems to work quite well. I haven't had any fundamental problems, and in my experimenting so far it's even picked up when I had a bunch of unit test failures on my playground site.

A GitHub Actions workflow failure due to failing unit tests

I also haven't figured out if/how I can publish summaries, like which unit tests failed, or extract build errors from a much longer log.

The only fundamental part that I know I do not know, is persistent state. If one container generates output - a compiled binary, a minified Javascript file, or a Docker container, for example - how does a subsequent container find and load that resource? I haven't figured this part out just yet.

I'm not sure I'd give up on AppVeyor or Travis just yet, but GitHub Actions is highly composable and no doubt has a bright future ahead of it.