Sebagian besar tim API memperlakukan kontrak sebagai hal yang belakangan. Mereka menulis kode terlebih dahulu, lalu membuat spesifikasi, kemudian menyaksikan keduanya menyimpang. Desain API git-native membalik urutan itu. Anda memperlakukan kontrak API sebagai kode sumber, membuat versinya di Git, dan meninjau setiap perubahan dengan cara yang sama seperti Anda meninjau logika aplikasi.
Panduan ini adalah tentang disiplin, bukan satu alat. Anda akan belajar cara merancang kontrak dalam cabang, meninjaunya dalam permintaan tarik (pull request), dan mengubah spesifikasi yang telah dikomit menjadi mock, tes, dan dokumentasi. Tujuannya adalah alur kerja di mana riwayat Git Anda adalah riwayat API Anda.
Jika Anda sudah tahu seperti apa perkakas Spec-First dan menginginkan panduan produknya, baca artikel pendamping tentang alur kerja API git-native. Artikel ini tetap berfokus pada praktik.
Apa Arti “Git-Native” untuk Pekerjaan API
Git-native berarti definisi API Anda tersimpan di repositori Anda sebagai file teks biasa. Bukan di database cloud proprietary. Bukan di balik login vendor. Sebuah file .yaml atau .json yang berada di samping kode Anda, dilacak oleh kontrol versi yang sama yang sudah digunakan tim Anda.
Bandingkan ini dengan alat-alat yang terkunci di cloud. Banyak platform desain API menyimpan kontrak di backend mereka sendiri. Anda mengedit melalui UI web, dan versi kanoniknya berada di server mereka. Repositori Anda menyimpan ekspor yang sudah usang paling banter. Ketika database vendor menjadi sumber kebenaran, riwayat Git Anda tidak memberi tahu apa pun tentang bagaimana API tersebut berevolusi.

