Background
GitHub Actions is generally available at the end of 2019. Thanks to the open marketplace of GitHub Actions, more and more projects are using it.
Whether you are in the Devs or Ops team, you must be familiar with infrastructure as code. However, if you don't have a good pipeline, the deployment process can be a headache.
In this article, you will learn how to use GitHub Actions to deploy CloudFormation stacks.
Prerequisites
- A GitHub Account (Click here to see free tier information)
- A Programmatic Access IAM user in AWS
- CloudFormation & S3 permissions
Process
Create CFN Templates
Let us create a simple CloudFormation template for creating an S3 bucket.
The filename is s3.yml
.
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Then we would like to name our own S3 bucket, and for our template to be reusable, we want to pass parameters to CloudFormation stacks.
Parameters:
BucketName:
Description: Name your Bucket
Type: String
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
AccessControl: Private
BucketName: !Ref BucketName
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
Finally, we can add descriptions and format version and checkin the template in our repository. Click here to view the full template.
Create GitHub Workflows
Create .github/workflows/main.yml
under our git root directory. Let us write our first worflow.
Configure AWS Credentials
We are using this action to configure AWS credentials.
"Configure AWS Credentials" Action For GitHub Actions - GitHub Marketplace
We can write the step according to the README.
- name: Configure AWS Credentials
id: creds
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: "ap-southeast-2"
In AWS IAM console, get your access key ID and secret access key.
Then navigate to the main page of GitHub repository > Click Setting
> In the left sidebar, click Secrets
> Click New repository secret
> Create AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
.
Create Deployment Actions
We are using this action to deploy CFN stacks.
AWS CloudFormation "Deploy CloudFormation Stack" Action for GitHub Actions - GitHub Marketplace
We can write the step according to the README.
- As I am writing this article, the latest version is
v1.0.3
.
- name: Deploy to AWS CloudFormation
uses: aws-actions/aws-cloudformation-github-deploy@v1.0.3
with:
name: S3Bucket
template: s3.yml
We also need to pass the input parameter BucketName
.
# Controls when the action will run.
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
inputs:
BucketName:
description: "Name your Bucket"
required: true
default: "demo-bucket"
Then we add parameter-overrides
in the Deploy to AWS CloudFormation
step.
- name: Deploy S3 Buckets CloudFormation Stacks
uses: aws-actions/aws-cloudformation-github-deploy@v1.0.3
with:
name: s3-buckets
template: s3.yml
parameter-overrides: >-
BucketName=${{ github.event.inputs.bucketName }}
Let's finally organise our action file main.yml
.
name: Deploy CloudFormation Stacks
# Controls when the action will run.
on:
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
inputs:
region:
description: "AWS Region"
required: true
default: "ap-southeast-2"
bucketName:
description: "S3 Bucket Name"
required: true
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
cfn-deployment:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Configure AWS credentials</span>
<span class="na">id</span><span class="pi">:</span> <span class="s">creds</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">aws-actions/configure-aws-credentials@v1</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">aws-access-key-id</span><span class="pi">:</span> <span class="s">${{ secrets.AWS_ACCESS_KEY_ID }}</span>
<span class="na">aws-secret-access-key</span><span class="pi">:</span> <span class="s">${{ secrets.AWS_SECRET_ACCESS_KEY }}</span>
<span class="na">aws-region</span><span class="pi">:</span> <span class="s">${{ github.event.inputs.region }}</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Deploy S3 Buckets CloudFormation Stacks</span>
<span class="na">id</span><span class="pi">:</span> <span class="s">s3-buckets</span>
<span class="na">uses</span><span class="pi">:</span> <span class="s">aws-actions/aws-cloudformation-github-deploy@v1.0.3</span>
<span class="na">with</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">s3-buckets</span>
<span class="na">template</span><span class="pi">:</span> <span class="s">s3.yml</span>
<span class="na">parameter-overrides</span><span class="pi">:</span> <span class="pi">>-</span>
<span class="s">BucketName=${{ github.event.inputs.bucketName }}</span>
Use GitHub Workflows
Make sure you have pushed all the files. Just like the following repo.
yunpengeric/Cloudformation-Github-Actions-Demo
Then navigate to the main page of GitHub repository > Click Actions
> In the left sidebar, click Deploy CloudFormation Stacks
> Click Run Workflow
.
You should see the following pre-filled data > Enter your S3 bucket name (Please note an S3 bucket name is globally unique) > Run Workflow
After a minute or so, you will see that our S3 bucket has been successfully deployed. If you see any errors, please leverage GitHub logs and CloudFormation console to troubleshoot.
Conclusion
We are still far from it if our goal is to create a good pipeline in production environment. You should take these things into consideration as well.
- How you can rotate keys to ensure security.
- How to modify your CFN templates so that when you deploy a second bucket, you don't delete the first one.
Top comments (0)