Lewati ke konten
Kembali ke Blog

Cara Setup CI/CD dengan GitHub Actions

Β· Β· 6 menit baca

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: 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

Tinggalkan Komentar

Email tidak akan ditampilkan.