Model git-native membalikkan hubungan itu. File di main adalah kontraknya. Segala sesuatu yang lain, termasuk GUI apa pun, adalah tampilan dari file tersebut. Pergeseran tunggal ini membuka sejarah, penelusuran kesalahan (blame), pemulihan (rollback), dan peninjauan untuk permukaan API Anda.
Pengaturan git-native memiliki tiga properti. Spesifikasi adalah file teks di repo. Perubahan mengalir melalui operasi Git normal seperti branch, commit, dan merge. Dan setiap artefak downstream, dari mock hingga dokumentasi, berasal dari file yang di-commit daripada database terpisah.
Mengapa Merancang dan Mengembangkan API di Git
Anda sudah memercayai Git dengan aset paling berharga Anda: kode Anda. Kontrak API Anda pantas mendapatkan perlakuan yang sama.
Riwayat adalah alasan pertama. Ketika seseorang bertanya “kapan kita menambahkan parameter paginasi cursor,” git log menjawab dalam hitungan detik. Commit yang memperkenalkannya membawa pesan, penulis, dan tanggal. Tidak ada tangkapan layar, tidak ada arkeologi changelog.
Penelusuran kesalahan (Blame) adalah yang kedua. Jalankan git blame pada file spesifikasi dan Anda akan melihat dengan tepat siapa yang mengubah setiap baris dan alasannya. Nama bidang yang membingungkan dapat ditelusuri kembali ke PR yang menambahkannya, dengan diskusi terlampir. Akuntabilitas menjadi otomatis.
Pemulihan (Rollback) adalah yang ketiga. Sebuah desain yang buruk telah rilis. Dengan Git, Anda dapat git revert merge dan kontrak kembali ke keadaan sebelumnya. Codegen, mock, dan dokumentasi downstream dibuat ulang dari file yang dipulihkan. Tidak ada pembersihan manual dalam sistem terpisah.
Tinjauan adalah yang keempat, dan inilah yang kurang dimanfaatkan tim. Permintaan tarik (pull request) adalah tempat alami untuk memperdebatkan desain API sebelum menjadi nyata. Peninjau berkomentar pada baris + yang menambahkan bidang wajib. Percakapan itu tetap ada di samping perubahan selamanya.
Satu sumber kebenaran mengikat semuanya. Ketika kontrak adalah satu file di main, tidak ada ambiguitas tentang versi mana yang nyata. Frontend, backend, QA, dan dokumentasi semuanya membaca baris YAML yang sama. Ini adalah janji inti dari alur kerja spesifikasi API berbasis Git.
Siklus Desain API Git-Native
Siklus ini memiliki lima langkah: merancang kontrak, melakukan commit, membuka PR, meninjau, dan menggabungkan (merge). Implementasi mengikuti penggabungan, bukan sebaliknya.
Mulailah dengan menulis kontrak. Misalkan Anda menambahkan endpoint untuk mengambil faktur pengguna. Anda membuat branch dan mengedit file OpenAPI.
# openapi.yaml (excerpt added on branch feat/invoices-list)
paths:
/users/{userId}/invoices:
get:
operationId: listUserInvoices
summary: List invoices for a user
parameters:
- name: userId
in: path
required: true
schema: { type: string, format: uuid }
- name: status
in: query
required: false
schema:
type: string
enum: [draft, open, paid, void]
responses:
"200":
description: A page of invoices
content:
application/json:
schema:
$ref: "#/components/schemas/InvoiceList"
"404":
description: User not found
Komit perubahan itu dengan pesan yang jelas: git commit -m "Add GET /users/{userId}/invoices contract". Commit ini kecil dan terfokus. Ini menjelaskan satu keputusan desain.
Sekarang buka permintaan tarik (pull request). Perbedaan (diff) menunjukkan kepada peninjau dengan tepat apa yang baru: satu path, satu operasi, dua parameter, dua respons. Rekan tim Anda mendiskusikan penamaan, nilai-nilai enum, dan apakah 404 adalah kode yang tepat untuk pengguna yang hilang. Mereka mungkin mendorong paginasi kursor sebelum satu baris kode handler pun ada.
Setelah PR disetujui, gabungkan (merge) PR tersebut. Kontrak di main sekarang menyertakan endpoint faktur. Implementasi datang berikutnya, dan dibatasi oleh spesifikasi yang telah Anda semua sepakati. Urutan ini adalah yang dimaksud orang dengan pengembangan API spec-first: kesepakatan mendahului kode.
Manfaatnya adalah perdebatan desain terjadi dengan biaya rendah. Mengubah bidang YAML dalam tinjauan membutuhkan waktu menit. Mengubah endpoint yang sudah dirilis, diimplementasikan, dan didokumentasikan membutuhkan waktu berhari-hari.
Strategi Percabangan untuk Kontrak API
Perlakukan perubahan kontrak seperti perubahan lainnya: satu cabang per unit kerja logis. Satu cabang per endpoint atau per modifikasi menjaga PR tetap kecil dan diff dapat dibaca.
Namai cabang agar maksudnya jelas. Gunakan awalan yang menandakan kelas perubahan. Ini membantu peninjau dan CI merutekan pekerjaan.
| Jenis perubahan | Awalan cabang | Contoh | Bobot tinjauan |
|---|---|---|---|
| Endpoint baru | feat/api- |
feat/api-invoices-list |
Standar |
| Bidang tambahan | feat/api- |
feat/api-invoice-currency |
Ringan |
| Perubahan merusak | break/api- |
break/api-remove-legacy-id |
Berat, butuh persetujuan |
| Perbaikan bug di spesifikasi | fix/api- |
fix/api-status-enum-typo |
Ringan |
| Hanya refactor | chore/api- |
chore/api-reorder-schemas |
Ringan |
Awalan membawa makna. Cabang break/api- memberitahu peninjau untuk melambat dan memeriksa setiap konsumen. Cabang chore/api- menandakan tidak ada perubahan semantik, sehingga tinjauan dapat berjalan cepat.
Anda juga memilih model percabangan. Pengembangan berbasis trunk cocok untuk sebagian besar tim API. Cabang berumur pendek digabungkan ke main setiap hari, dan spesifikasi tetap dekat dengan satu garis kebenaran. Gitflow, dengan cabang develop dan release yang berjalan lama, cocok untuk tim yang mengelompokkan perubahan API ke dalam rilis terjadwal.
| Model | Terbaik untuk | Tradeoff API |
|---|---|---|
| Berbasis Trunk | Pengiriman berkelanjutan, tim kecil | Kontrak berevolusi dalam langkah kecil; lebih sedikit masalah penggabungan |
| Gitflow | Rilis terjadwal, pengiriman teregulasi | Spesifikasi menyimpang di develop; penggabungan yang lebih besar dan berisiko |
Untuk sebagian besar pekerjaan API, lebih disukai berbasis trunk. Perubahan kontrak yang kecil dan sering menghasilkan diff yang kecil dan sering. Cabang yang berumur panjang memungkinkan spesifikasi menyimpang, dan konflik penggabungan YAML menjadi buruk dengan cepat ketika dua cabang merestrukturisasi file yang sama.
Meninjau Desain API dalam Permintaan Tarik (Pull Request)
PR spesifikasi adalah tinjauan desain, bukan pemeriksaan sintaks. Peninjau melihat semantik, dan beberapa pertanyaan mencakup sebagian besar risiko.
Apakah ini merusak konsumen yang ada? Menghapus bidang, mengganti nama path, atau memperketat tipe semuanya merupakan perubahan yang merusak. Peninjau memeriksa apakah perubahan tersebut bersifat aditif atau merusak, dan perubahan yang merusak menuntut peningkatan versi atau jalur depresiasi.
Apakah penamaannya konsisten? Jika setiap endpoint koleksi menggunakan kata benda jamak, path tunggal yang baru akan menonjol. Jika kesalahan mengembalikan bidang code di tempat lain, endpoint baru juga harus demikian. Peninjau menegakkan pola yang sudah ditetapkan API.
Apakah ramah terhadap diff? Jaga agar YAML tetap stabil sehingga diff tetap kecil. Urutkan kunci secara konsisten. Tambahkan path baru di tempat yang dapat diprediksi. Peninjau dapat membaca diff lima baris dalam hitungan detik, tetapi file yang diurutkan ulang menghasilkan diff seratus baris yang menyembunyikan perubahan yang sebenarnya.
Perubahan merusak yang ramah peninjau. Baris - menandai dengan tepat apa yang hilang.
# Diff a reviewer sees in the PR
parameters:
- name: status
in: query
schema:
type: string
- enum: [draft, open, paid, void]
+ enum: [draft, open, paid, void, uncollectible]
Diff itu bersifat aditif pada enum, jadi aman. Bandingkan dengan baris - yang menghapus void sepenuhnya, yang akan merusak klien mana pun yang mengirimkan nilai tersebut. Diff membuat perbedaan terlihat sekilas.
Dorong peninjau untuk berkomentar secara inline pada spesifikasi, sama seperti mereka berkomentar pada kode. Diskusi tetap terlampir pada baris tersebut dan bertahan dalam riwayat penggabungan.
Dari Desain ke Pengembangan
Setelah kontrak berada di main, itu menjadi sumber untuk segala sesuatu di downstream. Anda menghasilkan, Anda tidak menulis secara manual.

