Action Router
javascript
router({pull_request: [require("./allPr")],"pull_request.opened": [handleOpenedPr],"pull_request.labeled": [(tools) => {tools.github.removeLabel({ owner, repo, name });},],});
Context
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:
javascript
// We're working with PRsif (tools.context.event == "pull_request") {if (tools.context.payload.action == "opened") {// Some logic for opened PRshandleOpenedPr(tools);}if (tools.context.payload.action == "labeled") {// Some logic for labelled PRshandleLabels(tools);}handleAnyPrEvent(tools);}// But we also want the label functionality to work for issuesif (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:
javascript
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.
javascript
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:
javascript
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