CI/CD Workflow: GitHub Actions for AWS S3

CI/CD for a static website on AWS Simple Storage Service

Bryant Logan
6 min readOct 24, 2022

As part of my transition from sales to cloud, I decided to have a go at the Cloud Resume Challenge. A portion of the challenge requires you to create a portfolio/resume that is hosted in S3 as a static website. As I continued to make changes and improvements, it became time consuming to have to log into the AWS console with MFA, navigate to my S3 bucket, and manually upload files. So in typical DevOps fashion, I looked for a way to automate this process. The code for the GitHub Action and abbreviated instructions are available in my GitHub repository.

Prerequisites:

For this tutorial you will need:

  • An AWS account
  • A GitHub account
  • Visual Studio Code linked to GitHub account — more info here

Objective:

  1. Create an S3 bucket that enables static website hosting
  2. Create an IAM user with permissions to access S3 bucket
  3. Create workspace in VS Code to initialize GitHub repository
  4. Set up GitHub Actions workflow that uploads files to S3 after every commit is pushed to the repository
  1. Create S3 bucket & configure bucket settings

Head over to the S3 console and click ‘Create bucket’. Choose a globally unique name for the bucket. Disable the option to Block all public access, and check off the box acknowledging public access. Leave ACLs disabled.

Once the bucket has been created, click on it, and then click on ‘Properties’. Scroll all the way to the bottom, and you’ll see an option to edit static website hosting settings. Click on edit, and enable static website hosting. You’ll need to specify the index document — I went with the default index.html. Click on ‘Save changes’.

The last thing you’ll need to do is allow public read access to the objects in the bucket. In order to do this, click on ‘Permissions’, scroll down to the bucket policy and click ‘edit’. You’ll need to use the policy below and make sure to put your bucket ARN instead of the default in the template. Once this is done, click on ‘Save changes’. For more info, check out the AWS docs here.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::Bucket-Name/*"
]
}
]
}
JSON bucket policy to allow public access

Now that the bucket is properly set up, you can head over to the IAM console to create a user that GitHub will use to upload files to S3.

2. Create IAM user and attach S3 policy

In the IAM console, click on ‘Users’ under the IAM resources section. On the next screen, click ‘Add users’. You can choose any name you like. For the AWS credential type, choose the default programmatic access, which will provide the user with an access key and access key ID. Click on ‘Next: Permissions’.

Now, you’re going to attach a policy that will allow the new user to upload files to S3. Click on ‘Attach existing policies directly’ and filter results for s3. For the purpose of this demo, you’re going to attach the S3FullAccess policy. In real-world cases, you will want to apply least-privilege permissions. Click ‘Next: Tags’, and you can add tags if you’d like. Note: If you have a CloudFront distribution in front of your S3 bucket, you’ll need to add a policy that allows cache invalidation if you want real-time updates.

On the final screen, click ‘Create user’, and make sure to download the .csv file that has the user’s Access Key ID and Secret Access Key.

Now that the user has the necessary permissions, let’s head over to VS Code to set up the GitHub repository and demo website.

3. Set up webpage and GitHub Repository

In VS Code, you’ll need to make a directory that will contain the index.html file and optionally an error.html file. You can either do this from the terminal or use the UI on your computer. Once you’ve created the directory and index.html file, open the folder by clicking ‘Open folder’ on the left-hand side. You can type ‘!’ followed by ‘Enter’ into the editor to get some basic html populated. In the body section, I added:

<p>Hello World!</p>

After saving the changes, click on the search bar up top and search ‘Publish to GitHub’. It will then prompt you to either create a public or private repository.

Now, if you check your GitHub account, you should see a new repository has been created, and the files have been pushed.

Everything looks good! The directory on your local machine is being tracked, and any changes will be recognized by version control. Time for the last step: configuring the GitHub Action workflow!

4. Configure GitHub Actions

In the repository, click on ‘Settings’, then scroll down to Secrets and click on ‘Actions’.

On the next screen, click on ‘New repository secret’.

Now we’re going to add 3 secrets for the AWS_S3_BUCKET, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY. The AWS Access Key ID and Secret Access Key can be found in the .csv file that was downloaded earlier after creating the IAM user. Note: If using CloudFront, you’ll need to create another secret for the CloudFront distribution ID.

Now that the secrets have been created, you can now head back into the repository and click on ‘Actions’. Then click on ‘set up a workflow yourself’.

On the next screen, copy the code from here into the /.github/workflows/main.yml file that GitHub has created and click on ‘commit’.

You should be good to go! You can head back to the bucket and check what the web page is looking like so far by clicking on the index.html object and then the object url.

This is the current state:

Back in VS Code, I’m going to make a slight change to the code in the index.html file:

After clicking ‘Sync Changes’, this will trigger the workflow in GitHub Actions. You can track the progress of the job under the Actions tab in your repository. Job complete!

Now if you refresh your tab that has your webpage open, the changes should be live!

And there you have it! A simple CI/CD workflow that streamlines content and feature delivery to your website. The code and readme are available in my GitHub repository. If you run into any issues, feel free to write a note or find me on LinkedIn.

--

--