Create a Github Action using actions-toolkit

In this post we’re going to create a Github action that outputs an emoji when triggered by a release. It’ll output ๐ŸŽ‰ if a release is created, โ˜ ๏ธ if it’s deleted and โš ๏ธ if it’s any other action.

We’ll be using node to create this action as it allows me to make use of the excellent actions-toolkit.

Initialise your action

Instead of creating a Dockerfile manually and bootstrapping an application ourselves, we’re going to use actions-toolkit to run an interactive bootstrap process.

If you’re interested in how it works, there is a post on creating a Github Action with Docker

npx actions-toolkit release-reaction

This will ask you for an action name, description, icon and colour:

โ˜…  Welcome to actions-toolkit! Let's get started creating an action.

โ„น  Creating folder /private/tmp/release-reaction...
โœ” What is the name of your action? ยท Release Reaction
โœ” What is a short description of your action? ยท Output an emoji in the log, depending on if a release was published/unpublished/other

โœ” Choose an icon for your action. Visit https://feathericons.com for a visual reference. ยท bell
โœ” Choose a background color background color used in the visual workflow editor for your action. ยท blue

------------------------------------

โ„น  Creating package.json...
โ„น  Creating Dockerfile...
โ„น  Creating index.js...
โ„น  Creating index.test.js...

------------------------------------

โœ”  Done! Enjoy building your GitHub Action!
โ„น  Get started with:

cd release-reaction && npm install

Follow the instructions and change directory in to your new folder and run npm install.

Once that completes, edit index.js replace the existing contents with the following.

const { Toolkit } = require('actions-toolkit');

const tools = new Toolkit({
  event: ['release']
});

We require the actions-toolkit package and create a new instance of it to use in our action.

The event: ['release'] entry tells Toolkit that we’re expecting to be triggered on a release action and to exit with an error if we’re not. This prevents people from using incorrectly configured workflows.

Github provide an event.json file containing information about the event that triggered an action run. This file can be used to find out more information about the release, including the event action (created, deleted, published etc).

This information is made available by Toolkit in tools.context.payload. As we’re going to be checking the action a few times, let’s save it to a variable:

const action = tools.context.payload.action;

Our first error case is if action is not set. If this is the case, we want the action to exit with a failure. To do this, we can use the tools.exit.failure method which logs a message and then ends the process with an error code of 1.

if (!action) {
    tools.exit.failure('๐Ÿ˜ข No action found in the payload');
}

We’ll check for a success next. If the action is created then we’ll use the tools.exit.success method which logs and exits with an error code of 0 (no error):

if (action == 'created') {
    tools.exit.success('๐ŸŽ‰ New Release Created');
}

We also want to explicitly check for an action of deleted. We also use tools.exit.success here as although deletion is a negative action, it’s expected and we should acknowledge that:

if (action == 'deleted') {
    tools.exit.success('โ˜ ๏ธ Release Deleted');
}

Then finally, we handle any other actions that we don’t explicitly look for. We use tools.exit.neutral in this instance as it’s not a failure and it’s not a success, it’s just something we’re not interested in.

Using neutral behaves the same as failure – it will stop all running actions and not run any future actions in the current workflow. However, so long as there are no explicit failures then the workflow will be seen as successful.

tools.exit.neutral('โš ๏ธ Unknown action: ' + action);

Putting it all together, our action looks like the following:

const { Toolkit } = require('actions-toolkit');

const tools = new Toolkit({
  event: ['release']
});

const action = tools.context.payload.action;

if (!action) {
    tools.exit.failure('๐Ÿ˜ข No action found in the payload');
}

if (action == 'created') {
    tools.exit.success('๐ŸŽ‰ New Release Created');
}

if (action == 'deleted') {
    tools.exit.success('โ˜ ๏ธ Release Deleted');
}

tools.exit.neutral('โš ๏ธ Unknown action: ' + action);

Testing

You can test this workflow by creating Github releases, but there is an easier way thanks to act. Go and have a read of this post and continue reading once act is installed.

We’re going to be testing an action on our action itself, so we need to make sure it has a workflow defined in .github/main.workflow with the following contents:

workflow "Release" {
  on = "release"
  resolves = ["Release Status"]
}

action "Release Status" {
  uses = "./"
}

Once that’s done, create a file at /tmp/event.json with the following data:

{
    "action": "created",
    "release": {
        "name": "1.2.3",
        "body": "This is a test",
        "html_url": "https://example.com"
    },
    "repository": {
        "name": "Testing"
    }
}

This is a stripped down version of the release event JSON that Github provide (see complete example).

Run act release -e /tmp/event.json to trigger a release event using the fake event JSON payload that we’ve provided.

$ act release -e /tmp/event.json
[Release Status] docker build -t release-reaction:latest /tmp/release-reaction
[Release Status] docker run image=release-reaction:latest entrypoint=[] cmd=[]
โœ”  success   ๐ŸŽ‰ New Release Created

Congratulations! You just created and tested your first Github action using actions-toolkit.

Thoughts on this post

Leave a comment?