Using Github Actions and AWS CloudFormation to create Development to Production Workflow
As I learned from open source community about CI/CD and Infrastructure as Code (IaC) I felt need to share my own experience with those who are starting their learning journey, making it slightly easier for them by explaining the following:
- The importance of using Infrastructure as Code (IaC) — Configuration needed to build, deploy and setup web application are part of github repository which is used to demonstrate the concepts in this article. This means that there is (almost) no manual configuration required to create CI/CD and infrastructure.
- The possibility to simplify development to production workflow by using Github and AWS CloudFormation, as they are completely capable of replacing Jenkins or any other CI.
- To lay foundation for a proof of concept of a serverless web application which in future can use any front-end and back-end library to develop functionality, run tests (unit, integration and E2E), provide maximum availibility making both deveopers and users happy.
Github Actions has made it possible to automate, customize and execute development workflow right in the repository. New Github Actions are being added everyday. AWS has provided some very useful Github Actions which can be found here. Two AWS Github Actions used in this tutorial are:
- configure-aws-credentials to configure AWS credential environment variables for use in other Github Actions
- aws-cloudformation-github-deploy to deploys AWS CloudFormation Stacks right from within Github without logging into AWS console.
Code for workflow which uses Github Secrets to get AWS access key and secret key and creates CloudFormation stack can be found here. Even though the code for this workflow is self-explanatory, this is important to notice that due to idempotent nature of CloudFormation it can be run as many times as changes are pushed to ‘main’ branch without creating new stack every time. This is only going to create new resources or make changes to existing resources if there is a change. This code is going to make sure that it will not fail if there is no change.
CloudFormation makes it extremely easy to create all the AWS resources needed to build, deploy and serve application without the overhead of creating and maintaining servers. AWS resources created in this tutorial are S3 buckets, Cloudfront distributions, Route53 DNS records, ACM Certificate, CodePipeline, CloudWatch Rules, SNS Topics and Subscriptions and Simple Email Service (SES). Full credit goes to Reed Dadoune for making his website opensource which inspired me to learn CloudFormation by taking each piece of his template apart and recreating it one by one while understanding the fundamentals and learning how can I customize it to create foundation for an ideal serverless web application. I have removed static site generation and simply copy html/css files from Github to S3 bucket, link S3 bucket with Cloudfront distributions which are added as alias to Route53 DNS records. Certificate is linked to Cloudfront distributions after approval by Domain owner.
ACM Certificate Approval is the only manual step required when CloudFormation stack is created for the very first time. When ACM certificate is created through CLI/Cloudformation (automated way) then the only way it can be approved by domain owner is by clicking on approval request link sent to domain owner at the following email addresses. As explained here, request for approval email is sent to five email addresses so there has to be one of these email addresses which can be used to recieve email otherwise CloudFormation stack creation cannot complete as some of the resources required to create stack like Cloudfront distribution needs ACM Certificate to serve traffic over https. The easiest way to setup email address for approval request is to follow this tutorial to setup S3 bucket to recieve email. Since SES, S3 and Route53 are wired up so setting up bucket with permission for SES to write and adding records to Route53 for domain veritification can be done in few clicks. Once S3 bucket is setup to recieve emails from an address like admin@yourdomain.com you need to check it for email from ACM, download , open in any text editor, find link to approve certificate and finally approve certificate request.
Alias resource record for Cloud distribution When you look at creating DNS records for Cloud distribution then Z2FDTNDATAQYW2 seems to be HostedZoneId of your own domain where you want your website to be hosted but that is not true. As explained here this is a fixed value which cannot be changed.
AWS Secret Manager has been used in CloudFormation template as it can be seen here to store Github personal access token. Secret in Secret Manager has to be in the same region where CloudFormation stack is being created e.g. CloudFormation stack will fail if it is being created in us-east-1 and secret is saved in eu-west-1. Github personal access token is used by CodePipeline Source stage to get files from Github and pass it on to next action Deploy which copies it to public website hosted on S3 bucket.
Future Enhancements There are many features which can be added to it, some of them which I am planning to add are as follows;
- Use AWS Deploy to get npm dependencies to make it fully functional front end template repository.
- Create a back-end template repository which uses AWS API Gateway, Lambda and DynamoDb.
- While front-end is hosted on S3 and Cloudfront making it dynamic using CloudFront Lambda@Edge and Lambda functions.
- While doing above making sure that configuration for CI/CD and Infrastructure remains within application repository, deploying it through Github Actions and AWS Cloudformation.
- Do all above serverless without any overhead of maintaining expensive servers.