GitHub Actions

The CI/CD pipeline uses GitHub Actions as the delivery engine to automate builds and deployments. This workflow is the first step in a chain of events that seamlessly publishes code changes to a global audience without manual intervention.

Production Deployment Workflow

The entire process is defined in a single YAML file stored with the repository's source code. This workflow is triggered on every `git push` to the `main` branch, ensuring the live site always mirrors the latest stable version.

.github/workflows/publish-website.yml
name: Publish Website

on:
  push:
    branches: [ main ]
    paths:
      - '**/*.html'
      - '**/*.js'
      - '**/*.css'
      - 'tailwind.build.config.js'
      - 'src/css/style-source.css'
      - '.github/workflows/publish-website.yml'
  workflow_dispatch:

# Allows the job to request an OIDC token for secure AWS authentication
permissions:
  id-token: write
  contents: read

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

      - name: Set up Node
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install Tailwind CLI
        run: npm install --no-save tailwindcss@^3.4.0

      - name: Build and minify style.css
        run: |
          npx tailwindcss \
            -i ./src/css/style-source.css \
            -o ./public/assets/css/style.css \
            -c ./tailwind.build.config.js \
            --minify

      - name: Swap CDN for compiled CSS in every HTML file
        run: |
          find ./public -type f -name "*.html" -exec sed -i '/https:\/\/cdn\.tailwindcss\.com/d' {} +
          find ./public -type f -name "*.html" -exec sed -i '/tailwind-config\.js/d' {} +
          find ./public -type f -name "*.html" -exec sed -i '/' {} +
  

      - name: Configure AWS credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ vars.AWS_SERVICE_ROLE_ARN }}
          aws-region: us-east-1

      - name: Sync site to S3
        run: aws s3 sync ./public ${{ vars.ML_WEBSITE_S3_URI }} --delete

Workflow Responsibilities

1. Production Asset Generation
The workflow first builds and minifies the site's stylesheet. It then processes all HTML files to remove development-only scripts and injects a standard `` tag pointing to the compiled CSS file, optimizing the site for production.
2. Secure AWS Authentication
Using OpenID Connect (OIDC), the workflow securely requests temporary credentials from AWS without using long-lived secrets. This adheres to security best practices and the principle of least privilege.
3. Delivery to S3 Origin
The final responsibility of the workflow is to sync the prepared `public` directory to the S3 bucket. This action completes the "delivery" phase and implicitly triggers the next stage of the deployment process within AWS.

Event-Driven Cache Invalidation

Cache invalidation is intentionally decoupled from the GitHub Actions workflow. Instead, it is handled by an event-driven process within AWS, defined as Infrastructure as Code (IaC) using the AWS CDK.

When the GitHub workflow uploads a new `index.html` file to S3, an `s3:ObjectCreated:Put` event is triggered. This event invokes an AWS Lambda function that, in turn, creates a CloudFront invalidation for `/*`. This design is highly efficient, as it only runs when a key page is updated, and it keeps the CI/CD workflow focused solely on code delivery.