Episode ini membahas cara menyimpan hasil build dengan artifacts (paths, name, expire_in, when), mentransfernya antar job dan stage, membatasi transfer dengan dependencies, mengunduhnya via UI dan API, lalu mempublikasikan paket ke GitLab Package Registry.

Di episode 6 kita membangun Docker image di dalam pipeline dan mem-push-nya ke GitLab Container Registry — contoh sempurna bagaimana output sebuah job disimpan untuk dipakai job lain. Tapi image bukan satu-satunya output yang perlu berpindah. Binary aplikasi, arsip zip, laporan test, coverage report — semua ini dihasilkan di satu job dan dibutuhkan di job lain. Kalau tidak dikelola, setiap job terpaksa membangun ulang dari nol, dan pipeline kalian jadi lambat serta boros.
Di episode ini kita akan membedah artifacts — mekanisme GitLab untuk menyimpan dan mentransfer output job — lalu menyambungkannya dengan GitLab Package Registry, tempat kalian mempublikasikan paket yang bisa dipakai lintas project, bahkan lintas tim. Ini adalah episode yang menjembatani "hasil build" dengan "konsumsi hasil build".
artifactsSetiap job yang selesai bisa menyerahkan file atau direktori tertentu untuk disimpan GitLab. Ketika job berikutnya dimulai, file itu otomatis diunduh dan tersedia di dalam workspace-nya. Mari lihat contoh paling umum:
build_app:
stage: build
image: node:20-alpine
script:
- npm ci
- npm run build
artifacts:
paths:
- dist/
- coverage/
name: "$CI_COMMIT_REF_NAME"
expire_in: 1 week
when: on_successEmpat keyword kunci yang perlu dipahami:
paths — daftar file/direktori yang disimpan. Di sini dist/ (hasil build) dan coverage/ (laporan) ikut disimpan.name — nama arsip saat diunduh via UI. $CI_COMMIT_REF_NAME membuat nama berisi nama branch, jadi arsip tiap branch tidak tertimpa.expire_in: 1 week — masa berlaku artifact. GitLab akan menghapusnya otomatis setelah seminggu. Nilai penting ini menghemat storage; artifact lama jarang dipakai.when — kapan artifact disimpan. on_success (default) hanya saat job sukses. Opsi lain: on_failure (berguna untuk menyimpan log/debug saat gagal) dan always (disimpan apa pun hasilnya).Tip
Gunakan when: on_failure pada job test untuk menyimpan screenshot atau log gagal — ini cara tercepat menemukan penyebab kegagalan tanpa harus menjalankan ulang pipeline. Kombinasi when: always + expire_in pendek juga populer untuk laporan yang wajib tersedia apa pun hasilnya.
Pola alur kerja GitLab: artifacts dari stage sebelumnya otomatis ditransfer ke semua job di stage berikutnya. Jika build_app di stage build menghasilkan dist/, maka semua job di stage deploy bisa langsung membaca dist/ tanpa konfigurasi tambahan.
Masalahnya, "semua job menerima semua artifacts" bisa boros — terutama bila artifact berukuran ratusan MB dan job deploy hanya butuh sebagian. Di sinilah dependencies: berperan: ia membatasi artifact mana saja yang diterima sebuah job.
deploy_prod:
stage: deploy
image: alpine:latest
dependencies:
- build_app
script:
- ls dist/
- rsync -av dist/ deploy@server:/var/www/myappDengan dependencies: [build_app], job deploy_prod hanya menerima artifact dari job bernama build_app — bukan dari job lain di stage build. Perhatikan pula: dependencies hanya mengatur artifact mana yang diterima, bukan urutan eksekusi. Urutan antar job tetap diatur oleh stage (atau needs:, yang akan kita bahas di episode 9).
Warning
Hati-hati saat menulis daftar dependencies. Kalau nama job salah atau job itu di-skip oleh rules sehingga tidak menghasilkan artifact, pipeline bisa gagal. Selalu uji dengan sebuah push ke branch fitur, bukan langsung di main.
Selain otomatis di-transfer ke job berikutnya, artifacts juga bisa diunduh manusia. Di GitLab UI, buka halaman job → tab Browse untuk melihat struktur file-nya, atau klik Download untuk mengunduh arsipnya — berguna untuk mengambil build terakhir tanpa checkout kode.
Lewat API, job lain (atau script eksternal) bisa mengunduh artifacts dengan endpoint yang menerima token akses:
curl --header "PRIVATE-TOKEN: $API_TOKEN" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/$CI_JOB_ID/artifacts/download" \
--output build.zipKombinasi UI + API ini membuat artifacts menjadi jembatan antara pipeline dan manusia: QA mengambil build terbaru tanpa build manual, bot otomasi mengunduh hasil test untuk diproses lebih lanjut, dan tim release mengambil arsip untuk diarsipkan.
Artifacts adalah mekanisme internal pipeline. Tapi kadang kalian ingin mempublikasikan paket agar bisa dipakai project lain, atau bahkan tim di luar repo yang sama. GitLab menyediakan Package Registry bawaan yang mendukung banyak ekosistem dalam satu tempat:
| Ekosistem | Manajer paket | Endpoint GitLab |
|---|---|---|
| Node.js | npm / yarn | /api/v4/projects/ID/packages/npm/ |
| Java | Maven / Gradle | /api/v4/projects/ID/packages/maven/ |
| Python | pip / twine | /api/v4/projects/ID/packages/pypi/ |
| Go | go proxy | /api/v4/projects/ID/packages/go/ |
| Helm | helm repo | /api/v4/projects/ID/packages/helm/ |
Pola penerbitannya seragam: konfigurasi registry ke URL project, autentikasi dengan CI_JOB_TOKEN, lalu push dengan tool paket masing-masing. Contoh untuk npm:
publish_npm:
stage: deploy
image: node:20-alpine
script:
- echo "//${CI_SERVER_HOST}/api/v4/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=${CI_JOB_TOKEN}" > .npmrc
- npm ci
- npm publish --registry "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"
rules:
- if: $CI_COMMIT_TAGMari bedah: baris .npmrc menulis token autentikasi yang dibangun dari CI_JOB_TOKEN — token sementara yang otomatis disuntikkan GitLab ke setiap job, jadi tidak ada secret permanen yang perlu disimpan. rules: if: $CI_COMMIT_TAG memastikan paket hanya diterbitkan ketika ada tag rilis — pola umum agar versi paket sinkron dengan versi rilis. Nama dan versi paket diambil dari package.json project, dan GitLab memvalidasinya terhadap nama project saat publish.
Untuk Python (PyPI), polanya serupa — konfigurasi twine lalu push:
pip install twine
python -m twine upload \
--repository-url "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi" \
-u gitlab-ci-token -p "${CI_JOB_TOKEN}" dist/*Perhatikan dua hal yang konsisten di semua ekosistem: URL registry selalu berisi $CI_API_V4_URL + project ID, dan autentikasi selalu lewat $CI_JOB_TOKEN dengan username gitlab-ci-token (khusus PyPI). Setelah ter-publish, paket muncul di halaman Packages & Registries project dan bisa di-install dari project lain — ini fondasi untuk berbagi pustaka internal antar tim tanpa mempublikasikannya ke internet.
Note
Beberapa manajer paket perlu konfigurasi tambahan agar bisa mengunduh paket dari GitLab, bukan hanya mengunggah — misalnya npm butuh cakupan @scope:registry di .npmrc, dan Go butuh setting GOPROXY. Detailnya ada di dokumentasi Package Registry masing-masing ekosistem; yang penting di sini adalah memahami polanya: token job, URL API v4, dan project ID.
Pada episode 7 ini kalian telah menguasai alur "menyimpan dan memindahkan hasil build":
artifacts: paths: menyimpan output job; name, expire_in, dan when mengontrol penamaan, masa berlaku, dan kapan disimpan.dependencies: [job] membatasinya agar hanya artifact yang dibutuhkan yang diunduh.Yang perlu kalian sadari: artifacts menyimpan hasil akhir, tapi setiap job tetap harus mengunduh dependensi (node_modules, paket Maven) dari awal — dan itu bagian pipeline yang paling lambat. Di episode 8 kita akan membahas caching: bagaimana menyimpan dependensi sementara agar build berikutnya jauh lebih cepat, kapan memakai cache dan bukan artifacts, serta bagaimana menghubungkan runner ke object storage untuk cache yang dibagikan lintas runner. Sampai jumpa di episode 8!