Prevent Lazy GitHub Practices in 10 minutes using AWS Lambdas

"Can't you name all your pull requests in the right format?"
"...Oops I just merged into production"

Using AWS lambdas can be a cool and useful way to improve your workflow with GitHub.

Blocking merges when tests fail on your branch is common, but GitHub status checks can be pushed much further.

Combining GitHub’s API and Lambdas provides this opportunity.

Status Checks

Turns out we can use a Github Webhook Listener to POST to an AWS lambda after any specified events(pushes, commits, forks, pull requests etc).

In response, lambdas can in turn POST back to a Pull Request and create/update a status check.

Or they can just POST at specified times.

To test this out and get it up and running, we could impose two checks:

  • A required format for pull request titles
  • Specific times where merging to production is prohibited

For a full in-depth guide on setting all this up for your project see my github-lambda-status-checks repo.

Event Listener

First we set up a lambda which can react to a JSON of information about a pull request.

After deploying the lambda via serverless we are given an endpoint which, using GitHub webhooks, can automatically be hit on every pull request action(create, edit, …)

The webhook provides the lambda with a large amount of information about the PR.

An abridged version of some of the information sent to the lambda is shown below:

Abridged GitHub Status Post

Abridged GitHub Status Post

Amongst this, we are given a statuses_url to which we can send a POST request back to the GitHub API to create/update a status.

For example, sending the following created the fake CI status in the title image:

Success GitHub Status

Success GitHub Status

We can add any logic based on say, the pull request title, to send back a status result (‘success’, ‘failure’, ‘pending’).

Post GitHub Status

Post GitHub Status

These will appear, as in the title image, depending on the state sent.

In github-lambda-status-checks you can add any logic to gitWebhookListener.js from line 78 to tweak your status responses.

After any status check(which are unique by their context) has run at least once in a repo, it can be chosen as a Required status check on any protected branches(settings -> branches).

This will prevent the PR being merged unless the status check has a success state (see title image).

Cron Job

Lambdas can also be setup to trigger at set times in the day.

Using the GitHub API the lambda can say, GET all the pull requests from a given repo merging into the production branch.

At 4pm it could then send a pending state to all of these pull requests. If this check is set as Required, it would then block accidental merging at inappropriate times.

You could then trigger another lambda at 8am to unblock all these PRs.

Gotcha

If you set this status to ‘Required’ then any new pull request can not be merged until it passes this check, which won’t be until 8am the next day…

To overcome this you can check the time in the pull request event listener so that any new pull request can pass/fail the time check as expected.

What we did

We wanted to move a long running project from merging to production twice a week, to continuously deploying with every ticket.

The lambdas in this article came about to address some concerns we had about this.

Title Checker

Our release notes (linked directly to pull request titles) needed to accurately reflect what was in production at a given time (as opposed to random commit titles).

Devs/stakeholders needed to be able to quickly associate a pull request title to a team, ticket number and user story:

(A-TEAM 123) AAC I love this product

This was implemented similar to gitWebhookListener.js with simple JS/regex.

Time Checker

Our team had become accustomed to merging a validated ticket to a master branch.

This master branch would then be merged/deployed into production twice a week.

The worry with continuous deployment (eliminating master) was that a ticket may accidentally be merged to production (after validation) too late in the day (when bugs can’t be monitored/fixed).

Thus the timed lambda in githubTimeStatus.js (and the gotcha in githubWebhookListener.js) was implemented.

Further Applications

As we have seen, the response from GitHub provides a lot of information about the PR, so you could adapt this to any need you may have.

References

For a full in-depth guide on setting this up for your project see mygithub-lambda-status-checks repo.

Links


You liked this article? You'd probably be a good match for our ever-growing tech team at Theodo.

Join Us

  • ewolfe

    Some shameless self promotion, I built something pretty similar https://github.com/ewolfe/prlint

  • Casey Wireman

    I also did something similar to what’s listed here. We have Jenkins build containers for our codebase on every commit and send them off to ECR. We have a lifecycle policy that automatically deletes old untagged containers, but we wanted to be smarter about deleting old tagged containers since they could still technically belong to an active branch, so we have basically this setup that looks at branch deletion events -> API Gateway -> Lambda for cleaning up ECR.