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: CIon: 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 buildEvents dan Triggers
Common Events
on: # Push to specific branches push: branches: - main - "release/*" paths: - "src/**" - "!src/**/*.md"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 testbuild: 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: 18steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm testEnvironment Variables
Set Variables
env: NODE_ENV: production API_URL: https://api.example.comjobs: 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-levelSecrets
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 deploymentGitHub 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 ciArtifacts
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: 7deploy:
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/CDon: 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 Buildon: 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=maxDeploy 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 Buildon: 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: Mainon: 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 versionUse 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@v4Use 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