Belajar Curl - Scripting & Automation
Series/Belajar Curl/Episode 16
Episode 16 of 23

Belajar Curl - Scripting & Automation

Pada episode ini kita akan menjadikan curl mesin otomasi: memahami exit code, menghasilkan output yang bisa dibaca mesin dengan write-out, membangun pipeline curl dengan jq, serta memasang curl di CI/CD sebagai health check dan smoke test.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Pendahuluan

Sejauh ini curl selalu dijalankan secara manual — mengetik perintah, membaca hasil, menilai sendiri. Di episode 16 ini kalian akan mengubah curl menjadi mesin: perintah yang dijalankan tanpa pengawasan, yang hasilnya dibaca oleh skrip, dan yang menjadi bagian dari pipeline CI yang melindungi produksi. Bedanya bukan pada perintah curl-nya — bedanya pada cara kalian memperlakukannya: sebagai fungsi yang punya nilai kembali, bukan sebagai perintah yang hanya mencetak teks.

Exit Code: Bahasa antara curl dan Skrip

Setiap kali curl selesai, ia keluar dengan sebuah exit code — angka yang menceritakan bagaimana request berakhir. Angka ini adalah satu-satunya hal yang bisa dibaca skrip secara andal. Skrip memeriksa kode itu lewat $?:

cek-exit.sh
curl -sS https://api.example.com/health
echo "curl keluar dengan kode: $?"

Aturan yang jauh lebih penting untuk skrip: kode 0 berarti sukses, apapun isi body-nya. Jika server menjawab 404 Not Found dengan rapi, curl tetap menganggap sukses — body sukses terkirim, error hanya status HTTP. Untuk skrip, inilah jebakan terbesar. Solusinya adalah --fail-with-body: curl keluar non-zero (kode 22) saat server menjawab 4xx/5xx, sambil tetap menampilkan body agar debugging mudah:

fail-with-body.sh
curl -sS --fail-with-body https://api.example.com/users/99999
guard-if.sh
if curl -sS --fail-with-body --connect-timeout 5 --max-time 30 \
  https://api.example.com/health > /dev/null; then
  echo "Layanan sehat"
else
  echo "Layanan bermasalah" >&2
  exit 1
fi

Gunakan pola if curl ...; then setiap kali sebuah kegagalan request harus mengubah alur skrip — bukan sekadar menunggu curl mencetak error di layar yang mungkin tidak pernah dibaca siapa pun.

Tip

Kombinasikan selalu dengan --silent --show-error (alias -sS) di skrip: progress meter tidak akan membanjiri log, tapi pesan error tetap tampil. Tanpa -s, log CI kalian penuh sampah baris progress; tanpa -S, error yang penting bisa tenggelam.

Output yang Bisa Dibaca Mesin: -w

Skrip tidak pandai membaca teks bebas — ia pandai membaca struktur. Opsi -w (write-out) dari episode 6, 15, dan 18 mengubah output curl menjadi baris yang bisa diurai: status code, timing, dan ukuran dalam satu format yang kalian tentukan.

log-line.sh
curl -sS -o /dev/null \
  -w "%{http_code} %{time_total}s %{size_download}bytes %{url_effective}\n" \
  https://api.example.com/health

Tiga hal yang membuat baris ini cocok untuk log: formatnya satu baris per request (mudah di-grep), memakai variabel yang deterministik (bukan teks yang berubah-ubah), dan bisa ditambahkan tanggal lewat date +%F bila perlu. Menulis hasil ke file log dengan >> membuat jejak yang bisa diaudit — persis yang kita rekomendasikan di episode 13.

Pipeline curl | jq: Parsing Otomatis

Manusia membaca JSON dengan mata; skrip membacanya dengan jq — filter yang mengekstrak field tertentu dari dokumen JSON. Pipeline curl | jq adalah pasangan paling produktif di seluruh ekosistem curl:

jq-ekstrak.sh
curl -sS https://api.github.com/repos/curl/curl/releases/latest \
  | jq -r '.tag_name'
jq-filter.sh
curl -sS https://api.example.com/orders \
  | jq -r '.orders[] | select(.status == "paid") | .id'
  • -r membuat output "raw" tanpa tanda kutip — hasilnya siap dipakai sebagai argumen atau disimpan ke variabel.
  • Filter seperti select(.status == "paid") memilih data berdasarkan kondisi — kemampuan yang mengubah JSON mentah menjadi daftar ringkas yang bisa di-loop.
jq-loop.sh
for id in $(curl -sS https://api.example.com/orders \
            | jq -r '.orders[].id'); do
  echo "Memeriksa order $id"
  curl -sS --fail-with-body "https://api.example.com/orders/$id" \
    | jq -r '.total'
done

Perhatikan bahwa loop di atas memanggil curl sekali untuk daftar, lalu sekali per item — pola yang wajar untuk otomasi. Dari episode 15 kalian tahu: jika batch request ke host yang sama bisa dijalankan paralel, pertimbangkan --parallel untuk versi yang lebih cepat.

Idempotensi dan Reproducibilitas

Skrip yang berjalan di CI harus memberi hasil yang sama setiap kali dijalankan — reproducible. Beberapa kebiasaan yang merusak ini:

  • Timestamp acak di body — membuat request tidak pernah identik dan sulit dibandingkan.
  • Header yang tidak eksplisit — hasil yang bergantung pada nilai default yang bisa berubah antar versi.
  • Payload ditulis inline — sulit di-review dan berisiko salah ketik.

Solusinya sederhana: buat request idempotent (menjalankan dua kali memberi efek yang sama) dan deterministik (isi yang sama setiap run). Simpan payload di file yang di-commit ke repository, dan minta dengan eksplisit:

payload-file.sh
curl -sS --fail-with-body --json @payloads/create-user.json \
  https://api.example.com/users

File create-user.json di-commit bersama skripnya, direview dalam pull request yang sama — persis pola request library yang akan kita pakai di episode 22. Request yang bisa diulang adalah request yang bisa dipertanggungjawabkan.

curl di CI/CD

Di sinilah semua keterampilan bersatu. Pipeline CI tidak peduli indahnya perintah — ia peduli exit code. Berikut curl dalam dua platform paling umum.

Health Check di GitHub Actions

health-check.yml
name: Health Check
on:
  schedule:
    - cron: '*/5 * * * *'
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - name: Cek kesehatan API
        run: curl --fail-with-body --silent --connect-timeout 5 --max-time 30 \
          https://api.example.com/health

Jika layanan tidak sehat, --fail-with-body membuat langkah ini gagal — dan kegagalan langkah membuat job gagal. Health check terjadwal ini adalah alarm pertama sebelum pengguna mengeluh.

Smoke Test di GitLab CI

.gitlab-ci.yml
smoke-test:
  stage: test
  image: curlimages/curl:8.12.0
  variables:
    API_BASE: https://staging.example.com
  script:
    - curl --fail-with-body --silent "$API_BASE/health"
    - curl --fail-with-body --silent "$API_BASE/api/v1/users" \
        -H "Authorization: Bearer $API_TOKEN"

Perhatikan detail yang membuat job ini bisa diulang: versi image curl dipin (curlimages/curl:8.12.0) agar perilaku tidak bergeser antar build, base URL dan token lewat environment, dan tiap langkah menggunakan --fail-with-body sehingga kegagalan HTTP dianggap kegagalan pipeline.

Important

Token di CI hanya boleh lewat secret store: di GitHub Actions $API_TOKEN berasal dari Settings > Secrets, di GitLab CI dari Settings > CI/CD > Variables. Jangan pernah menulis token literal di file YAML — file itu masuk ke git, dan riwayat git tidak pernah benar-benar bisa dibersihkan.

Skrip Lengkap: Deploy Gate

Rangkai semuanya menjadi satu skrip yang bisa berdiri sendiri — perwakilan dari yang akan kalian temui di dunia kerja: memeriksa kesehatan, menunggu layanan stabil, lalu menandai kesiapan deploy.

deploy-gate.sh
#!/usr/bin/env bash
set -euo pipefail
 
ENDPOINT="${1:-https://api.example.com/health}"
ATTEMPTS=5
DELAY=3
 
for i in $(seq 1 "$ATTEMPTS"); do
  code=$(curl -sS -o /dev/null -w "%{http_code}" \
    --connect-timeout 5 --max-time 30 "$ENDPOINT" || true)
  echo "Percobaan $i/$ATTEMPTS: HTTP $code"
 
  if [ "$code" = "200" ]; then
    echo "Layanan sehat, deploy boleh jalan"
    exit 0
  fi
  sleep "$DELAY"
done
 
echo "Layanan belum sehat setelah $ATTEMPTS percobaan" >&2
exit 1

Bedah logikanya: set -euo pipefail membuat skrip berhenti pada error pertama yang tak tertangani; || true mencegah curl yang gagal langsung menghentikan loop; -w menangkap status lewat variabel http_code dalam bentuk yang bisa dibandingkan; dan exit code di ujung menjadi sinyal final untuk pipeline. Skrip seperti inilah yang membedakan otomasi yang dipikirkan dari otomasi yang asal jalan.

Penutup

Episode 16 mengubah curl menjadi mesin otomasi: memahami exit code dan --fail-with-body sebagai bahasa kegagalan, menghasilkan output terstruktur dengan -w untuk log yang bisa diurai, membangun pipeline curl | jq untuk parsing JSON otomatis, membuat request yang idempotent dan reproducible, serta memasang curl di GitHub Actions dan GitLab CI sebagai health check dan smoke test.

Inti yang perlu diingat: skrip tidak membaca layar — ia membaca exit code. Semua keindahan output di terminal tidak ada artinya jika skrip tidak bisa menilai sukses atau gagal. Ajari curl untuk berbicara dalam bahasa skrip, dan kalian bisa menyerahkan pekerjaan apa pun padanya tanpa pengawasan.

Di episode 17 berikutnya kita akan melihat bagaimana curl berinteraksi dengan ekosistem di sekitarnya: API testing tools — perbandingan dengan wget, httpie, dan Postman, serta bagaimana curl menjadi fondasi tool testing modern. Sampai jumpa!