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
handleOpenedPr(tools)
}
if (tools.context.payload.action == "labeled") {
// Some logic for labelled PRs
handleLabels(tools)
}
handleAnyPrEvent(tools)
}
// But we also want the label functionality to work for issues
if (
tools.context.event == "issue" &&
tools.context.payload.action == "labeled"
) {
handleLabels(tools)
}
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:
router(
{
"issue.labeled": [handleLabels],
"pull_request.opened": [handleOpenedPr],
"pull_request.labeled": [handleLabels],
pull_request: [handleAnyPrEvent],
},
[tools]
)
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.
router({
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`
console.log(results)
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
Top comments (0)