Codegen didahulukan. Alat seperti openapi-generator menghasilkan stub server dan klien yang tipenya ditentukan dari file yang di-commit. Handler Anda mengisi logika bisnis, tetapi bentuk permintaan dan respons sesuai dengan kontrak berdasarkan konstruksi. Spesifikasi dan kode tidak dapat bertentangan tentang format wire.
Mock datang berikutnya. Server mock membaca spesifikasi dan mengembalikan respons contoh untuk setiap endpoint. Pengembang frontend membangun berdasarkan mock sebelum backend ada. Mereka mulai saat kontrak digabungkan, bukan berminggu-minggu kemudian.
Tes menyusul. Tes kontrak menegaskan bahwa server yang sedang berjalan cocok dengan spesifikasi. Kirim permintaan, validasi respons terhadap skema, dan gagalkan build jika ada penyimpangan. Ini adalah penjaga terhadap penyimpangan spesifikasi/kode.
Dokumentasi juga dibuat. Dokumentasi referensi dibuat langsung dari file OpenAPI. Ketika kontrak berubah, dokumentasi juga berubah dalam commit yang sama. Tidak ada pembaruan dokumen terpisah yang terlupakan.
Prinsipnya konsisten. Setiap artefak berasal dari satu file yang telah di-commit. Buat ulang pada setiap penggabungan, dan mock, klien, tes, serta dokumentasi Anda akan tetap sinkron dengan kontrak.
Konvensi Tim yang Skalabel
Konvensi adalah apa yang mencegah alur kerja git-native runtuh saat tim berkembang. Putuskan sejak awal dan tuliskan.
Pertama, pilih antara satu file spesifikasi dan banyak. Satu openapi.yaml sederhana tetapi menjadi tidak praktis setelah beberapa lusin endpoint. Memisahkan ke beberapa file dengan referensi $ref menjaga setiap file tetap dapat dibaca, dengan biaya langkah bundling. Pola umum adalah satu file per sumber daya, dibundel menjadi satu spesifikasi pada waktu build.
Kedua, lakukan versi secara sengaja. Tingkatkan info.version OpenAPI pada setiap perubahan yang berarti, dan ikuti semantic versioning. Perubahan aditif meningkatkan versi minor. Perubahan yang merusak meningkatkan versi mayor dan biasanya berarti awalan path baru seperti /v2/.
Ketiga, simpan changelog. Sebuah CHANGELOG.md di samping spesifikasi mencatat apa yang berubah dan mengapa dalam istilah manusia. Riwayat Git tepat tetapi bertele-tele; changelog adalah ringkasan yang dapat dibaca yang sebenarnya dipindai oleh konsumen Anda.
Keempat, lindungi spesifikasi dengan CODEOWNERS. Wajibkan pengelola API untuk menyetujui setiap perubahan pada file kontrak. Ini mencegah kontributor yang bermaksud baik merilis desain yang tidak konsisten.
# .github/CODEOWNERS
/api/openapi.yaml @api-stewards
/api/paths/ @api-stewards
Kelima, lakukan linting di CI. Linter menangkap masalah gaya dan konsistensi sebelum tinjauan. Jalankan pada setiap PR agar manusia meninjau desain, bukan pemformatan.
# .github/workflows/api-lint.yml
name: API Lint
on:
pull_request:
paths: ["api/"]
jobs:
spectral:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Spectral
run: npx @stoplight/spectral-cli lint api/openapi.yaml --fail-severity warn
Dengan linting CI ditambah CODEOWNERS, setiap perubahan kontrak mendapatkan pemeriksaan otomatis dan pengelola manusia. Kombinasi itu skalabel dari tiga insinyur menjadi tiga ratus.
Jebakan Umum dan Cara Menghindarinya
Desain API git-native memiliki mode kegagalan yang dapat diprediksi. Mengetahuinya memungkinkan Anda merancang untuk menghindarinya.
Penyimpangan spesifikasi/kode adalah yang terburuk. Kontrak mengatakan satu hal; server yang berjalan melakukan hal lain. Cegah hal ini dengan tes kontrak di CI yang memvalidasi respons langsung terhadap spesifikasi yang telah di-commit. Jika menyimpang, build akan gagal. Penyimpangan menjadi pipeline yang rusak, bukan kejutan produksi.
PR raksasa adalah jebakan berikutnya. Satu cabang yang menambahkan dua puluh endpoint menghasilkan diff yang tidak dapat ditinjau. Peninjau hanya melihat sekilas, menyetujui, dan melewatkan masalah. Bagi pekerjaan menjadi satu endpoint atau satu perubahan per PR. Diff kecil mendapatkan tinjauan nyata.
Artefak yang ditulis tangan menyebabkan inkonsistensi diam-diam. Ketika seseorang menulis klien secara manual alih-alih menghasilkannya, klien tersebut menyimpang dari spesifikasi. Hasilkan klien, stub, dan dokumentasi dari file yang telah di-commit setiap saat. Perlakukan artefak API yang ditulis tangan sebagai pertanda buruk.
Konflik penggabungan YAML membuat tim frustrasi pada cabang yang berumur panjang. Dua cabang merestrukturisasi file yang sama dan Git tidak dapat mendamaikannya. Hindari ini dengan cabang berumur pendek, urutan kunci yang stabil, dan tata letak file yang terpisah sehingga perubahan menyentuh file yang berbeda. Pengembangan berbasis trunk ditambah PR kecil menghilangkan sebagian besar konflik sebelum dimulai.
Pola di keempatnya sama. Pertahankan perubahan tetap kecil, turunkan artefak dari spesifikasi, dan biarkan CI menegakkan kontrak. Disiplin mengalahkan heroisme.
Di Mana Apidog Berperan
Anda dapat menjalankan alur kerja git-native dengan editor teks dan CLI. Banyak tim menginginkan GUI untuk desain tanpa melepaskan Git sebagai sumber kebenaran. Itulah celah yang diisi oleh Mode Spec-First Apidog.
Mode Spec-First menjaga file OpenAPI di repositori Git Anda dan memiliki sinkronisasi dua arah. Anda mengedit kontrak di desainer visual Apidog atau di editor Anda, dan keduanya tetap konsisten dengan file di repo Anda. File di Git tetap kanonik, sehingga cabang, PR, dan riwayat semuanya berfungsi persis seperti yang dijelaskan di sini. Anda mendapatkan GUI tanpa terikat cloud. Lihat dokumentasi Mode Spec-First untuk detail pengaturan.
Intinya bukan pada alatnya. Intinya adalah Anda dapat memiliki permukaan desain visual dan disiplin git-native pada saat yang bersamaan. Repo tetap menjadi satu sumber kebenaran, dan Apidog menjadi salah satu tampilan atasnya.
Pertanyaan Umum
Apakah desain API git-native hanya untuk OpenAPI?
Tidak. Disiplin ini berlaku untuk format kontrak berbasis teks apa pun. OpenAPI adalah yang paling umum, tetapi alur kerja yang sama berlaku untuk AsyncAPI, file .proto gRPC, atau GraphQL SDL. Selama kontrak adalah file teks yang dapat Anda bandingkan (diff), buat cabang (branch), dan tinjau, itu adalah git-native.
Bagaimana cara menangani perubahan merusak dalam alur kerja git-native?
Buat perubahan merusak terlihat dan disengaja. Gunakan awalan cabang break/api-, tingkatkan versi mayor, dan wajibkan persetujuan pengelola melalui CODEOWNERS. Jika memungkinkan, tambahkan bentuk baru di samping yang lama dan deprecate path lama sesuai jadwal. Diff PR dan peningkatan versi bersama-sama memberi sinyal perubahan merusak kepada setiap konsumen.
Haruskah spesifikasi API berada di repo yang sama dengan kodenya?
Biasanya ya, ketika satu tim memiliki keduanya. Menggabungkan spesifikasi dan implementasi berarti satu PR dapat mengubah kontrak dan handler secara bersamaan, dan tes kontrak berjalan dalam satu pipeline. Letakkan spesifikasi di repo terpisah hanya ketika banyak tim mengonsumsi satu API bersama dan membutuhkan versi yang independen.
Bagaimana cara mencegah spesifikasi dan kode menyimpang?
Tambahkan tes kontrak ke CI. Mereka mengirim permintaan nyata ke server Anda yang sedang berjalan dan memvalidasi setiap respons terhadap spesifikasi yang telah di-commit. Perbedaan menyebabkan build gagal. Dikombinasikan dengan menghasilkan stub dan klien dari spesifikasi, tes kontrak menjadikan penyimpangan sebagai kegagalan pipeline alih-alih bug produksi.
Kesimpulan
Desain API git-native adalah disiplin, bukan produk. Anda memperlakukan kontrak sebagai kode sumber, mengembangkannya dalam cabang, meninjaunya dalam permintaan tarik, dan menghasilkan setiap artefak downstream dari file yang telah di-commit. Riwayat, penelusuran kesalahan, pemulihan, dan peninjauan datang secara gratis karena Git sudah memberikannya kepada Anda.
Mulai dari kecil. Pindahkan spesifikasi Anda ke repositori, tambahkan langkah lint, dan wajibkan peninjauan pada perubahan kontrak. Bangun dari sana dengan codegen, mock, dan tes kontrak. Alur kerja ini berlipat ganda: setiap konvensi membuat yang berikutnya lebih mudah, dan riwayat Git Anda menjadi catatan lengkap tentang bagaimana API Anda berkembang.
Jika Anda menginginkan permukaan desain visual yang menyimpan spesifikasi di Git, coba Mode Spec-First di Apidog dan lihat bagaimana sinkronisasi dua arah sesuai dengan alur kerja di atas.
