GitHub process automation: A bot to build pull requests authorized by core maintainers
We are maintaining multiple Open Source projects where we focus on CloudFormation templates. To ensure that the templates are of high quality, we leverage automated testing and pull requests. We could use the CodeBuild GitHub integration to execute yamllint, cfn-lint, and also aws cloudformation validate-template to make sure that a pull request is not breaking the templates. That’s a great way to allow contributions while ensuring high quality. You can also use Travis CI and others to run the static tests on each commit / pull request.
However, the mentioned tools only inspect the templates. They don’t create an actual CloudFormation stack. To be 100% sure that a pull request is not breaking any template, we have to create some CloudFormation stacks with the changes from the pull request. Creating a CloudFormation stack causes AWS costs (the actual AWS resources cause the costs, not CloudFormation). Usually, we spent 500 - 1000 USD per month to run automated tests on our templates.
The problem: If we create stacks automatically for every pull request, someone could open hundreds of pull requests and waste our money.
The solution: Let only core committers trigger the tests by commenting on the pull request.
You might come up with other processes based on GitHub Pull Requests that can be automated. E.g., you might want to push each change to a replication of the GitHub repository to CodeCommit. Read on if you are interested in the implementation using serverless technologies. You can find the full source code on GitHub.
The diagram was created with Cloudcraft - Visualize your cloud architecture like a pro.
GitHub triggers an HTTPS request for every comment made in a repository to an endpoint that you can define (aka webhook). You can create an HTTPS endpoint with API Gateway and forward the HTTPS request to a Lambda function.
The Lambda function inspects the GitHub data and kicks off a CodeBuild build.
To provide feedback to GitHub users, we watch CodeBuild with a CloudWatch Event Rule. Whenever a build status changes we trigger another Lambda function and signal the information back to GitHub.
The high-level architecture is described. Now it’s time to turn the plan into reality.
We recently released a new open source project to speed up CloudFormation projects in a modular way. I will use cfn-modules in the following implementation. Check out the details if you are interested: cfn-modules: Rapid CloudFormation. I will use cfn-modules in the following implementation.
First, you set up the project.
Create a new directory:
cfn-modules relies on npm to install and update modules. Initialize the project with the following command:
npm init -y
Now it’s time to start adding the first modules.
You should always monitor your AWS resources. Let’s start with that.
Special offer: cloudonaut t-shirt
Do you love our blog posts and podcast episodes? Unlock our weekly videos and online events by subscribing to cloudonaut plus.
Special offer: Join cloudonaut plus before November 30th, and we will send you a cloudonaut t-shirt for free.Subscribe now!
Run the following command to install the first cfn-module:
npm i @cfn-modules/alerting -P
template.yml file with the following content:
alerting module provides an SNS topic with a topic policy that allows most AWS resources to send messages for alerting purposes.
Next, you have to define the CodeBuild project that executes the actual tests.
I use CodeBuild in an unusual way. Usually, CodeBuild downloads the source for you. In this case, I use a dummy CodeCommit repository to satisfy this requirement. But the actual code for testing is downloaded with
git clone and the commit information are passed in via an environment variables (
Milestone completed: you can run tests for every commit on GitHub.
Luckily, cfn-modules provide an easy way to create an API Gateway backed by a Lambda function.
npm i @cfn-modules/lambda-event-source-webhook -P
Append the following to the
Milestone completed: you can now receive GitHub webhooks.
To provide feedback to the contributor we use GitHub status API to update the status of the pull request. For example, a failed build will look like this in the GitHub Pull Request UI:
To provide feedback, you can listen to CodeBuild state changes using a CloudWatch Event Rule. Append the following to the
Finally, append the following to the
template.yml to easily get the API Gateway endpoint URL.
Find the full source code on GitHub including deployment information.
You used an API Gateway to receive GitHub webhooks and start CodeBuild builds. Asynchronously, in the background, you listen for build changes with a CloudWatch Event Rule and signal the build changes back to GitHub using the status API. With this pattern, you can implement many custom processes on top of GitHub to improve reliability and security of your software development and delivery capabilities.