CI/CD Pipeline for Static Website Deployment
The second part of this project involves integrating a CI/CD pipeline via Github Actions to automatically upload the website frontend code currently stored in the github repo (https://github.com/bolucloud/s3-hosted-site/tree/main/website).
The following steps need to be followed to accomplish this:
- Create an IAM user or role and Policy
- Add secrets to Github and Write Github Actions workflow
- Update HTML file and Test
Create an IAM User or Role and Policy
Following the principles of least privilege, you should create a new user or role to be used by the github actions workflow and only allow actions required for the data upload from github to s3 to be successful. In my case, I decided to simply create a user to allow Github Actions access into the AWS account. Next, create a policy that allows access to the s3 bucket where your site is hosted. This is created using terraform. Link to HCL code here -->
If you are creating the user via the AWS console, be sure to create the AWS access keys for the user as well. If creating via Terraform, the Access Key and Secret Access Keys can be retrieved from the state file.
resource "aws_iam_user" "github_s3_hosted_site_user" {
name = "github-s3-hosted-site-user"
}
resource "aws_iam_access_key" "github_s3_hosted_site_user_key" {
user = aws_iam_user.github_s3_hosted_site_user.name
}
Next, create a IAM policy to attach to the IAM user created. We are granting the user the following access:
- Allowing access to list buckets in the AWS account
- Allowing all Get actions
- Allowing all List actions
- Allowing PutObject action on the s3 hosted site bucket only.
The below policy was created to be attached to the IAM user or role. Detailed code to create and attach the policy is found in the s3-hosted-site repo, in iam.tf file.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:ListAllBuckets",
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"s3:Put*",
"s3:List*",
"s3:Get*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::www.bolucloudtestbucket.demo.bolu.cloud/*",
"arn:aws:s3:::www.bolucloudtestbucket.demo.bolu.cloud"
]
}
]
}
Github Secrets and Github Actions Workflow
The IAM user credentials (Access Key and Secret Access Key) will now be entered into github. To do this, go into your repo, and find the Settings page. On the left navigation, find Secrets and Variables and click on Actions. In the section that says Repository Secrets, click New repository secret to enter your two secrets named AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY similar to below.
After getting secrets into your github repo, its time to write the steps to allow the data to be updated automatically upon update. Github actions works by referencing a particular location in your repository, so we need to create a folder called .github at the root level of the repository, and then a folder called workflow. Inside the workflow folder, our yaml files to dictate our github actions will reside. The code for push-frontend-to-s3.yml is below.
name: push-frontend-update-to-s3
on: [push]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup AWS CLI
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: us-east-1
- name: Sync files to S3 bucket
run: |
aws s3 sync website s3://www.bolucloudtestbucket.demo.bolu.cloud
While the code above is correct, this action will perform an update to the s3 code on any git commits (or pushes) to the repository, which isn't the behavior desired. The html code in our repo should only be updated to the s3 bucket after the code has been reviewed and merged to the main branch. A simple change to the on block should fix this. Note that in order to reference the AWS credentials secrets entered in the Github repo, use the ${{ secret.SECRET_NAME }} format.
name: push-frontend-update-to-s3
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup AWS CLI
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: us-east-1
- name: Sync files to S3 bucket
run: |
aws s3 sync website s3://www.bolucloudtestbucket.demo.bolu.cloud
Update HTML File and Test
So I updated website folder by adding a githubactionstest.html file, and also adding a new section in the index.html site with "<p>Updated via github actions</p>". Before I merged the PR into the main branch, the s3 bucket only had 2 objects (see below) and after merging and the Github Actions workflow running, it now has 3 objects (see below).
To get more details about your Github Actions workflow, click on the Actions tab on your repository --> https://github.com/bolucloud/s3-hosted-site/actions/runs/8413222736/job/23035133020
The updated website also renders the page with the updated code https://bolucloudtestbucket.demo.bolu.cloud/