GitHub Actions Tutorial — Deploy to AWS

2 minute read

Deploy to AWS

GitHub Actions integrates with AWS through OIDC (recommended) or static credentials. OIDC eliminates long-lived secrets — GitHub mints a short-lived token that AWS trusts directly.


1. Create an IAM OIDC Provider

In AWS Console → IAM → Identity providers → Add provider:

Provider URL: https://token.actions.githubusercontent.com
Audience:     sts.amazonaws.com

2. Create an IAM Role

Trust policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
        },
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
        }
      }
    }
  ]
}

3. Use in Workflow


permissions:
  id-token: write
  contents: read

steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::ACCOUNT_ID:role/github-actions-role
      aws-region: us-east-1

No secrets needed — OIDC handles authentication.


Deploy to S3


name: Deploy to S3

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

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

      - name: Sync to S3
        run: aws s3 sync ./dist s3://${{ secrets.S3_BUCKET }} --delete

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


Deploy to ECS


name: Deploy to ECS

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - uses: aws-actions/amazon-ecr-login@v2
        id: ecr

      - name: Build and push image
        env:
          ECR_REGISTRY: ${{ steps.ecr.outputs.registry }}
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/my-app:$IMAGE_TAG .
          docker push $ECR_REGISTRY/my-app:$IMAGE_TAG

      - name: Update ECS task definition
        id: task-def
        uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          task-definition: task-definition.json
          container-name: my-app
          image: ${{ steps.ecr.outputs.registry }}/my-app:${{ github.sha }}

      - name: Deploy to ECS
        uses: aws-actions/amazon-ecs-deploy-task-definition@v2
        with:
          task-definition: ${{ steps.task-def.outputs.task-definition }}
          service: my-app-service
          cluster: my-cluster
          wait-for-service-stability: true


Deploy Lambda Function


name: Deploy Lambda

on:
  push:
    branches: [main]

permissions:
  id-token: write
  contents: read

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

      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: us-east-1

      - name: Package and deploy
        run: |
          zip -r function.zip src/
          aws lambda update-function-code \
            --function-name my-function \
            --zip-file fileb://function.zip


Common Mistakes

Mistake Fix
id-token: write permission missing Required for OIDC — add at job or workflow level
OIDC trust policy too broad Restrict sub claim to specific repos and branches
Secrets in logs AWS CLI masks credentials, but avoid echo $SECRET
Old aws-actions versions Use @v4 for configure-credentials, @v2 for ECR/ECS

Quick Reference

Target Key Action
Auth (OIDC) aws-actions/configure-aws-credentials@v4
ECR aws-actions/amazon-ecr-login@v2
ECS aws-actions/amazon-ecs-deploy-task-definition@v2
S3 aws s3 sync CLI command
Lambda aws lambda update-function-code CLI command

← Back to: Chapter 13: Deployments

Next: Deploy to Azure →

Updated: