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
bash
npx actions-toolkit release-reaction
This will ask you for an action name, description, icon and colour:
bash
โ 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.
javascript
const { Toolkit } = require("actions-toolkit");Toolkit.run(async (tools) => {// Add code here},{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:
javascript
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
.
javascript
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):
javascript
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:
javascript
if (action == "deleted") {tools.exit.success("โ ๏ธ Release Deleted");}
Then finally, we handle any other actions that we don't explicitly look for. In version 1 of GitHub Actions we could 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. Here's how it used to work:
Using
neutral
behaved the same asfailure
- it stopped all running actions and did 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.
However, as of version 2 of GitHub Actions the neutral
concept no longer exists. With this in mind, let's log a warning using tools.log.warn
and allow the action to exit successfully.
javascript
tools.log.warn("โ ๏ธ Unknown action: " + action);
If we wanted to conditionally execute the next step, we could set an
output
in this action and use anif
statement in the next step to check if it has been set.
Putting it all together, our action looks like the following:
javascript
const { Toolkit } = require("actions-toolkit");Toolkit.run(async (tools) => {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.log.warn("โ ๏ธ Unknown action: " + action);},{event: ["release"],});
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/workflows/release.yml
with the following contents:
yaml
name: Release Statuson: releasejobs:release:name: Releaseruns-on: ubuntu-lateststeps:- name: Show Release Statususes: ./
Once that's done, create a file at /tmp/event.json with the following data:
javascript
{"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.
bash
$ 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
.