Kembali ke Blog
Cara Setup CI/CD dengan GitHub Actions
GitHub Actions memungkinkan automation workflow untuk CI/CD. Mari pelajari cara setup dari dasar.
Apa itu GitHub Actions?
Konsep Dasar
GitHub Actions adalah:
- CI/CD platform built into GitHub
- Automate workflows (build, test, deploy)
- Event-driven (push, PR, schedule)
- Free untuk public repos
- 2000 minutes/month untuk private (free tier)
Terminologi
Workflow: Automation process (.yml file)
Job: Set of steps in workflow
Step: Individual task
Action: Reusable unit of code
Runner: Server yang menjalankan workflow
Event: Trigger untuk workflow
Basic Workflow
File Structure
repository/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── deploy.yml
├── src/
└── package.json
Simple CI Workflow
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
Events dan Triggers
Common Events
on:
# Push to specific branches
push:
branches:
- main
- "release/*"
paths:
- "src/**"
- "!src/**/*.md"
# Pull request
pull_request:
branches: [main]
types: [opened, synchronize, reopened]
# Manual trigger
workflow_dispatch:
inputs:
environment:
description: "Environment to deploy"
required: true
default: "staging"
type: choice
options:
- staging
- production
# Scheduled
schedule:
- cron: "0 0 * * *" # Daily at midnight
# Release
release:
types: [published]
Jobs dan Steps
Multiple Jobs
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run tests
run: npm test
build:
runs-on: ubuntu-latest
needs: test # Wait for test job
steps:
- uses: actions/checkout@v4
- name: Build
run: npm run build
deploy:
runs-on: ubuntu-latest
needs: [test, build] # Wait for both
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy
run: echo "Deploying..."
Matrix Strategy
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20, 22]
exclude:
- os: windows-latest
node-version: 18
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm test
Environment Variables
Set Variables
env:
NODE_ENV: production
API_URL: https://api.example.com
jobs:
build:
runs-on: ubuntu-latest
env:
BUILD_DIR: ./dist
steps:
- name: Use env vars
run: |
echo "Node env: $NODE_ENV"
echo "Build dir: $BUILD_DIR"
env:
STEP_VAR: step-level
Secrets
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to server
env:
SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
API_TOKEN: ${{ secrets.API_TOKEN }}
run: |
echo "$SSH_KEY" > key.pem
chmod 600 key.pem
# Use for deployment
GitHub Context
steps:
- name: Use GitHub context
run: |
echo "Repository: ${{ github.repository }}"
echo "Branch: ${{ github.ref_name }}"
echo "SHA: ${{ github.sha }}"
echo "Actor: ${{ github.actor }}"
echo "Event: ${{ github.event_name }}"
Caching
Cache Dependencies
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js with cache
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
# Or manual caching
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
Artifacts
Upload Artifacts
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-files
path: dist/
retention-days: 7
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: build-files
path: dist/
Common Workflows
Node.js CI/CD
name: Node.js CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run lint
- run: npm test
build:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/
- name: Deploy to server
run: |
# Add deployment commands
echo "Deploying..."
Docker Build & Push
name: Docker Build
on:
push:
branches: [main]
tags: ["v*"]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
username/app:latest
username/app:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Deploy to Cloud
# Vercel
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: "--prod"
# Netlify
- name: Deploy to Netlify
uses: nwtgck/actions-netlify@v3
with:
publish-dir: "./dist"
production-branch: main
github-token: ${{ secrets.GITHUB_TOKEN }}
deploy-message: "Deploy from GitHub Actions"
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
# AWS S3
- name: Deploy to S3
uses: jakejarvis/s3-sync-action@master
with:
args: --delete
env:
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
SOURCE_DIR: "dist"
Reusable Workflows
Create Reusable Workflow
# .github/workflows/reusable-build.yml
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
required: false
type: string
default: "20"
secrets:
npm-token:
required: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm run build
Use Reusable Workflow
# .github/workflows/main.yml
name: Main
on:
push:
branches: [main]
jobs:
build:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: "20"
secrets:
npm-token: ${{ secrets.NPM_TOKEN }}
Best Practices
Security
# Pin action versions
- uses: actions/checkout@v4 # Use specific version
# Use secrets for sensitive data
env:
API_KEY: ${{ secrets.API_KEY }}
# Limit permissions
permissions:
contents: read
pull-requests: write
# Use environments for production
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
Performance
# Enable caching
- uses: actions/cache@v4
# Use fail-fast
strategy:
fail-fast: true
# Cancel in-progress runs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Kesimpulan
GitHub Actions adalah powerful tool untuk CI/CD yang terintegrasi langsung dengan GitHub. Mulai dengan simple workflow lalu kembangkan sesuai kebutuhan project.
Ditulis oleh
Hendra Wijaya
Artikel Sebelumnya
Cara Setup dan Menggunakan Bing Webmaster Tools
Artikel Selanjutnya
Cara Setup Email Marketing untuk Bisnis