Introducing Action Router

Handle multiple event types in a single GitHub Action by routing using GITHUB_EVENT_NAME and the payload action

If you’re building a GitHub Action that contains multiple triggers that have slightly different actions, you may find yourself writing code that looks like the following:

// We're working with PRs
if (tools.context.event == "pull_request") {
  if (tools.context.payload.action == "opened") {
    // Some logic for opened PRs
  if (tools.context.payload.action == "labeled") {
    // Some logic for labelled PRs


// But we also want the label functionality to work for issues
if (
  tools.context.event == "issue" &&
  tools.context.payload.action == "labeled"
) {

After I found myself writing code like the above repeatedly, I realised that what my more complex actions were missing was a router. Something to work out what the event type and subtype are and delegate to another method. I ended up building action-router which allows you to do the following:

    "issue.labeled": [handleLabels],
    "pull_request.opened": [handleOpenedPr],
    "pull_request.labeled": [handleLabels],
    pull_request: [handleAnyPrEvent],

The router expects anything that’s callable, which means that so long as it can be called as a function you can require the code, define functions in the same file or even pass anonymous functions directly.

  pull_request: [require("./allPr")],
  "pull_request.opened": [handleOpenedPr],
  "pull_request.labeled": [
    tools => {
      tools.github.removeLabel({ owner, repo, name })

All of the methods that match the event type and subtype are run concurrently. This means that in the first router example both handleOpenedPr and handleAnyPrEvent would run together whenever a pull_request is opened. The results of these methods are returned as an array of promises, which means you can run the following:

const results = await router({
  "issue.labeled": [handleLabels],

// Results is an array of results. results[0] will be the return value of `handleLabels`

I’ve used the router in anger on a few actions now and it’s definitely reducing the amount of boilerplate code I’m writing. If you’re interested in giving it a go, installation and usage instructions are available on GitHub

May 03, 2020


Want to learn how to build your own GitHub Actions?

Get The Book