Creating a GitHub Action for triggering Boomerang Flow workflows

Boomerang Flow is typically aimed at no-code to low-code users with a visually beautiful drag-and-drop workflow editor. In some scenarios, you may want to trigger one of these workflows from a developer focussed starting point, in this case, GitHub.

This would be useful if there is a business process with approvals and integrations that needed to be handled by product or executive users that might feel more comfortable modeling the business process in such a visual tool.

We could trigger from a GitHub app but in this case, let's have a bit of fun and trigger as a step in a GitHub Action using CloudEvents.

Creating the Code

As Boomerang Flow accepts CloudEvents to trigger Workflows we will write a simple NodeJS function using the CloudEvents SDK to send an event and take dynamic inputs through environment variables.

To do this quickly, I utilized the Boomerang Flow Task creation npx utility

npx @boomerang-io/worker-cli init

This generates a simple folder structure, NodeJS CLI scaffolding, initial dependencies, and an initialized git repository.

I then went about craft the cloudevent object following the Boomerang Flow eventing documentation

const event = new CloudEvent({
subject: "/" + workflowId + "/" + topic,
type: "io.boomerang.eventing.custom",
source: "/github/action",
datacontenttype: "application/json",
data: JSON.stringify(payload),
});

Throwing in a simple process.env reference to get access to the Action input

const {
FLOW_URL: url,
FLOW_TOKEN: token,
FLOW_WORKFLOW_ID: workflowId,
FLOW_TOPIC: topic,
FLOW_PAYLOAD: payload,
} = process.env;

The CloudEvents SDK has a great method for creating a structured HTTP event, then add in an Authorization header and use node-fetch and DONE!

const binaryMessage = HTTP.structured(event);const requestHeaders = { ...binaryMessage.headers, ...{ Authorization: token } };const requestConfig = {
method: "PUT",
body: binaryMessage.body,
headers: requestHeaders,
};
try {
await fetch(url, requestConfig);
} catch (e) {
log.err(e);
process.exit(1);
}

We now have a very simple function that utilizes a structured data format to trigger a workflow

Defining the GitHub Action

Next up is defining the action and GitHub makes this reasonably straight forward and easy, if you do this in the GitHub Web UI it even provides contextual prompts as to what objects are allowed in the YAML definition.

It is also good to note, that if you are familiar with Tekton or other Kubernetes CRD based objects, there is less boiler plate required.

Although I do highly recommend reading these two sections of the GitHub Actions documentation
- Creating a Docker container action
- Metadata syntax for GitHub Actions

We know the inputs and environment variables based on the NodeJS function. We also will run this as a Docker container as a simple but effective cross platform execution method… this same container could run as a Tekton Task. You also get to have a bit of fun with the ‘branding’.

name: Boomerang Flow Run Workflow
description: Trigger a workflow to execute
author: 'Boomerang'
branding:
icon: play-circle
color: blue
inputs:
url:
description: The Boomerang Flow event URL and context
required: true
token:
description: The security token as part of your workflow
required: true
workflowId:
description: The ID of the workflow you wish to execute
required: true
topic:
description: The custom topic entered into your worlflow configuration
required: true
payload:
description: The JSON payload to send with the event
required: false
runs:
using: 'docker'
image: 'docker://boomerangio/flow.action:latest'
args:
- flow
- run
env:
FLOW_URL: ${{ inputs.url }}
FLOW_TOKEN: ${{ inputs.token }}
FLOW_WORKFLOW_ID: ${{ inputs.workflowId }}
FLOW_TOPIC: ${{ inputs.topic }}
FLOW_PAYLOAD: ${{ inputs.payload }}

Once this is committed, we do need to publish a release and it seems to be pretty standard to do a vX.Y.Z format.

Bringing it together

I created a simple Boomerang Flow workflow to send a Slack message. Obviously we would want to make this a bit more complex, potentially introduce approvals and other business related process steps.

Boomerang Flow workflow editor

I created a new GitHub repository, navigated to the Actions tab, and searched for our new Boomerang Flow Action in the marketplace. Added in the required details and took advantage of the powerful secrets substition for providing the token. Having this stored with the repository or organization is an amazingly simple and effective security mechanism.

name: flow
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
automate:
runs-on: ubuntu-latest
steps:
- name: Boomerang Flow Run Workflow
uses: boomerang-io/flow.action@v0.5.2
with:
url: ${{ secrets.FLOW_URL }}
token: ${{ secrets.FLOW_TOKEN }}
workflowId: ${{ secrets.FLOW_WORKFLOW_ID }}
topic: github
#payload: # optional

It took a few goes to get going and then we successfuly had the workflow triggered.

A Catch

A stumbling block when creating container based actions is that by default Actions will override the working directory

--workdir /github/workspace: it sets the working directory of the container

This meant that our NodeJS function was failed to run due not being able to find the package.json. Its easy to fix, all you need to do is add the npm --prefix flag, in our case that became

ENTRYPOINT [ "npm", "--prefix", "/cli", "start" ]

Summary

End to end it took about 3 hours as a first time GitHub Actions creator to have a published re-usable Action on the marketplace that sends a CloudEvent to Boomerang Flow and triggers a workflow.

Now all we need to do is drag and drop Tasks to create a more complex representation of our business processes.

Show your support

Thanks for reading! If you made it this far, show your support if this helped you:
- ⭐️ the GitHub repository
- 💬 Follow us on Twitter
- Install the project on your own Kubernetes cluster
- 🙏 Join us and help contribute

--

--

--

A software engineer and automation enthusiast, made in Australia, Ex New Yorker.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Everything you need to know about RxJS 6+

RxJS

Writing Defensive Javascript

Classless State via Hooks

A shimmery blue and purple metal fishing lure with several hooks hanging from it is being held up close to the camera by a somewhat out of focus  white bearded male wearing a green jacket with a black and yellow plaid shirt underneath.

Absolute Simplest Node.js Debugging — VSCode/DevTools

How to make custom Mixin(Plugin) in CesiumJS

Being a dumbass is a human right — Part 2

Creating React App locally

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store

Tyson Lawrie

A software engineer and automation enthusiast, made in Australia, Ex New Yorker.

More from Medium

Custom Lenses for the AWS Well-Architected Tool

Github Actions + Slack : Automated Slack Notifications using Github Actions

OAuth2.0 and OpenID

Product Comparison: TeamCode Pylon VS Docker Dev Environment