Skip to main content

GitHub Actions to S3/CloudFront CI setup

· 2 min read

This article describes how to setup GitHub Actions CI deploy to AWS S3 / CloudFront.

Create an IAM user for GitHub Actions with a policy to allow deploying to the S3 bucket and invalidating the CloudFront distrubution:

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AccessToGetBucketLocation",
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::my-bucket-name"
]
},
{
"Sid": "AccessToWebsiteBuckets",
"Effect": "Allow",
"Action": [
"s3:PutBucketWebsite",
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::my-bucket-name",
"arn:aws:s3:::my-bucket-name/*"
]
},
{
"Sid": "AccessToCloudfront",
"Effect": "Allow",
"Action": [
"cloudfront:GetInvalidation",
"cloudfront:CreateInvalidation"
],
"Resource": [
"arn:aws:cloudfront::012345678901:distribution/DISTRIBUTIONID"
]
}
]
}

Replace these variables:

  • 012345678901 -> your AWS account ID
  • DISTRIBUTIONID -> your CloudFront distribution ID
  • my-bucket-name -> your S3 bucket's name

In GitHub Actions Secrets, set these environment variables:

AWS_INVALIDATE_DISTRIBUTION_ID=DISTRIBUTIONID
AWS_S3_BUCKET=name-of-bucket
AWS_ACCESS_KEY_ID=***
AWS_SECRET_ACCESS_KEY=***

In package.json add a deploy script:

"deploy": "aws s3 sync --delete build/ \"s3://${AWS_S3_BUCKET}/\" --cache-control max-age=600 && aws cloudfront create-invalidation --distribution-id \"${AWS_INVALIDATE_DISTRIBUTION_ID}\" --paths '/*'",

Create .github/workflows/deploy.yml:

name: Deploy

on:
push:
branches:
- master

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
cache: 'yarn'

- 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: ${{ secrets.AWS_REGION }}

- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn deploy
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_INVALIDATE_DISTRIBUTION_ID: ${{ secrets.AWS_INVALIDATE_DISTRIBUTION_ID }}

This assumes that the script build creates a directory build with all the static assets.

Now push the code and let GitHub Actions do its magic.

Example repo: https://github.com/mifi/mifi.no

Inspired by: