Panduan CI/CD GitHub Actions untuk AWS
Termasuk OIDC (tanpa long■lived keys), build & push Docker ke ECR, deploy ke ECS Fargate, EKS,
dan Lambda.
Pendahuluan & Prasyarat
Dokumen ini menjelaskan cara membangun pipeline CI/CD dengan GitHub Actions yang melakukan: (1)
build & test, (2) build/push container ke Amazon ECR, (3) deployment ke AWS (ECS Fargate, EKS, atau
Lambda). Kami menggunakan OIDC agar runner GitHub bisa assume role di AWS tanpa menyimpan
access key/secret di Secrets.
Prasyarat singkat: Repository di GitHub, AWS account, ECR repository (untuk workload container), IAM
role untuk OIDC.
Diagram Alur Pipeline
Konfigurasi OIDC GitHub → AWS (IAM Role)
1) Buat IAM Role dengan trusted identity = GitHub OIDC provider.
2) Batasi audience & repository (mis. repo:org/repo:ref:refs/heads/main) di trust policy.
3) Lampirkan policy minimal (ECR push, ECS/EKS/Lambda deploy sesuai target).
4) Catat ARN role, misalnya: arn:aws:iam:::role/GitHubActionsDeployRole.
GitHub Actions akan mengonfigurasi kredensial AWS via action resmi
aws-actions/configure-aws-credentials@v4.
Contoh 1 — CI Dasar (Node.js) + Build & Test
File: .github/workflows/ci.yml
name: CI - Build & Test (Node.js)
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [18.x, 20.x]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- name: Install deps
run: npm ci
- name: Lint
run: npm run lint --if-present
- name: Unit test
run: npm test -- --ci
- name: Upload coverage
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-${{ matrix.node }}
path: coverage/**
Contoh 2 — Build & Push ke ECR, Deploy ke ECS Fargate
File: .github/workflows/cd-ecs.yml
name: CD - ECR + ECS Fargate
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
id-token: write
env:
AWS_REGION: ap-southeast-1
ECR_REPO: my-app
ECS_CLUSTER: my-ecs-cluster
ECS_SERVICE: my-ecs-service
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: ${{ env.AWS_REGION }}
- name: Log in to Amazon ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build, tag, and push image
run: |
IMAGE_TAG=${{ github.sha }}
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_URI=$ACCOUNT_ID.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}
docker build -t $ECR_URI:$IMAGE_TAG .
docker push $ECR_URI:$IMAGE_TAG
echo "ECR_IMAGE=$ECR_URI:$IMAGE_TAG" >> $GITHUB_ENV
- name: Update ECS service
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
with:
task-definition: ecs-task-def.json
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
image: ${{ env.ECR_IMAGE }}
Contoh 3 — Build & Push ke ECR, Deploy ke EKS (kubectl)
File: .github/workflows/cd-eks.yml
name: CD - ECR + EKS
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
permissions:
contents: read
id-token: write
env:
AWS_REGION: ap-southeast-1
ECR_REPO: my-app
K8S_DEPLOYMENT: app
K8S_NAMESPACE: default
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: ${{ env.AWS_REGION }}
- name: Login to ECR
uses: aws-actions/amazon-ecr-login@v2
- name: Build & push image
run: |
IMAGE_TAG=${{ github.ref_name }}
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
ECR_URI=$ACCOUNT_ID.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPO }}
docker build -t $ECR_URI:$IMAGE_TAG .
docker push $ECR_URI:$IMAGE_TAG
echo "ECR_IMAGE=$ECR_URI:$IMAGE_TAG" >> $GITHUB_ENV
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Update kubeconfig for EKS
run: |
aws eks update-kubeconfig --region $AWS_REGION --name my-eks-cluster
- name: Deploy manifests
run: |
kubectl -n $K8S_NAMESPACE set image deployment/$K8S_DEPLOYMENT app=$ECR_IMAGE
kubectl -n $K8S_NAMESPACE rollout status deployment/$K8S_DEPLOYMENT --timeout=180s
Contoh 4 — Deploy ke AWS Lambda (SAM)
File: .github/workflows/cd-lambda-sam.yml
name: CD - AWS Lambda (SAM)
on:
push:
branches: [ main ]
permissions:
contents: read
id-token: write
env:
AWS_REGION: ap-southeast-1
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
aws-region: ${{ env.AWS_REGION }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install AWS SAM CLI
run: |
pip install aws-sam-cli
- name: Build
run: sam build
- name: Deploy (guided=false)
run: sam deploy --no-confirm-changeset --no-fail-on-empty-changeset --stack-name my-sam-app --r
Best Practices Pipeline GitHub Actions di AWS
• Gunakan OIDC + IAM Role, hindari long■lived access keys.
• Pisahkan pipeline CI (lint/test/build) vs CD (rilis/deploy).
• Gunakan environments & required reviewers untuk gate production.
• Manfaatkan cache & artifact untuk mempercepat build dan audit rilis.
• Terapkan policy least■privilege pada role deploy (ECR/ECS/EKS/Lambda saja).
• Versikan image dengan tag sha atau semver dan simpan SBOM/scan hasil (mis. Trivy) di step terpisah.
• Monitoring: CloudWatch, alarms, log aggregation; rollback otomatis bila rollout gagal.