Getting started with Github Actions

A while back, Github announced Github Actions, which is a containerised platform for running things when you do something in Github, like make a PR, comment, etc.

On the surface, it looks like a very nice wrapper over the top of their existing web-hook apis, with container execution infrastructure for free. Oh, and a library of existing stuff you can use.

I signed up for the beta, and eventually got in, only to find that it was private repos only - and I couldn't make them (I can now). Today, I came across @jessfraz (Jessie Frazelle) blog post on The Life of a Github Action, which is a nice, small, understandable introduction to making a small Action. I decided to use my ferry ride to look into it again. But....

Eventually, the docs came back up (Thanks Jess and Brendan)

My goal for this is to scratch a small itch we have at work. We tag PRs with ready for review when they are ready, and a webhook look at that, and posts it off into Slack for us, someone sees it, reviews it, and then does the PR approval flow to approve it, and finally, marks it as ready to land.

We used to just do the last bit, before approvals arrived. Now we have to do both. It's only one more click, but it's also difficult to do on mobile, and we have a few bits which trigger off that flag being set.

So, I started hacking on it. The actual function is quite simple, and I've included the code below (until I make the repo public), but here's some of the issues I hit, which might be in the docs.... which I couldn't read.

The action. Not exactly complicated.

First, you can have actions locally. I thought I had to refer to another public repository, or initially, a docker registry. But no, you can have it in the same repo, which is awesome.

action "tag on approve" {
    uses = "./tag-on-review/" <--- this is local to my project
    secrets = ["GITHUB_TOKEN"]
}
.github/
  main.workflow

tag-on-review/
  Dockerfile
  tag-on-review.sh

I was using a PR as a test, but committing to master for the workflow and container. It took a few goes to realise that the workflow which was being executed is the one inside the branch!

So Protip: Use another repo for your workflow actions, not the local one. Then you can tie it to a specific branch with uses = "nicwise/my-action@master" and not have this problem. Downside is, the repo has to be public. I really hope I can have a mono-repo for these, I don't want a repo with just one shell script and a Dockerfile.

There is a bit in the workflow which talks about the GITHUB_TOKEN, which is marked as a secret. Actions provides secret management (awesome!) so I was expecting to have to set this - but this one appears to be a special case, and it's just injected in. Nice.

action "tag on approve" {
    uses = "./tag-on-review/"
    secrets = ["GITHUB_TOKEN"] <-- special unicorn. 
# If you make your own, you need to add them into the UI in Settings -> Secrets
}

The content of the event is provided for you. You don't get a URL, it's just a local file - all very concourse-y, which is good. You can then just run jq over it to get stuff out, if you are using bash. Otherwise, pick your preferred Json parser.

action=$(jq --raw-output .action "$GITHUB_EVENT_PATH")
pr_url=$(jq --raw-output .pull_request.url "$GITHUB_EVENT_PATH")

Another snag I hit was that I was testing the approvals action, and I can't approve my own work, so I had to make another account to approve it. Would be nice to have a flag saying "can approve own work", even if it's off by default, and has a big warning. Maybe it is there if I paid Github some money.

Overall, it was really easy, and now I need to think of other things to use Actions for.

One of the main missing bits I'd like to know - it might be there - is how I'd apply this to all (or a wide subset) of our repos without putting a main.workflow in each one, and having to maintain it - could I apply it at the org level somehow? Sort of like how webhooks are also done at an org level.

This is also quite many-repo specific. We tend to use a mono-repo pattern (one repo with many services, in their own folders). We could have a load of .workflow files, and just check the path in a starting step, but still, it would be nice to be able to iterate down N levels (N = 2 for us - services/NAME/.github would do) and have changes below there, trigger just those workflows.


The code for this is on github nicwise/actions-test. Most of it is bastardised off Jess' blog post, so I can't really claim much originality on it.

Nic Wise

Nic Wise

Auckland, NZ