Skip to content

GitHub action that upload contents to S3 bucket and performs CloudFront invalidation.

License

Notifications You must be signed in to change notification settings

kazimanzurrashid/aws-static-web-app-update-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

AWS Static Web App update action

GitHub GitHub release (latest by date) GitHub Workflow Status

This action uploads the contents of the specified directory with proper mime-type and cache-control into S3 bucket and optionally issues an invalidation command to associated cloudfront distribution.

Usage

minimum

uses: kazimanzurrashid/[email protected]
with:
  location: './web/public'
  bucket: 'example.com'

complete

uses: kazimanzurrashid/[email protected]
with:
  location: './web/public'
  bucket: 'example.com'
  cache-control: |
    private,max-age=31536000: ['**', '!index.html']
  invalidate: 'XXXXXXXXXXXXXX'
  wait: true
  AWS_REGION: ${{ secrets.AWS_REGION }}
  AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
  AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
  AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }}

AWS Permission

The AWS Account needs to have the "s3:PutObject" permission, if Cloudfront invalidation is enabled then "cloudfront:CreateInvalidation" and "cloudfront:GetInvalidation" are required, if no distribution id is provided (e.g. invalidate: true) then "cloudfront:ListDistributions" is also required.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:PutObject"],
      "Resource": "*" // Don't use for production, change it to your s3 bucket name
    },
    {
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateInvalidation",
        "cloudfront:GetInvalidation",
        "cloudfront:ListDistributions"
      ],
      "Resource": "*" // Don't use all, change it to your actual cloudfront distribution
    }
  ]
}

Inputs

location

Required. The location of the directory which contents would be uploaded.

bucket

Required. The name of the S3 bucket where the content would be uploaded.

cache-control

Optional. HTTP cache-control mapping. behind the scene it uses globby to find the matching file.

invalidate

Optional. Boolean or the id of the cloudfront distribution, the default is false, if true then it uses the cloudfront distribution id that is associated with the S3 bucket.

wait

Optional. Boolean, if true then it would wait for the invalidation to complete, the default is true.

AWS_REGION

Optional, if not specified fallbacks to environment variable.

AWS_ACCESS_KEY_ID

Optional, if not specified fallbacks to environment variable.

AWS_SECRET_ACCESS_KEY

Optional, if not specified fallbacks to environment variable.

AWS_SESSION_TOKEN

Optional, if not specified fallbacks to environment variable.

Outputs

N/A

Examples

React

name: Web
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Node.js setup
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Build
        run: |
          npm ci
          npm run build

      - name: Update
        uses: kazimanzurrashid/[email protected]
        with:
          location: ./build
          bucket: my-site.com
          cache-control: |
            public, max-age=31536000, immutable: '/static/**/**'
            max-age=0, no-cache, no-store, must-revalidate: ['./index.html', './'service-worker.js]
          invalidate: true
        env:
          AWS_REGION: ${{ secrets.AWS_REGION }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Angular

name: Web
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Node.js setup
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Build
        run: |
          npm ci
          ng build --configuration production

      - name: Update
        uses: kazimanzurrashid/[email protected]
        with:
          location: ./dist/my-ng-app
          bucket: my-site.com
          cache-control: |
            public, max-age=31536000, immutable: ['./**/*.js', './**/*.css', './**/*.png', './**/*.jpg', './assets/**/**']
            max-age=0, no-cache, no-store, must-revalidate: ['./index.html']
          invalidate: true
        env:
          AWS_REGION: ${{ secrets.AWS_REGION }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

Gatsby

name: Web
on:
  push:
    branches:
      - main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Node.js setup
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Build
        run: |
          npm ci
          npm run build

      - name: Update
        uses: kazimanzurrashid/[email protected]
        with:
          location: ./public
          bucket: my-site.com
          cache-control: |
            max-age=0, no-cache, no-store, must-revalidate: ['./**/**/*.html', './page-data/**/**']
            public, max-age=31536000, immutable: ['./static/**/**', './*.js', './*.css']
          invalidate: true
        env:
          AWS_REGION: ${{ secrets.AWS_REGION }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

License

This project is distributed under the MIT license.