Ringkasan Utama
Cara membuat CI/CD GitHub Actions untuk pemula: simpan file YAML di folder .github/workflows, picu dengan push dan pull_request, jalankan npm ci, typecheck, lint, dan test, lalu hubungkan job berikutnya dengan needs. Job yang gagal membuat job turunannya dilewati, dan branch protection membuat check merah benar-benar memblokir merge.
Kamu sudah menulis kode yang jalan di laptop, lalu push, dan baru sadar ada error tipe yang lolos ke branch main. Atau kamu membuka tab Actions untuk pertama kali dan melihat daftar kosong, tanpa tahu file apa yang harus dibuat dan di mana menyimpannya. Di titik ini hampir semua pemula menyalin YAML dari contoh orang lain, menekan push, dan berharap hasilnya hijau.
Panduan ini membangun satu workflow dari nol: satu file, dua job, dan beberapa pemeriksaan yang berurutan. Lalu kamu merusaknya dengan sengaja supaya melihat sendiri job berikutnya dilewati. Perintah dan nama key saya cocokkan dengan dokumentasi resmi GitHub dan npm. Polanya sama dengan workflow deploy situs ini (verify, lalu build, lalu deploy), tetapi dibuat sekecil mungkin. Output yang saya tulis hanya yang memang pasti keluar; tampilan tab Actions bisa sedikit berbeda dari waktu ke waktu.
Ingin konsepnya dulu? Pelajaran gratis kami membahas quality gate di GitHub Actions dan alur pipeline DevOps dari git push sampai production. Artikel ini sisi prakteknya: kamu menulis file, push, dan melihat hasilnya sendiri.
Yang kamu butuhkan
Tidak banyak, dan kamu tidak perlu server.
- Akun GitHub dan satu repository, dengan project Node.js yang punya package.json dan package-lock.json yang sudah di-commit.
- Node.js dan git terpasang di laptop, supaya kamu bisa menjalankan pemeriksaan yang sama secara lokal sebelum push.
- Script untuk typecheck dan lint. Contoh di sini memakai npx tsc --noEmit dan npm run lint; ganti dengan perintah project-mu.
Kalau project-mu belum memakai TypeScript atau linter, tidak apa-apa. Polanya sama untuk perintah apa pun yang berakhir dengan kode exit bukan nol saat gagal, dan itulah yang dilihat runner untuk menentukan lolos atau gagal.
Langkah 1: Jalankan pemeriksaan di laptop dulu
CI hanya mengulang di server apa yang bisa kamu jalankan di laptop. Jadi pastikan dulu perintah-perintah ini lolos secara lokal, dengan urutan yang nanti dipakai di CI: yang murah dan cepat di depan.
# npm ci deletes node_modules and installs exactly what package-lock.json says,
# which is the closest thing to a fresh CI runner on your own laptop.
npm ci
npx tsc --noEmit # prints nothing when the types are fine
npm run lint
npm test
# Each command exits with 0 on success. Check the last one:
echo $?
# 0Menurut dokumentasi npm, npm ci dibuat untuk lingkungan otomatis seperti CI: ia menghapus node_modules lebih dulu dan tidak pernah mengubah package.json atau file lock. Kalau package-lock.json tidak cocok dengan package.json, ia berhenti dengan error alih-alih memperbaikinya. Karena itu npm ci di laptop adalah latihan terbaik untuk runner yang bersih.
Kalau npm ci mengeluh soal lock file, biasanya package-lock.json tidak sinkron dengan package.json. Jalankan npm install sekali di laptop, commit file lock yang baru, lalu coba lagi.
Langkah 2: Tulis workflow pertama dan push
Workflow disimpan di folder .github/workflows di root repository, dan file-nya harus berekstensi .yml atau .yaml. Buat file ci.yml di sana. Bagian on menentukan pemicunya: di sini push ke branch main dan setiap pull request. Satu job bernama verify menjalankan step-nya berurutan di runner ubuntu-latest.
# .github/workflows/ci.yml
name: ci
on:
push:
branches: [main]
pull_request:
jobs:
verify:
name: Typecheck and lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx tsc --noEmit
- run: npm run lintAda dua jenis step. uses memanggil action siap pakai (checkout mengambil kode repository, setup-node memasang Node.js), sedangkan run menjalankan perintah shell biasa. Versi action di sini (v4) mengikuti workflow situs ini; contoh di dokumentasi GitHub sekarang sudah memakai major yang lebih baru, jadi cek halaman action-nya saat kamu menulis workflow baru. Dan perhatikan satu kesalahan nama folder yang sangat umum:
# Wrong: GitHub only reads .github/workflows (plural), so this file is ignored.
.github/workflow/ci.yml
# Right:
.github/workflows/ci.ymlSetelah itu commit dan push. Begitu push sampai ke main, GitHub membaca file-nya dan memulai run tanpa kamu menekan apa pun.
git add .github/workflows/ci.yml
git commit -m "ci: add first workflow"
git push origin mainLangkah 3: Baca hasilnya di tab Actions
Buka repository di GitHub lalu klik tab Actions. Urutan membaca hasilnya menurut dokumentasi GitHub:
- Pilih workflow ci di sidebar kiri.
- Klik run yang ingin kamu lihat dari daftar run.
- Di sidebar kiri bagian Jobs, klik job verify.
- Buka setiap step untuk melihat outputnya.
Kalau semua step lolos, job berwarna hijau. Kalau satu step merah, itu step yang gagal. Dokumentasi GitHub menjelaskan bahwa secara default sebuah step hanya berjalan jika step sebelumnya berhasil, jadi step di bawah step yang merah tidak dijalankan. Itu sebabnya satu job saja sudah berfungsi sebagai gate kecil.
Langkah 4: Pecah jadi dua job dengan needs
CI/CD butuh urutan antar tahap: periksa dulu, baru build. Menurut dokumentasi GitHub, job dalam satu workflow berjalan paralel secara default, dan needs adalah cara membuatnya berurutan. Tanpa needs, job build mulai bersamaan dengan verify, dan verify yang merah tidak menghentikannya.
# Wrong: no needs. Jobs run in parallel by default, so build starts at the
# same time as verify and a red verify does not stop it.
build:
runs-on: ubuntu-latest# Right: add this job under jobs: in ci.yml (it assumes an npm run build script).
# needs makes build wait for verify, and skips it when verify fails.
build:
needs: verify
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 buildAturannya dari dokumentasi: kalau sebuah job gagal atau dilewati, semua job yang membutuhkannya ikut dilewati, kecuali job itu memakai kondisi yang membuatnya tetap lanjut, misalnya always(). Kegagalan menjalar ke seluruh rantai setelah titik gagalnya.
# The same shape in this site's .github/workflows/deploy.yml (shortened):
jobs:
verify: # npm ci, tsc --noEmit, npm run lint
build-and-push:
needs: verify
deploy:
needs: build-and-pushRantai yang sama dipakai workflow deploy situs ini: verify menjalankan npm ci, typecheck, dan lint; build-and-push needs verify; deploy needs build-and-push. Untuk sisi deploy-nya (SSH, registry, Compose), baca CI/CD dengan GitHub Actions dari nol sampai production. Di panduan ini kita berhenti di gate-nya.
Langkah 5: Rusak dengan sengaja dan lihat job dilewati
Gate baru terbukti berfungsi kalau kamu pernah melihatnya menahan sesuatu. Tambahkan error tipe, cek dulu di laptop, lalu push.
// src/count.ts
const count: number = "three";npx tsc --noEmit
# Expect a TS2322 error: Type 'string' is not assignable to type 'number'.
git add -A
git commit -m "test: break the typecheck on purpose"
git push origin mainDi tab Actions, job verify berwarna merah dan berhenti di step typecheck. Step lint di bawahnya tidak dijalankan, dan job build ditandai dilewati (skipped), bukan berjalan. Tidak ada yang di-build. Itulah arti gate: commit yang salah berhenti di pintu pertama. Hapus baris tadi, push lagi, dan semuanya kembali hijau.
Job yang dilewati bukan berarti lolos. Yang kamu cari adalah merah di verify; build yang abu-abu hanyalah akibatnya. Kalau build justru hijau padahal verify merah, hampir pasti needs-nya hilang.
Langkah 6: Pastikan test benar-benar dipanggil CI
Script di package.json tidak melindungi apa pun sampai ada step yang memanggilnya. Ini nyata di situs ini: repo-nya punya script npm test, tetapi job verify di deploy.yml hanya menjalankan npm ci, typecheck, dan lint, jadi test yang gagal tidak akan menghentikan deploy di sini. Saya tulis apa adanya karena kamu akan menemukan celah yang sama kalau tidak mengeceknya.
# Wrong: package.json has a "test" script, but no step ever calls it.
- run: npm ci
- run: npx tsc --noEmit
- run: npm run lint
# Right: cheapest checks first, tests last, so a typo fails in seconds.
- run: npm ci
- run: npx tsc --noEmit
- run: npm run lint
- run: npm testUrutannya disengaja: pemeriksaan murah dulu. Typecheck dan lint melaporkan kesalahan jauh sebelum test atau build selesai, sehingga commit buruk gagal cepat dan job yang mahal tidak pernah dimulai. Kalau project-mu belum punya test, lewati step ini dan catat bahwa gate-mu belum mencakupnya.
Langkah 7: Buat check merah benar-benar memblokir merge
Workflow hanya melaporkan hasil. Yang membuatnya mengikat adalah branch protection dengan required status checks: menurut dokumentasi GitHub, semua check wajib harus lolos sebelum kolaborator bisa me-merge perubahan ke branch yang dilindungi. Aktifkan di pengaturan repository untuk branch main, lalu pilih check dari job verify; nama yang tampil mengikuti key name pada job itu.
Dua jebakan. Pertama, status berhasil, dilewati, dan netral semuanya memenuhi syarat, jadi check wajib yang tidak sengaja dilewati membuat tombol merge menjadi hijau. Kedua, nama job sebaiknya unik di semua workflow, karena nama yang dipakai ulang bisa memberi hasil ambigu dan memblokir merge. Satu hal lagi: deploy.yml situs ini hanya berjalan pada push ke main, bukan pada pull request, jadi gate untuk pull request membutuhkan workflow dengan pemicu pull_request, seperti ci.yml kita tadi. File di repo tidak bisa menunjukkan apakah branch protection menyala; itu ada di pengaturan GitHub.
Error umum dan cara memperbaikinya
Enam masalah yang paling sering membuat pemula berhenti, lengkap dengan penyebab dan perbaikannya.
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Workflow tidak muncul di tab Actions | File tidak ada di .github/workflows (misalnya salah ketik workflow tanpa s), ekstensinya bukan .yml atau .yaml, atau belum di-push. | Pindahkan ke .github/workflows/ci.yml di root repository, lalu push. |
| npm ci error saat instalasi | package-lock.json tidak ada atau tidak cocok dengan package.json. npm ci tidak memperbaikinya, ia berhenti dengan error. | Jalankan npm install di laptop, commit package-lock.json yang baru, lalu push lagi. |
| Job build tetap jalan padahal verify merah | Job build tidak punya needs, jadi berjalan paralel dengan verify. | Tambahkan needs: verify pada job build. |
| Hijau di laptop, merah di CI | Runner mulai dari kondisi bersih: file yang belum di-commit tidak ada di sana, dan versi Node bisa berbeda dari laptop. | Commit semua file yang dibutuhkan, samakan node-version dengan versi lokal, dan jalankan npm ci di laptop untuk meniru runner. |
| Test gagal, tetapi alur tetap lanjut | Tidak ada step yang memanggil npm test; script di package.json saja tidak cukup. | Tambahkan run: npm test di job verify, setelah typecheck dan lint. |
| Pull request tetap bisa di-merge walau check merah atau dilewati | Belum ada required status checks, atau check wajibnya dilewati (status dilewati dianggap memenuhi syarat). | Aktifkan branch protection dengan required status checks, pastikan job wajib berjalan di setiap pull request, dan jaga nama job tetap unik. |
Dua kebiasaan yang menghemat paling banyak waktu: jalankan perintah yang sama di laptop sebelum push, dan baca step merah dari atas ke bawah. Step merah pertama adalah penyebabnya; yang di bawahnya hanya korban.
Checklist sebelum CI kamu dianggap selesai
- File ada di .github/workflows dengan ekstensi .yml atau .yaml, dan sudah di-push.
- Pemicunya mencakup push ke main dan pull_request.
- Perintah di CI sama dengan yang kamu jalankan di laptop, yang murah dulu, yang mahal belakangan.
- Setiap job tahap berikutnya punya needs ke job yang harus menjaganya.
- Kamu sudah merusaknya dengan sengaja dan melihat job berikutnya dilewati, lalu required status checks menyala di branch main.
Belajar lebih dalam
Konsepnya ada di pelajaran gratis quality gate di GitHub Actions dan alur pipeline DevOps dari git push sampai production. Kalau ingin melihat pipeline sampai production, baca artikel di atas; kalau run-mu terasa lambat, lihat strategi caching GitHub Actions.
Aturan yang bisa kamu bawa: CI adalah apa yang benar-benar dijalankan workflow-mu, bukan apa yang tertulis di package.json; needs yang membuat urutan; dan branch protection yang membuat merah berarti berhenti. Mulailah dengan satu job kecil yang jujur, lalu tambahkan gate satu per satu.
Sumber dan referensi
- Dokumentasi GitHub: quickstart GitHub Actions (lokasi file workflow)
- Dokumentasi GitHub: sintaks workflow (on, jobs, job paralel)
- Dokumentasi GitHub: memakai job dalam workflow (needs)
- Dokumentasi GitHub: ekspresi dan fungsi status check (success)
- Dokumentasi GitHub: tentang protected branch (required status checks)
- Dokumentasi npm: npm ci

