Pada pipeline CI/CD yang modern, permasalahan utama bukan hanya menjalankan banyak cakupan pengujian—tetapi juga menjaga waktu eksekusi tetap pendek. Dengan matrix environment, Anda bisa menjalankan build pada beberapa kombinasi sistem operasi, versi runtime, atau dependensi target secara paralel. Namun tanpa caching, setiap tugas tetap mengunduh ulang paket dan membangun dari awal. Dalam artikel ini kita langsung bahas konfigurasi GitHub Actions dan GitLab CI yang menggabungkan matrix environment dengan cache deterministik, serta strategi fallback ketika cache tidak tersedia.
1. Konsep Matrix Environment dan Manfaatnya
Matrix environment memungkinkan mendefinisikan beberapa kombinasi parameter (misalnya sistem operasi dan versi Node.js) dalam satu workflow. Ini penting untuk memastikan kompatibilitas lintas target tanpa membuat workflow terpisah untuk setiap kombinasi.
Prinsip dasarnya adalah:
- Setiap kombinasi dijalankan di job terpisah sehingga bisa berjalan paralel.
- Ambil repository workspace yang sama, lalu gunakan cache agar dependensi tidak diunduh ulang.
- Gunakan strategi caching yang deterministik agar cache reuse bisa terjadi meski matrix berkembang.
2. Strategi Cache Deterministik
Cache yang baik membutuhkan key yang konsisten tapi cukup spesifik. Jika terlalu umum, build bisa menerima cache usang; jika terlalu spesifik, cache tidak pernah reuse. Pendekatan yang berhasil biasanya mencakup:
- Bagian statis: Nama tool dan versi environment (contoh:
node-18-linux). - Hash file lock: Hash dari
package-lock.jsonatau sejenisnya. - Fallback key: Menyediakan prefix umum untuk digunakan saat cache miss spesifik.
Contoh key GitHub Actions: node-18-linux-${{ hashFiles('package-lock.json') }} dengan fallback key node-18-linux-. Dengan fallback, cache tetap bisa digunakan meski file hash berubah drastis.
3. Implementasi GitHub Actions
Berikut contoh workflow minimal yang menggabungkan matrix dan cache cache npm:
name: CI
on: [push]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
Dalam example ini, actions/setup-node sudah menyediakan caching bawaan. Namun untuk kontrol penuh (misalnya caching artifacts yang bukan npm), Anda dapat memakai actions/cache langsung, dengan key seperti berikut:
- name: Cache node_modules
uses: actions/cache@v4
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ matrix.node }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ matrix.node }}-
Dengan restore key yang lebih umum, cache masih bisa digunakan saat hash baru dan cache spesifik belum tersedia.
4. Konfigurasi GitLab CI Parallel Matrix
GitLab CI tidak menyediakan key matrix langsung, tetapi mendukung parallel matrix menggunakan matrix: pada job. Berikut contoh:
stages:
- test
test_job:
stage: test
parallel:
matrix:
- OS: [ubuntu:22.04, ubuntu:20.04]
- NODE_IMAGE: [node:18, node:20]
script:
- echo "Running on $OS with $NODE_IMAGE"
- npm ci
- npm test
cache:
key: "$OS-$NODE_IMAGE-$CI_PROJECT_ID-${CI_COMMIT_REF_SLUG}"
paths:
- node_modules/
Perhatikan cache key menggunakan kombinasi OS dan image agar setiap lingkungan mendapat cache sendiri. Jika ingin fallback, tambahkan key yang lebih umum dan atur when: on_failure untuk menarik cache umum jika spesifik gagal:
cache:
key:
files:
- package-lock.json
prefix: "$OS-$NODE_IMAGE"
paths:
- node_modules/
policy: pull-push
5. Strategi Cache Miss dan Debugging
Cache miss bisa terjadi karena:
- Perubahan file lock menghasilkan hash baru.
- Pipeline dijalankan pada branch baru tanpa cache.
- Key terlalu spesifik (misalnya menyertakan timestamp).
Solusi:
- Gunakan restore-keys (GitHub Actions) atau prefix plus files (GitLab) agar cache tetap digunakan jika key utama gagal.
- Log detail cache: pada GitHub Actions terlihat di output apakah cache hit atau miss. Pastikan
actions/cachemenulis pesan yang mencantumkan key yang dicoba. - Verifikasi bahwa path yang dicache sesuai (misalnya npm menyimpan dependensi di
node_modulestapi Anda hanya mencache.npm). - Gunakan perintah seperti
ls -lasebelum dan sesudah restore cache untuk memastikan konten terisi.
6. Metrik Performa dan Evaluasi
Ukuran dampak dapat diamati dengan membandingkan durasi job sebelum dan sesudah penerapan matrix + cache. Contoh nyata:
- Sebelum: Job tunggal Ubuntu Node.js 18, install full packages membutuhkan ~3m10s.
- Setelah: Matrix 2 OS x 2 Node, tetapi setiap job memanfaatkan cache sehingga tahap install turun menjadi ~45s per job.
- Durasi pipeline keseluruhan: 1m10s sebelum vs 1m30s setelah (meskipun lebih lama total karena paralel, latency balik/merge request turun karena job selesai lebih cepat).
Gunakan monitoring CI (misalnya GitHub Actions timing atau GitLab Pipeline duration) untuk memantau varian durasi dan cache hit rate—terutama pada branch pengembang yang sering berubah.
7. Kesimpulan dan Best Practice
Menggabungkan matrix environment dengan strategi cache deterministik mengurangi waktu eksekusi berulang tanpa mengorbankan coverage. Perhatikan:
- Cache key harus stabil tapi cukup spesifik.
- Selalu sediakan fallback key untuk cache miss.
- Gunakan logging dan perintah diagnostik untuk memastikan cache benar-benar terpakai.
Dengan pendekatan ini, pipeline CI/CD menjadi lebih cepat, paralel, dan efektif dalam menjamin kualitas lintas target tanpa penalti performa yang signifikan.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!