| Comments

I’ve been doing a lot of playing around with GitHub Actions lately.  GitHub has had access to repo activity via webhook capabilities for a while.  Actions basically gives similar capabilities in a DevOps flow on the repo itself, where the code for your ‘hook’ is an asset in the repo…using YAML configuration.  Recently an idea came up in one of our teams to provide better pro-active notification of certain types of Issues on our repos.  In GitHub, you can monitor activity in a few ways as a consumer: watching the repo and subscribing to a conversation.  In watching a repo you get a lot of noise of lots of notifications.  In subscribing to an Issue you can only do so after the issue is created and not notification when it is initially created.  What I wanted was simple: Notify me when an Issue is added to a repo that has been labeled as a breaking change.  So with that goal I set off to create this.

Creating the Action

Creating the action was simple.  I followed the great javascript-action template.  I recommend following the instructions in the template rather than the actual documentation as it is simpler to follow and more concise.  The cool thing about the template is you can click ‘Use this template’ and get a new repo for your action quickly:

actionstemplate1

I was able to configure my action quickly.  My goal was to accomplish the following things:

  • Look at an Issue
  • If the issue had a specific (or multiple) labels grab the content of the issue
  • Convert the contents from markdown to HTML and send an email to a set of folks

Actions are JavaScript apps and I was able to use two libraries to help me achieve this quickly: remarkable (to convert Markdown) and SendGrid (to email).  Aside from those you are able to use GitHub core SDKs to get access to the ‘context’ of what that Action is…well, acting upon.  In having this context, I can examine the payload and the specific Issue within that payload.  It looks something like this (relevant lines highlighted):

var core = require('@actions/core');
var github = require('@actions/github');
var sendgrid = require('@sendgrid/mail');
var moment = require('moment');
var Remarkable = require('remarkable').Remarkable;
var shouldNotify = false;

// most @actions toolkit packages have async methods
async function run() {
  try { 
    // set SendGrid API Key
    sendgrid.setApiKey(process.env.SENDGRID_API_KEY);

    // get all the input variables
    var fromEmail = core.getInput('fromMailAddress');
    var toEmail = core.getInput('toMailAddress');
    var subject = core.getInput('subject');
    var verbose = core.getInput('verbose');
    var labelsToMonitor = core.getInput('labelsToMonitor').split(",");
    var subjectPrefix = core.getInput('subjectPrefix');

    // check to make sure we match any of the labels first
    var context = github.context;
    var issue = context.payload.issue;

This context gives me all I need to inspect the Issue contents, labels, etc.  From that then I can decide that I need to perform the notification, convert, and send the email.  Simple and done.

Consuming the Action

Since the Action is now defined, something needs to consume it.  This is in the form of a GitHub Workflow.  This is a YAML file that decides when to operate and what to do.  Specifically you define a Trigger.  These can be things like when a push happens, a PR is issued, or, in my case, when an Issue happens.  So now on my repo I can consume the action and decide when it should operate.  As an example here is how I’m consuming it by putting a yaml file in .github/workflows folder in my repo.

name: "bc-notification"
on: 
  issues:
    types: [edited, labeled]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/[email protected]
    - uses: timheuer/[email protected]
      env:
        SENDGRID_API_KEY: ${{ secrets.SENDGRID_API }}
      with:
        fromMailAddress: '${{ secrets.BC_NOTIFY }}'
        toMailAddress: '${{ secrets.BC_NOTIFY }}'
        subject: 'BC:'
        subjectPrefix: 'BC:'
        labelsToMonitor: "Breaking change"

Looking at this workflow you can see in the highlighted areas that I’m triggering on Issues, and then secondarily only when they are edited or labeled.  Then later on this workflow defines using my new action I created (and now published as a tagged version) called issue-notifier.  Done.  Now whenever an Issue is labeled as a breaking change in this repo and email is sent to a set of partners via email proactively without them having knowledge that there may be something they want to subscribe to in the repo.  Here is an example of seeing it triggered:

issuesampleanim

and the result notification in my inbox:

samplemail

Dev experience for Actions

I’ve had a good experience working with GitHub Actions and learning the various ways of automating a few things beyond just build in my repos.  My #1 wish for the ‘inner loop’ experience in creating Actions is the debugging experience.  You have to actually push the workflow and trigger it so ‘test’ it.  This leads to a slow inner-loop development flow.  It would be nice to have some more local runner capability to streamline this process and not muddy the repo with a bunch of check-ins fixing dumb things as you are iterating.

Anyhow, if you want to use this action I created, feel free: https://github.com/marketplace/actions/github-issue-notifier

Comments