Beranda / Kursus / CI/CD for Beginners / II — Praktik
II — Praktik
Artikel 4 dari 6

Build, Secrets & Environment Variables

Upgrade pipeline dasar dengan tiga hal: matrix build untuk test di beberapa versi Node sekaligus, GitHub Secrets untuk menyimpan credential dengan aman, dan job build terpisah yang menghasilkan artifact siap deploy.

10 Juli 2026

Workflow kita di artikel sebelumnya sudah jalan, tapi masih dasar banget: satu job, satu versi Node, dan belum ada konsep menyimpan credential dengan aman. Di artikel ini kita upgrade tiga hal: matrix build, GitHub Secrets, dan job build terpisah yang menghasilkan artifact.

Matrix Build — Test di Beberapa Versi Node Sekaligus

Kadang kita perlu memastikan kode kita jalan di beberapa versi Node — misalnya karena sebagian tim masih pakai Node 18, sebagian sudah pindah ke Node 20. Daripada bikin job terpisah-pisah secara manual, GitHub Actions punya fitur bernama matrix.

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [18, 20]

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: 'npm'
      - run: npm ci
      - run: npm test

Dengan strategy.matrix, satu definisi job ini otomatis "digandakan" jadi dua job yang jalan paralel: satu pakai Node 18, satu pakai Node 20. Kalau salah satu gagal, kita langsung tahu versi Node mana yang bermasalah.

Satu catatan penting: karena sekarang job test pecah jadi dua check terpisah, kalau kamu sudah setting branch protection di artikel sebelumnya, buka lagi Settings → Branches, dan update supaya kedua status check (test (18) dan test (20)) sama-sama wajib lolos.

GitHub Secrets — Menyimpan Credential dengan Aman

Sekarang bayangkan kamu butuh API key untuk konek ke layanan eksternal — payment gateway, email service, apa pun. Jangan pernah hardcode credential di kode atau commit ke repo, walaupun repo-nya private. Solusinya: GitHub Secrets.

Langkahnya:

  • Masuk ke Settings → Secrets and variables → Actions → New repository secret.
  • Nama: DEMO_API_KEY, value: nilai apa saja untuk demo (misal sk_demo_12345).
  • Save.
  • Secret ini terenkripsi, tidak akan pernah muncul di kode, dan cuma bisa diakses dari dalam workflow lewat context secrets.

    Tambahkan step baru di job build (dijelaskan di bagian berikutnya):

    - name: Demo penggunaan secret (dengan masking otomatis)
      env:
        DEMO_API_KEY: ${{ secrets.DEMO_API_KEY }}
      run: |
        echo "Mencoba print langsung (akan otomatis di-mask oleh GitHub): $DEMO_API_KEY"
        echo "DEMO_API_KEY terpasang, panjang: ${#DEMO_API_KEY} karakter"
    

    Perhatikan baik-baik hasil log-nya nanti: walaupun kita coba echo nilai secret-nya langsung, GitHub otomatis mengganti tampilannya jadi *** di log. Ini fitur keamanan bawaan supaya secret tidak bocor lewat log, bahkan kalau developer tidak sengaja nge-print-nya.

    Tapi jangan andalkan masking ini sebagai satu-satunya proteksi. Best practice-nya: hindari nge-print secret sama sekali. Cara yang lebih aman kalau cuma mau memverifikasi secret-nya terpasang, cukup cek panjang karakternya seperti contoh di atas.

    Job build — Memisahkan Test dan Packaging, Pakai needs

    Sekarang kita pisahkan concern-nya. Job test fokus memastikan kode benar. Job baru, build, fokus menyiapkan paket yang siap di-deploy — ini yang nanti menjadi "artifact" yang konsepnya sudah dibahas di artikel anatomi pipeline.

    build:
      needs: test
      runs-on: ubuntu-latest
    
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-node@v4
          with:
            node-version: '20'
            cache: 'npm'
    
        - name: Install production dependencies
          run: npm ci --omit=dev
    
        - name: Demo penggunaan secret (dengan masking otomatis)
          env:
            DEMO_API_KEY: ${{ secrets.DEMO_API_KEY }}
          run: |
            echo "DEMO_API_KEY terpasang, panjang: ${#DEMO_API_KEY} karakter"
    
        - name: Package aplikasi jadi artifact
          run: zip -r release.zip . -x "tests/*" -x ".git/*" -x "*.test.js" -x "coverage/*"
    
        - name: Upload artifact
          uses: actions/upload-artifact@v4
          with:
            name: task-tracker-api-build
            path: release.zip
            retention-days: 7
    

    Poin-poin yang perlu dipahami:

  • needs: test — job build baru mulai jalan setelah SEMUA job dalam matrix test sukses. Ini yang membuat job berurutan (sequential), berbeda dengan default yang paralel.
  • npm ci --omit=dev — untuk packaging, kita tidak butuh dev dependency seperti Jest, jadi cuma install yang perlu untuk runtime.
  • zip -r release.zip ... — membuat satu file terkompresi berisi kode yang siap di-deploy, exclude file yang tidak perlu (test, coverage, .git).
  • actions/upload-artifact@v4 — upload release.zip supaya bisa didownload dari halaman run, atau dipakai job lain nantinya (kita akan pakai konsep ini lagi saat membahas deployment).
  • Setelah run selesai, scroll ke bagian bawah halaman run itu, kamu akan melihat artifact task-tracker-api-build yang bisa didownload langsung. Coba download dan extract — isinya persis kode aplikasi kita yang sudah siap deploy, tanpa file test.

    Kenapa Ini Penting?

    Kenapa kita repot-repot memisahkan build dari test, dan pakai artifact? Karena begitu kode di-build sekali dan lolos test, kita tidak perlu build ulang dari nol tiap mau deploy. Artifact yang sama, yang sudah teruji itu, yang kita bawa terus sampai ke production — prinsip "build once, deploy everywhere". Ini juga yang mencegah kasus "kok di staging jalan tapi di production beda hasilnya", karena artifact-nya identik.

    Rangkuman

  • Matrix build untuk test multi-versi Node sekaligus.
  • GitHub Secrets untuk menyimpan credential dengan aman.
  • Job build terpisah yang menghasilkan artifact lewat needs, supaya urutannya benar.
  • Topik

    CI/CDGitHub Actions