Automating Static Website Deployment with GitHub Actions and AWS S3
Ravindra Singh

Ravindra Singh @ravindras

About: I deploy and manage infrastructure and applications across AWS and GCP Cloud. Certified in these platforms, I use Terraform and CI/CD tools to build scalable, secure solutions.

Location:
Pune, India
Joined:
Oct 31, 2023

Automating Static Website Deployment with GitHub Actions and AWS S3

Publish Date: Jul 23
3 2

Introduction

In today's fast-paced development environment, automating your deployment process is no longer a luxury—it's a necessity. Continuous Integration and Continuous Deployment (CI/CD) has become the industry standard for delivering software efficiently and reliably. In this blog post, I'll walk you through setting up a complete CI/CD pipeline using GitHub Actions to automatically deploy a static website to Amazon S3.

Why CI/CD Matters

Before diving into the technical details, let's understand why CI/CD is so important:

  1. Faster Delivery: Automate repetitive tasks to release features more quickly
  2. Higher Quality: Catch bugs early through automated testing
  3. Reduced Risk: Small, incremental changes are easier to troubleshoot
  4. Consistency: Every deployment follows the same process
  5. Developer Focus: Less time on operations means more time for coding

For static websites specifically, a CI/CD pipeline ensures that every change you push to your repository is automatically tested and deployed, eliminating manual FTP uploads or console interactions.

The Architecture

Our CI/CD pipeline follows this simple flow:

  1. Developer pushes code to GitHub repository
  2. GitHub Actions detects the change and triggers a workflow
  3. The workflow builds and tests the website
  4. If successful, the workflow deploys the site to AWS S3
  5. The website is immediately available to visitors

This architecture provides several benefits:

  • Scalability: S3 can handle virtually unlimited traffic
  • Cost-Effective: Pay only for what you use
  • Reliable: AWS's infrastructure ensures high availability
  • Secure: Access controls and encryption protect your content

Source Git Link: https://github.com/ravindrasinghh/github-actions-s3-workshop/tree/master

Prerequisites

To follow along with this tutorial, you'll need:

  • A GitHub account
  • An AWS account
  • Basic understanding of HTML, CSS, and JavaScript
  • Familiarity with Git commands

Step 1: Setting Up Your S3 Bucket

First, we need to create an S3 bucket configured for static website hosting:

  1. Log in to the AWS Management Console and navigate to S3
  2. Click "Create bucket"
  3. Enter a globally unique name for your bucket
  4. Choose your preferred region
  5. Uncheck "Block all public access" (since this is a public website)
  6. Enable "Static website hosting" under the Properties tab
  7. Set "index.html" as both the index and error document
  8. Add a bucket policy to allow public read access:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-bucket-name/*"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Creating IAM Credentials

For GitHub Actions to access your S3 bucket, you'll need IAM credentials:

  1. Navigate to IAM in the AWS Console
  2. Create a new policy with the following permissions:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name",
                "arn:aws:s3:::your-bucket-name/*"
            ]
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode
  1. Create a new IAM user with programmatic access
  2. Attach the policy you just created
  3. Save the Access Key ID and Secret Access Key securely

Step 3: Setting Up Your GitHub Repository

  1. Create a new repository or use an existing one
  2. Add your static website files to the repository
  3. Navigate to Settings > Secrets and variables > Actions
  4. Add the following secrets:
    • AWS_ACCESS_KEY_ID: Your IAM user's access key
    • AWS_SECRET_ACCESS_KEY: Your IAM user's secret key
    • S3_BUCKET_NAME: Your S3 bucket name

Step 4: Creating the GitHub Actions Workflow

The heart of our CI/CD pipeline is the GitHub Actions workflow file. Create a new file at .github/workflows/deploy-to-s3.yml with the following content:

name: Deploy Static Website to S3

on:
  push:
    branches: [ main ]
  workflow_dispatch:  # Allows manual triggering

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    # No build step needed for this simple static website
    # Just update the deployment timestamp in the JavaScript file
    - name: Update deployment timestamp
      run: |
        echo "// Updating timestamp for deployment on $(date)" >> js/script.js
        echo "// Deployment ID: ${{ github.run_id }}" >> js/script.js

    # Configure AWS credentials
    - name: Configure AWS credentials
      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: "ap-south-1"

    # Deploy to S3 bucket - directly sync the repository contents
    - name: Deploy to S3
      run: |
        aws s3 sync ./ s3://${{ secrets.S3_BUCKET_NAME }}/ \
          --delete \
          --exclude ".git/*" \
          --exclude ".github/*" \
          --exclude "README.md" 

Enter fullscreen mode Exit fullscreen mode

Let's break down what this workflow does:

  1. Triggers: The workflow runs whenever code is pushed to the main branch or when manually triggered
  2. Checkout: Fetches the latest code from your repository
  3. Timestamp: Adds a deployment timestamp to your JavaScript file
  4. AWS Credentials: Configures AWS credentials using your GitHub secrets
  5. Deployment: Syncs your website files to the S3 bucket, excluding unnecessary files
  6. Confirmation: Outputs the URL where your website can be accessed

Step 5: Testing the Pipeline

Now it's time to see your CI/CD pipeline in action:

  1. Commit and push your changes to the main branch
  2. Go to the "Actions" tab in your GitHub repository
  3. Watch as your workflow runs automatically
  4. Once completed, click on the workflow run to see the details
  5. Visit your website URL to confirm the deployment was successful

Understanding the Workflow

Let's dive deeper into some key aspects of our GitHub Actions workflow:

The Trigger

on:
  push:
    branches: [ main ]
  workflow_dispatch:
Enter fullscreen mode Exit fullscreen mode

This section defines when the workflow should run. In our case, it runs on pushes to the main branch and can also be triggered manually using the "workflow_dispatch" event.

AWS Credentials

- name: Configure AWS credentials
  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'
Enter fullscreen mode Exit fullscreen mode

This step uses the official AWS GitHub Action to configure credentials. The credentials are stored securely as GitHub secrets and are never exposed in logs.

S3 Sync

- name: Deploy to S3
  run: |
    aws s3 sync ./ s3://${{ secrets.S3_BUCKET_NAME }}/ \
      --delete \
      --exclude ".git/*" \
      --exclude ".github/*" \
      --exclude "README.md" \
      --exclude "*.md" \
      --exclude ".vscode/*"
Enter fullscreen mode Exit fullscreen mode

The aws s3 sync command efficiently uploads only the files that have changed. The --delete flag removes files from the bucket that don't exist in your repository, ensuring your website is always in sync with your code.

Common Issues and Troubleshooting

Here are some common issues you might encounter and how to fix them:

Access Denied Errors

If you see "Access Denied" errors in your workflow:

  • Double-check your IAM permissions
  • Verify that your bucket policy allows the necessary actions
  • Ensure your GitHub secrets are correctly set

Files Not Updating

If your website isn't reflecting the latest changes:

  • Check that you're pushing to the correct branch
  • Look for errors in the GitHub Actions logs
  • Try clearing your browser cache

Workflow Not Triggering

If your workflow isn't running:

  • Verify that the workflow file is in the correct location (.github/workflows/)
  • Check that the trigger conditions match your push event
  • Ensure the workflow file has valid YAML syntax

Conclusion

Setting up a CI/CD pipeline with GitHub Actions and AWS S3 is a powerful way to streamline your website deployment process. By automating these tasks, you can focus on what matters most—building great websites.

I hope this guide helps you implement your own automated deployment pipeline. Happy coding!

Comments 2 total

Add comment