UI vs. UX: What’s the difference?

Panduan Lengkap CI/CD dengan GitHub Actions

Di dunia pengembangan perangkat lunak yang serba cepat, setiap push kode idealnya langsung diperiksa, dibangun, dan siap rilis—tanpa ritual manual yang memakan waktu. Itulah peran CI/CD (Continuous Integration/Continuous Delivery/Deployment): mengotomatiskan pengujian, build, hingga deployment agar rilis lebih cepat, aman, dan konsisten. GitHub Actions memudahkan semua ini langsung di dalam GitHub: kamu menulis workflow YAML, memilih pemicu (push/PR/jadwal), dan runner GitHub mengeksekusinya untukmu.

Siapa target panduan ini & prasyarat

  • Target: developer web/backend/front-end (Node.js/React, Laravel/PHP, Python, Java) yang ingin membuat pipeline CI/CD praktis.
  • Prasyarat ringan: punya repo GitHub, bisa commit/push, dan punya skrip build/test dasar pada proyek.

Konsep inti GitHub Actions (singkat & jelas)

  • Workflow: file .yml di .github/workflows/ berisi alur otomatisasi.
  • Event/Trigger: pemicu workflow (mis. push, pull_request, workflow_dispatch, schedule).
  • Job: kumpulan langkah (steps) yang berjalan di runner (VM Ubuntu/Windows/macOS).
  • Step: perintah shell run atau action siap pakai (uses:).
  • Runner: mesin eksekusi (mis. ubuntu-latest).
  • Secrets: kredensial aman (token, kunci SSH) di repo Settings → Secrets and variables → Actions.
  • Environment: konteks seperti staging/production bisa pakai approval sebelum deploy.
  • Artifact: file hasil build/test report yang disimpan.
  • Cache: mempercepat pipeline (mis. cache dependency).
  • Matrix: uji di banyak versi/OS paralel.
  • Concurrency: cegah run menumpuk pada branch yang sama.

Gambaran besar alur CI/CD

1.CI saat push/PR: checkout → install dependensi → lint → test → build → upload artifact.

2.CD setelah CI lulus:

  • Frontend → GitHub Pages/VPS.
  • Backend → bangun image Docker, push ke registry (GHCR/Docker Hub), lalu deploy (VPS/Kubernetes/Cloud).

3.Environment & Approval: staging otomatis, production butuh persetujuan.

4.Release/Tag (opsional): tandai versi untuk audit/rollback.

Persiapan repo (5 menit)

1.Buat folder .github/workflows/.

2.Pastikan ada skrip di proyek (contoh Node.js di package.json):

{  

"scripts": {  

  "lint": "eslint .",  

  "test": "vitest run --coverage",  

  "build": "vite build"  } }
 

(Ganti sesuai stack: php artisan test, pytest, mvn test, dll.)

3.Tambahkan secrets yang diperlukan (contoh):

  • Deploy SSH: SSH_HOST, SSH_USER, SSH_KEY (private key).
  • Docker Hub: DOCKERHUB_USERNAME, DOCKERHUB_TOKEN.
  • Cloud/OIDC: kredensial/role yang diperlukan.

Bagian A — CI dasar (lint, test, build + artifact)

File: .github/workflows/ci.yml

name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

permissions:
  contents: read  # prinsip least privilege

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true  # batalkan run lama jika ada yang baru

jobs:
  build-test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18.x, 20.x]
      fail-fast: false

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'

      - name: Install deps
        run: npm ci

      - name: Lint
        run: npm run lint --if-present

      - name: Test
        run: npm test --if-present

      - name: Build
        run: npm run build --if-present

      - name: Upload artifact (build output)
        if: success()
        uses: actions/upload-artifact@v4
        with:
          name: app-dist
          path: |
            dist
            build

Kenapa ini penting: memastikan setiap perubahan selalu teruji & bisa dibangun di lingkungan bersih (runner), bukan hanya di laptopmu.

Alternatif setup bahasa lain (di step “Setup …”):

  • Python: actions/setup-python@v5 + pip install -r requirements.txt + pytest
  • PHP/Laravel: shivammathur/setup-php@v2 + composer install + php artisan test
  • Java/Maven: actions/setup-java@v4 + mvn -B verify

Bagian B — Continuous Delivery: build & push Docker image

Bangun image & push ke GitHub Container Registry (GHCR) setiap push ke main.

File: .github/workflows/docker.yml

name: Docker CI/CD

on:
  push:
    branches: [ main ]
    paths:
      - 'Dockerfile'
      - '**/*.ts'
      - '**/*.js'
      - 'package.json'
      - 'pnpm-lock.yaml'
      - 'package-lock.json'

permissions:
  contents: read
  packages: write
  id-token: write  # disarankan untuk OIDC ke cloud (opsional)

env:
  IMAGE_NAME: ghcr.io/${{ github.repository }}

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

      - name: Set up QEMU (multi-arch)
        uses: docker/setup-qemu-action@v3

      - name: Set up Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.IMAGE_NAME }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          platforms: linux/amd64,linux/arm64
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Pakai Docker Hub? Ubah login:

- uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKERHUB_USERNAME }}
    password: ${{ secrets.DOCKERHUB_TOKEN }}
env:
  IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/nama-image

Bagian C — Continuous Deployment (opsi yang paling umum)

Opsi 1: Deploy frontend ke GitHub Pages (SPA/React/Vite)

Sekali di UI: Settings → Pages → Source: GitHub Actions.

File: .github/workflows/pages.yml

name: Deploy to GitHub Pages

on:
  push:
    branches: [ main ]
  workflow_dispatch: {}

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: true

jobs:
  build:
    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
      - name: Upload Pages artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: ./dist

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: production
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4

Tips SPA: atur base di vite.config (jika repo bukan root) dan SPA fallback bila perlu.

Opsi 2: Deploy ke VPS via SSH (statik/backend Node)

Prasyarat server: user non-root, public key ada di ~/.ssh/authorized_keys, web root jelas.
Secrets: SSH_HOST, SSH_USER, SSH_KEY.

File: .github/workflows/deploy-ssh.yml

name: Deploy to VPS via SSH

on:
  push:
    branches: [ main ]
  workflow_dispatch: {}

permissions:
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://your-domain.com
    steps:
      - uses: actions/checkout@v4

      - name: Build app (contoh front-end)
        run: |
          npm ci
          npm run build

      - name: Upload build to server
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          source: "dist/*"
          target: "/var/www/myapp"

      - name: Restart service (contoh backend Node)
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /var/www/myapp
            pm2 reload myapp || pm2 start server.js --name myapp

Opsi 3: Deploy ke Cloud via OIDC (contoh AWS S3 static hosting)

Ide: tanpa static keys; runner menukar ID Token ke kredensial sementara.

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployer
    aws-region: ap-southeast-1

- name: Sync to S3
  run: aws s3 sync dist s3://nama-bucket --delete

Opsi 4: Kubernetes (ringkas)

Asumsikan kubeconfig disimpan di secret KUBE_CONFIG.

- name: Set kubeconfig
  run: |
    mkdir -p $HOME/.kube
    echo "${{ secrets.KUBE_CONFIG }}" > $HOME/.kube/config

- name: Rollout new image
  run: |
    kubectl set image deployment/myapp myapp=${{ env.IMAGE_NAME }}:latest
    kubectl rollout status deployment/myapp

Bagian D — Monorepo & workflow pintar

Jalankan hanya saat folder tertentu berubah:

on:
  push:
    branches: [ main ]
    paths:
      - 'apps/web/**'
      - '!**.md'

Gunakan filter canggih (dorny/paths-filter) + fan-out jobs:

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      web: ${{ steps.filter.outputs.web }}
      api: ${{ steps.filter.outputs.api }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            web:
              - 'apps/web/**'
            api:
              - 'apps/api/**'

  web-ci:
    needs: changes
    if: needs.changes.outputs.web == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # ... langkah CI untuk web

  api-ci:
    needs: changes
    if: needs.changes.outputs.api == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # ... langkah CI untuk api

Reusable workflow (antar-repo/proyek):

# .github/workflows/reuse-ci.yml
name: Reusable CI
on:
  workflow_call:
    inputs:
      node:
        required: true
        type: string

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node }}
      - run: npm ci && npm test && npm run build

Pemanggil:

jobs:
  use-shared-ci:
    uses: owner/repo/.github/workflows/reuse-ci.yml@main
    with:
      node: '20'

Bagian E — Keamanan & izin (harus dibaca!)

  • Least privilege: set permissions minimal; buka hanya yang perlu (mis. packages: write saat push image).
  • Jangan pernah mencetak secrets ke log.
  • Pisahkan secrets per-environment (staging vs production).
  • Pin actions minimal ke major (lebih ketat: ke commit SHA) untuk mengurangi risiko supply chain.
  • Branch protection: wajibkan PR review + status checks (CI) lulus sebelum merge.
  • Dependabot: otomatisasi update dependency & actions.

Bagian F — Observability & troubleshooting

  • Logs: buka run → klik job → step → lihat log (error jelas di sini).
  • Rerun: jalankan ulang job/step yang gagal.
  • Debug verbose: aktifkan ACTIONS_STEP_DEBUG=true di repo (Settings → Actions → enable debug).
  • Masalah umum & solusinya:
GejalaPenyebab UmumSolusi Cepat
Cache tidak pernah hitkey tidak stabil/path salahPakai hashFiles pada lockfile, cek path
Gagal push ke GHCR/Dockerpermissions kurangTambah packages: write (GHCR) / login action Docker
SSH gagalFormat key/izin serverPastikan OpenSSH key, izin file benar, IP runner diizinkan
SPA di Pages 404Tidak ada fallback/baseAtur base & fallback SPA (config bundler/redirects)
Build berbeda dgn lokalVersi Node/OS bedaTetapkan versi (matrix), pakai npm ci, bersihkan cache

Checklist implementasi cepat

  •  CI lint + test + build + upload artifact
  •  CD: build & push Docker (opsional)
  •  CD: deploy (GitHub Pages / VPS / Cloud / K8s)
  •  Environment staging & production + approval
  •  Secrets aman & permissions minimal
  •  Concurrency untuk cegah job menumpuk
  •  Filter paths / reusable workflows (untuk monorepo)
  •  Dependabot & pin actions

Kesimpulan (versi inspiratif & profesional)

GitHub Actions mengubah setiap push menjadi proses rilis yang teruji, bisa direproduksi, dan siap produksi—tanpa kerja manual berulang. Dengan pipeline CI/CD yang rapi, kamu bukan hanya mempercepat rilis fitur; kamu juga meningkatkan kualitas, mengurangi risiko, dan memberi tim ruang untuk fokus pada hal yang benar-benar penting: membangun produk yang hebat. Mulailah dari CI dasar, tambahkan CD yang sesuai target deploy-mu, lalu tingkatkan keamanan dan kecepatan seiring kebutuhan—pipeline-mu akan tumbuh bersama produkmu.