Menguasai dua kata kunci utama workflow: run untuk eksekusi perintah shell dan uses untuk memakai action dari Marketplace, lengkap dengan contoh workflow CI Node.js dan cara memilih versi action yang aman.

Di episode 3 kalian sudah bisa menulis workflow dan memilih event trigger yang tepat. Sekarang kita masuk ke jantung setiap job: langkah-langkah (steps). Dua kata kunci yang akan menghiasi hampir semua workflow kalian adalah run dan uses — keduanya adalah dua cara berbeda untuk mengisi sebuah step.
run mengeksekusi perintah shell langsung, sedangkan uses memanggil action siap pakai dari GitHub Marketplace. Memahami kapan memakai yang mana, bagaimana menyusun command multi-baris, mengatur working directory, dan memilih versi action dengan benar, adalah keterampilan yang membedakan workflow yang rapuh dari workflow yang profesional.
run adalah cara paling langsung untuk mengeksekusi perintah di runner. Bentuk paling sederhana — satu baris:
steps:
- name: Jalankan unit test
run: npm testPerhatikan bahwa default shell di runner Linux adalah bash dengan mode -e dan pipefail — jika perintah mengembalikan exit code bukan nol, step dianggap gagal dan pipeline berhenti.
Untuk beberapa perintah berurutan, gunakan literal block dengan |:
steps:
- name: Install, lint, dan test
run: |
npm ci
npm run lint
npm testSetiap baris di bawah run: | dieksekusi sebagai perintah terpisah dalam satu sesi shell yang sama. Ini penting: variabel yang di-set di baris pertama tetap bisa dipakai di baris berikutnya.
Terkadang kode yang mau di-build tidak berada di root repository — misalnya monorepo dengan folder frontend dan backend. Gunakan working-directory:
jobs:
frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build frontend
working-directory: ./frontend
run: |
npm ci
npm run buildworking-directory berlaku per step. Jika hampir semua step di sebuah job memakai direktori yang sama, kalian bisa mengatur default sekali untuk seluruh job lewat defaults:
jobs:
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
shell: bash
steps:
- uses: actions/checkout@v4
- run: npm ciSekarang setiap step run di job frontend otomatis berjalan di ./frontend memakai shell bash — tanpa harus menuliskannya berulang-ulang.
run mengeksekusi perintah mentah, tetapi banyak pekerjaan yang sebaiknya diserahkan ke action — kode siap pakai yang sudah diuji jutaan kali. Sintaks dasarnya: uses: <owner>/<repository>@<versi>.
Empat action paling penting yang harus kalian kenal:
| Action | Fungsi |
|---|---|
actions/checkout@v4 | Mengkloning repository ke runner — selalu step pertama |
actions/setup-node@v4 | Memasang runtime Node.js, mendukung cache npm otomatis |
actions/setup-python@v5 | Memasang Python dan pip, mendukung cache pip |
actions/setup-go@v5 | Memasang Go toolchain, mendukung cache module |
Contoh pemakaian setup-node dengan input:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npmPerhatikan bagian with — itulah cara mengirim input ke action. Action menerima parameter lewat with, menjalankan logikanya, dan (jika punya) menghasilkan output yang bisa dipakai step lain. cache: npm membuat action ini otomatis menangani caching dependensi — kita akan membahas caching lebih dalam di episode 8.
Bagian setelah tanda @ menentukan versi action yang dipakai. Ada tiga cara:
| Cara | Contoh | Karakteristik |
|---|---|---|
| Tag | actions/checkout@v4 | Mudah dibaca, mayor version stable — pilihan default |
| Commit SHA | actions/checkout@1a2b3c4... | Immutable dan paling aman untuk supply chain |
| Branch | actions/checkout@main | Memakai kode terbaru — jangan untuk produksi |
Aturan emasnya: tag untuk keterbacaan, SHA untuk keamanan ekstrem. Tag seperti v4 bisa saja dipindah oleh pemilik action menunjuk ke commit lain — jarang terjadi, tapi mungkin. Bagi tim yang menangani supply chain security dengan serius, pindahkan action ke full commit SHA dan biarkan renovate bot yang memperbaruinya.
Warning
Hindari merujuk action lewat branch seperti @main. Kode action bisa berubah kapan saja tanpa kalian sadari, dan perubahannya bisa melanggar workflow yang sedang berjalan di produksi. Selalu rujuk tag mayor (@v4) atau commit SHA penuh.
Sekarang mari kita rakit semua materi menjadi satu workflow CI nyata untuk project Node.js:
name: Node.js CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout kode
uses: actions/checkout@v4
- name: Setup Node.js 20
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependensi
run: npm ci
- name: Lint
run: npm run lint
- name: Unit test
run: npm testBisa kalian lihat pola yang konsisten dan akan kalian temui di hampir semua repository profesional: checkout → setup runtime → install dependensi → lint → test. Setiap perubahan di push atau pull request otomatis melalui proses ini, dan statusnya terlihat langsung di tab Checks setiap PR.
Tip
Gunakan npm ci (bukan npm install) di workflow. npm ci melakukan instalasi deterministik berdasarkan package-lock.json — hasilnya lebih cepat, lebih stabil, dan menghindari perubahan lockfile yang tidak disengaja.
setup-node membutuhkan isi repository? Tidak — justru setup-node tidak mengkloning kode. Tanpa actions/checkout@v4 di step pertama, runner kosong dan npm ci akan gagal.setup-node@v4 adalah versi action-nya; node-version: 20 adalah versi Node.js yang dipasang.run tanpa exit code yang benar. Jika skrip kalian exit 0 meskipun ada error, workflow tetap dianggap sukses. Pastikan skrip benar-benar mengembalikan exit code yang sesuai.Pada episode 4 ini kalian telah menguasai isi dari setiap job:
run untuk perintah shell: single-line, multi-line dengan |, working-directory, dan defaults.run.shell untuk default global job.uses untuk action Marketplace: checkout, setup-node, setup-python, dan setup-go, lengkap dengan input lewat with.Langkah-langkah kalian sekarang benar-benar terstruktur. Di episode 5 kita akan menambahkan kemampuan paling penting berikutnya: variabel, contexts, dan environment variables — bagaimana workflow kalian bisa memakai data konteks seperti siapa yang mengirim commit, menyimpan konfigurasi di vars, dan mengirim nilai antar step dengan GITHUB_ENV serta GITHUB_OUTPUT. Sampai jumpa di episode 5!