Episode ini membahas cara berbagi hasil build antar job menggunakan artifacts dan mempercepat pipeline dengan caching dependensi, mulai dari upload dan download artifact hingga cache key dan restore key.

Di episode 6 kita belajar bahwa job berjalan paralel di runner yang terpisah — tidak ada sistem file bersama. Di episode 7 kita menggandakan job dengan matrix. Pertanyaan berikutnya yang pasti muncul: kalau begitu, bagaimana caranya job deploy mendapatkan file hasil build dari job build? Dan kenapa setiap kali push, npm ci harus mengunduh seluruh dependensi dari nol, padahal kemarin sudah sama?
Dua masalah ini diselesaikan oleh dua mekanisme berbeda yang sering tertukar: artifacts untuk memindahkan data antar job, dan caching untuk mempercepat instalasi dependensi antar run. Di episode ini kita akan membedah keduanya, kapan memakainya, dan contoh workflow lengkapnya.
Setiap job dimulai dengan runner yang bersih — kode checkout-nya sendiri, tidak ada sisa job lain. Context needs di episode 6 memang bisa meneruskan data, tetapi hanya berupa string pendek (misalnya output job). Kalau yang mau dipindahkan adalah file: bundle JavaScript, binary, file installer, atau laporan coverage — artifacts adalah jawabannya.
Analoginya: needs itu seperti menulis catatan di secarik kertas untuk rekan kerja; artifacts seperti mengirimkan kotak berisi barang lewat kurir. Keduanya sah, tapi jenisnya beda.
Untuk menyerahkan file dari sebuah job, gunakan actions/upload-artifact@v4. Ia mengemas direktori atau file menjadi satu paket bernama (name) yang disimpan GitHub:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: bundle
path: dist/
retention-days: 7name adalah identitas paket, path menentukan file atau direktori yang dikemas, dan retention-days mengatur berapa hari GitHub menyimpannya sebelum dibuang (default 90 hari). Artifacts juga bisa diunduh manual lewat UI tab "Actions" — berguna untuk mengambil file installer tanpa menunggu deploy.
Di job lain, paket tersebut diambil dengan actions/download-artifact@v4:
jobs:
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/download-artifact@v4
with:
name: bundle
path: dist/
- run: ./deploy.shJob deploy menunggu build (via needs), lalu menyalin isi paket bundle ke direktori dist/ di runner-nya sendiri. Kini file yang dibangun di satu runner bisa dikonsumsi di runner lain.
Gabungan keduanya menghasilkan pipeline build-then-deploy yang jujur — deploy selalu memakai file hasil build yang sama persis:
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
- uses: actions/upload-artifact@v4
with:
name: bundle
path: dist/
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/download-artifact@v4
with:
name: bundle
path: dist/
- run: ./deploy.shNote
Artifacts tidak bisa dibagikan lintas run workflow — paket dibuat dan dipakai dalam satu run yang sama, lalu disimpan beberapa hari untuk keperluan debugging manual. Jika kalian butuh menyimpan file untuk waktu lama (misalnya binary rilis), gunakan GitHub Releases, bukan artifacts.
Masalah kedua adalah kecepatan. npm ci mengunduh dan menginstal seluruh node_modules setiap kali pipeline jalan — padahal isinya hampir tidak berubah antar push. Cache menyimpan direktori yang mahal untuk dibuat ulang (dependensi, toolchain, layer build) dan memulihkannya di run berikutnya.
Cache dikunci oleh sebuah cache key. Bila key cocok, isi cache di-restore; bila tidak, job tetap jalan tapi hasil baru disimpan sebagai cache baru. Ini membedakan cache dari artifacts: cache bersifat per-repo dan persisten lintas run, artifacts per-run.
Cara termudah — tanpa menulis apa pun selain satu baris — adalah memakai fitur cache bawaan pada setup actions. Actions seperti setup-node, setup-python, dan setup-go punya opsi cache yang otomatis menyimpan dan memulihkan dependensi sesuai ekosistemnya:
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ciDengan cache: npm, setup-node sendiri yang menempatkan cache di ~/.npm dan menentukan key berdasarkan lockfile. Jika lockfile kalian bukan di root, tunjukkan lokasinya dengan cache-dependency-path. Python dan Go memakai pola yang sama: cache: pip dan cache: go.
Untuk kendali penuh, ada actions/cache@v4. Kuncinya adalah kombinasi beberapa faktor — sistem operasi runner dan hash isi lockfile:
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-Bagaimana cara membacanya? runner.os memisahkan cache per sistem operasi (Linux, Windows, macOS) agar tidak saling menimpa. hashFiles menghasilkan hash dari isi package-lock.json — key berubah hanya ketika dependensi benar-benar berubah. Sedangkan restore-keys adalah pencadangan: bila key persis tidak ditemukan, GitHub mencari key terbaru dengan prefix tersebut, misalnya Linux-npm- — sebagian cache lebih baik daripada tidak ada cache sama sekali.
Tip
Defaultnya, cache hanya bisa dibaca dari branch yang sama (dan branch default). restore-keys menjadi jembatan yang penting: ia memungkinkan pull request dari branch fitur memulihkan cache milik branch default. Simpan direktori ~/.npm (bukan node_modules) karena npm ci akan menghapus node_modules saat dimulai.
| Aspek | Artifact | Cache |
|---|---|---|
| Tujuan | Memindahkan file antar job | Menyimpan ulang hasil build/instalasi |
| Masa hidup | Per run, disimpan 90 hari (default) | Persisten lintas run, bisa di-expire |
| Isi | Hasil build, binary, laporan | Dependensi, toolchain, layer build |
| Bisa diunduh manual | Ya, lewat UI | Tidak |
| Biaya | Kecil, per-run | Kuota penyimpanan tersendiri |
| Kesalahan | Gejala | Solusi |
|---|---|---|
Cache isi node_modules untuk npm ci | Cache selalu miss, tidak berguna | Cache ~/.npm saja |
Key cache tanpa hashFiles | Cache lama selalu dipakai | Sertakan hash lockfile di key |
Download artifact tanpa needs | Race condition, file belum ada | Tambah needs ke job build |
retention-days terlalu pendek | Artifact hilang sebelum audit | Sesuaikan dengan kebijakan tim |
| Mengira cache = artifacts | File "cache" diunduh manual | Gunakan upload/download artifact |
Artifacts dan caching adalah dua sisi dari optimasi workflow multi-job:
upload-artifact@v4 → download-artifact@v4) dengan pengaturan retention-days.cache: npm, cache: pip, cache: go) memberi cache otomatis; actions/cache@v4 memberi kendali penuh lewat key dan restore-keys.runner.os + hashFiles menjaga cache tetap tepat sasaran dan aman per platform.Di episode 9 selanjutnya, kita masuk fase keamanan: Secret Management & Security Best Practices — bagaimana menyimpan password dan API key dengan aman, mencegah script injection, dan menerapkan least privilege pada GITHUB_TOKEN. Karena pipeline yang cepat tidak ada artinya jika mudah dibobol!