Auto-Deploy React App with GitHub Actions + AWS


Setting up a complete CI/CD pipeline for React applications doesn’t have to be complex. In this guide, I’ll walk you through creating an automated deployment pipeline that takes your code from commit to production using GitHub Actions, AWS S3, and CloudFront.



Table of Contents



What We’re Building

By the end of this tutorial, you’ll have:

  • Automated testing and building on every pull request
  • Automatic deployment to AWS S3 + CloudFront on merge to main
  • Cache invalidation to ensure users see updates immediately
  • Preview deployments for pull requests



Prerequisites

  • A React application ready to deploy
  • AWS account with S3 and CloudFront access
  • GitHub repository for your project
  • Basic familiarity with GitHub Actions



Step 1: AWS Infrastructure Setup



Create S3 Bucket

First, create an S3 bucket to host your static website:

aws s3 mb s3://your-app-production --region us-east-1
aws s3 website s3://your-app-production --index-document index.html --error-document error.html
Enter fullscreen mode

Exit fullscreen mode



Set Up CloudFront Distribution

Create a CloudFront distribution for global CDN delivery:

{
  "CallerReference": "your-app-production",
  "Origins": {
    "Quantity": 1,
    "Items": [
      {
        "Id": "S3Origin",
        "DomainName": "your-app-production.s3.amazonaws.com",
        "S3OriginConfig": {
          "OriginAccessIdentity": ""
        }
      }
    ]
  },
  "DefaultCacheBehavior": {
    "TargetOriginId": "S3Origin",
    "ViewerProtocolPolicy": "redirect-to-https"
  }
}
Enter fullscreen mode

Exit fullscreen mode



Configure IAM User

Create an IAM user with these permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-app-production",
        "arn:aws:s3:::your-app-production/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateInvalidation"
      ],
      "Resource": "*"
    }
  ]
}
Enter fullscreen mode

Exit fullscreen mode



Step 2: GitHub Actions Workflow

Create .github/workflows/deploy.yml:

name: Deploy React App

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Run tests
      run: npm test -- --coverage --watchAll=false

    - name: Run linting
      run: npm run lint

    - name: Upload coverage reports
      uses: codecov/codecov-action@v3

  build:
    runs-on: ubuntu-latest
    needs: test

    steps:
    - uses: actions/checkout@v3

    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'

    - name: Install dependencies
      run: npm ci

    - name: Build application
      run: npm run build

    - name: Upload build artifacts
      uses: actions/upload-artifact@v3
      with:
        name: build-files
        path: build/

  deploy:
    runs-on: ubuntu-latest
    needs: build
    if: github.ref == 'refs/heads/main'

    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-files
        path: build/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v2
      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 to S3
      run: |
        aws s3 sync build/ s3://${{ secrets.S3_BUCKET }} --delete

    - name: Invalidate CloudFront
      run: |
        aws cloudfront create-invalidation \
          --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \
          --paths "/*"
Enter fullscreen mode

Exit fullscreen mode



Step 3: Advanced Features



Cache-Busting Strategy

Add cache-busting to your build process by updating package.json:

{
  "scripts": {
    "build": "react-scripts build && npm run optimize",
    "optimize": "node scripts/optimize-build.js"
  }
}
Enter fullscreen mode

Exit fullscreen mode

Create scripts/optimize-build.js:

const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

function addCacheHeaders() {
  const buildPath = path.join(__dirname, '../build');
  const staticPath = path.join(buildPath, 'static');

  // Add hash to static files
  const files = fs.readdirSync(staticPath, { recursive: true });

  files.forEach(file => {
    if (file.endsWith('.js') || file.endsWith('.css')) {
      const filePath = path.join(staticPath, file);
      const content = fs.readFileSync(filePath);
      const hash = crypto.createHash('md5').update(content).digest('hex').substring(0, 8);

      const newName = file.replace(/\.([^.]+)$/, `.${hash}.$1`);
      fs.renameSync(filePath, path.join(staticPath, newName));
    }
  });
}

addCacheHeaders();
Enter fullscreen mode

Exit fullscreen mode



Preview Deployments

Add preview deployments for pull requests:

  preview:
    runs-on: ubuntu-latest
    needs: build
    if: github.event_name == 'pull_request'

    steps:
    - name: Download build artifacts
      uses: actions/download-artifact@v3
      with:
        name: build-files
        path: build/

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v2
      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: Deploy to preview
      run: |
        PREVIEW_PATH="previews/pr-${{ github.event.number }}"
        aws s3 sync build/ s3://${{ secrets.S3_BUCKET }}/${PREVIEW_PATH}
        echo "Preview URL: https://your-domain.com/${PREVIEW_PATH}" >> $GITHUB_STEP_SUMMARY
Enter fullscreen mode

Exit fullscreen mode



Step 4: GitHub Secrets Configuration

Add these secrets to your GitHub repository:

  1. AWS_ACCESS_KEY_ID – Your IAM user’s access key
  2. AWS_SECRET_ACCESS_KEY – Your IAM user’s secret key
  3. S3_BUCKET – Your S3 bucket name
  4. CLOUDFRONT_DISTRIBUTION_ID – Your CloudFront distribution ID



Step 5: Monitoring and Optimization



Add Build Notifications

    - name: Slack notification
      if: always()
      uses: 8398a7/action-slack@v3
      with:
        status: ${{ job.status }}
        text: 'Deployment ${{ job.status }} for commit ${{ github.sha }}'
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Enter fullscreen mode

Exit fullscreen mode



Performance Monitoring

Add bundle size checking:

    - name: Check bundle size
      run: |
        npm run build
        npx bundlesize
Enter fullscreen mode

Exit fullscreen mode

With bundlesize configuration in package.json:

{
  "bundlesize": [
    {
      "path": "./build/static/js/*.js",
      "maxSize": "300 kB"
    },
    {
      "path": "./build/static/css/*.css", 
      "maxSize": "50 kB"
    }
  ]
}
Enter fullscreen mode

Exit fullscreen mode



Troubleshooting Common Issues



Build Failures

  • Check Node.js version compatibility
  • Verify all environment variables are set
  • Review test failures in the Actions tab



Deployment Issues

  • Confirm S3 bucket policies allow public read access
  • Verify CloudFront distribution is pointing to correct origin
  • Check IAM permissions for S3 and CloudFront access



Cache Issues

  • Ensure CloudFront invalidation is running
  • Verify cache-control headers on S3 objects
  • Consider using versioned URLs for assets



Conclusion

You now have a production-ready CI/CD pipeline that automatically tests, builds, and deploys your React applications with zero downtime and instant cache invalidation. This automated workflow will save hours of manual deployment work while ensuring consistent, reliable releases that scale with your development team.

The pipeline includes advanced features such as preview deployments, comprehensive testing, and performance monitoring — exactly what you need for professional React application deployments.

Need help implementing CI/CD pipelines or AWS infrastructure for your project? I specialize in DevOps consulting and can set up production-ready deployment automation in days, not weeks. Check out my portfolio and services or send me a message to discuss your project.


This is part 1 of my “DevOps for Startups” series. Part 2 covers building a scalable AWS infrastructure with Terraform soon.



Source link

Leave a Reply

Your email address will not be published. Required fields are marked *