Dua insinyur dalam tim yang sama merilis dua *endpoint* dalam minggu yang sama. Satu mengembalikan created_at, yang lain mengembalikan createdAt. Satu melakukan *pagination* dengan ?page=, yang lain dengan ?offset=. Tidak ada yang salah secara individual. Namun, bersama-sama, mereka membuat API Anda terasa seperti dirakit oleh orang asing, dan setiap klien yang menggunakannya harus menanggung bebannya. File OpenAPI tervalidasi dengan baik. Dapat di-*parse*, dirender di Swagger UI, dan menghasilkan SDK. Ini hanya tidak konsisten, dan *validator* biasa tidak bisa mengatakan apa-apa tentang itu.
Itulah celah yang tepat yang diisi oleh *linter*. Sebuah *validator* menjawab “apakah spesifikasi ini legal OpenAPI?” Sebuah *linter* menjawab “apakah spesifikasi ini mengikuti aturan yang kita sepakati?” Alat *open-source* paling populer untuk pertanyaan kedua adalah Spectral, *linter* Stoplight untuk dokumen JSON dan YAML. Ia dilengkapi dengan *ruleset* OpenAPI bawaan, memungkinkan Anda menulis aturan sendiri, dan berjalan dari terminal atau editor Anda. Jika Anda menginginkan cara gratis yang dapat diskrip untuk menegakkan panduan gaya API, Spectral adalah pilihan pertama yang jelas, dan panduan ini menunjukkan cara menggunakannya dengan benar.
Ini juga menunjukkan pertukarannya. Spectral adalah *ruleset* yang Anda rakit dan pelihara. Bagi tim yang lebih suka mendapatkan pemeriksaan konsistensi, *mock server*, dan *runnable test* dari satu tempat tanpa menulis aturan YAML secara manual, Apidog mengintegrasikan pekerjaan itu ke dalam permukaan desain itu sendiri. Kami akan membahas Spectral sepenuhnya terlebih dahulu, kemudian menunjukkan di mana jalur serba ada menghemat biaya pemeliharaan Anda.
Apa yang sebenarnya dilakukan Spectral
Spectral adalah *linter* generik. Anda mengarahkannya ke dokumen terstruktur, memberinya seperangkat aturan, dan ia melaporkan setiap tempat di mana dokumen tersebut melanggar aturan, dengan nomor baris dan tingkat keparahan. Ini tidak spesifik untuk OpenAPI; ia memahami OpenAPI, AsyncAPI, dan Arazzo secara *out of the box*, dan Anda dapat melakukan *lint* pada file JSON atau YAML apa pun dengan aturan khusus.

Alasan mengapa ini penting untuk pekerjaan API adalah *ruleset* spectral:oas bawaannya. *Ruleset* tersebut mengkodekan daftar panjang konvensi OpenAPI: operasi harus memiliki operationId, objek info harus berisi deskripsi dan kontak, *tag* harus didefinisikan sebelum digunakan, parameter tidak boleh saling menduplikasi. Jalankan terhadap spesifikasi dunia nyata dan Anda hampir selalu akan mendapatkan daftar peringatan pada percobaan pertama. Tidak ada yang merusak *parser*. Semuanya membuat spesifikasi lebih sulit untuk dikelola.
Ini adalah pekerjaan yang berbeda dari validasi struktural. Alat seperti swagger-cli atau Redocly menjawab apakah dokumen sesuai dengan skema OpenAPI. Spectral menjawab apakah dokumen mengikuti gaya perusahaan Anda di atas itu. Anda menginginkan keduanya, dan kedua pemeriksaan itu menyatu dengan rapi dalam sebuah *pipeline*. Kami membahas bagian validasi dalam panduan tentang cara memvalidasi spesifikasi OpenAPI; artikel ini adalah tentang bagian gaya dan konsistensi.
Menginstal Spectral dan menjalankan *lint* pertama Anda
Spectral dikirim sebagai paket npm. CLI-nya adalah @stoplight/spectral-cli. Instal secara global:
npm install -g @stoplight/spectral-cli
Node.js adalah satu-satunya dependensi sistem, jadi mesin atau *image* CI apa pun dengan Node yang sudah terinstal dapat menjalankannya. Jika Anda tidak ingin menginstalnya secara global, npx @stoplight/spectral-cli ... berfungsi pada *build runner* sementara.
Spectral membutuhkan *ruleset* untuk mengetahui apa yang harus diperiksa. Konvensinya adalah file bernama .spectral.yaml di direktori kerja Anda. Yang paling sederhana namun berguna adalah memperluas aturan OpenAPI bawaan:
# .spectral.yaml
extends: ["spectral:oas"]
Sekarang *lint* spesifikasi. Dengan .spectral.yaml di direktori saat ini, Spectral akan mengambilnya secara otomatis:
spectral lint openapi.yaml
Atau tunjuk *ruleset* secara eksplisit:
spectral lint openapi.yaml --ruleset .spectral.yaml
Outputnya sengaja dibuat mudah dibaca. Setiap temuan menunjukkan baris dan kolom, tingkat keparahan, aturan yang aktif, dan pesan yang mudah dipahami:
openapi.yaml
3:6 warning info-contact Info object should contain `contact` object.
5:10 error info-description OpenAPI object info `description` must be present.
✖ 2 problems (1 error, 1 warning, 0 infos, 0 hints)
Jalankan pertama kali terhadap spesifikasi yang ada adalah saat sebagian besar tim menyadari seberapa banyak penyimpangan yang telah terjadi. Aturan-aturan itu tidak pernah ditegakkan, jadi tidak ada yang mengikutinya.
Menulis aturan Anda sendiri
*Ruleset* bawaan adalah titik awal, bukan tujuan akhir. Nilai sebenarnya dari Spectral adalah mengkodekan konvensi tim Anda sebagai aturan yang diperiksa oleh mesin pada setiap perubahan. Sebuah aturan memiliki empat bagian yang bergerak: apa yang harus dilihat (given, sebuah ekspresi JSONPath), apa yang harus diperiksa (then, sebuah fungsi), seberapa "keras" notifikasinya (severity), dan apa yang harus dikatakan ketika gagal (message).
Berikut adalah aturan yang menerapkan jalur *kebab-case*, sebuah konvensi umum perusahaan:
# .spectral.yaml
extends: ["spectral:oas"]
rules:
paths-kebab-case:
description: Paths should be kebab-case.
message: "{{property}} should be kebab-case (lower-case, hyphen-separated)"
severity: warn
given: $.paths[*]~
then:
function: pattern
functionOptions:
match: "^(\\/|[a-z0-9-.]+|{[a-zA-Z0-9_]+})+$"
given memilih setiap kunci jalur. then menjalankan fungsi pattern bawaan terhadap ekspresi reguler. Apa pun yang gagal dalam pola akan dilaporkan sebagai peringatan dengan pesan Anda. Anda dapat melarang ID bilangan bulat demi UUID, mewajibkan respons kesalahan pada setiap POST, melarang nomor versi di URL server, atau mewajibkan setiap operasi memiliki deskripsi. Spectral dilengkapi dengan beberapa fungsi inti (truthy, pattern, schema, length, enumeration, dan banyak lagi) sehingga sebagian besar konvensi tidak memerlukan kode sama sekali.
Ketika sebuah aturan membutuhkan logika yang tidak dapat diekspresikan oleh opsi fungsi, Spectral memungkinkan Anda menulis aturan dalam JavaScript atau TypeScript dan mengimpor fungsi kustom. Di situlah alat ini menjadi sangat kuat dan di situlah pemeliharaan dimulai. Jika Anda ingin mendalami hal itu, kami memiliki panduan lengkap tentang membangun aturan Spectral kustom dengan TypeScript.
Tingkat Keparahan, dan membuat *build* gagal
Setiap aturan Spectral memiliki tingkat keparahan: error, warn, info, atau hint. Secara *default*, CLI hanya keluar dengan kode bukan nol ketika menemukan error. Peringatan dicetak tetapi tidak membuat proses gagal. Ini tidak masalah saat Anda membersihkan spesifikasi lama dan tidak ingin seribu peringatan menghalangi setiap *merge*.
Setelah spesifikasi Anda bersih, kencangkan gerbangnya. *Flag* --fail-severity mengontrol ambang batas:
spectral lint openapi.yaml --fail-severity=warn
Sekarang sebuah peringatan juga mengembalikan kode keluar 1, yang dibaca oleh langkah CI untuk menandai dirinya gagal. Ini adalah mekanisme yang mengubah *linter* menjadi gerbang kualitas yang sebenarnya: *pipeline* memblokir *merge* saat spesifikasi menyimpang dari panduan gaya. Anda juga dapat mengganti tingkat keparahan aturan individual di *ruleset* Anda, menaikkan aturan yang Anda pedulikan dari warn menjadi error atau membungkam aturan yang tidak sesuai dengan tim Anda dengan mengaturnya ke off.
Menjalankan Spectral di CI
Sebuah *linter* yang hanya berjalan ketika seseorang mengingatnya bukanlah sebuah gerbang. Tujuannya adalah untuk menjalankannya pada setiap *push*, di mesin yang bersih, dengan *ruleset* yang sama untuk semua orang. Spectral membuatnya singkat. Berikut adalah *job* GitHub Actions yang melakukan *lint* pada spesifikasi di setiap *pull request* yang menyentuhnya:
name: Lint OpenAPI
on:
pull_request:
paths:
- "openapi.yaml"
jobs:
spectral:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm install -g @stoplight/spectral-cli
- run: spectral lint openapi.yaml --fail-severity=warn
Untuk pelaporan yang lebih kaya, Spectral dapat mengeluarkan JUnit XML, yang sebagian besar *dashboard* CI mem-*parse* menjadi pohon lulus/gagal:
spectral lint openapi.yaml -f junit -o results.xml
Hubungkan artefak tersebut ke *dashboard* Anda dan setiap kontributor melihat aturan mana yang gagal dan di mana, tanpa membaca *log* mentah. Jika Anda ingin gambaran yang lebih luas tentang pelapisan pemeriksaan struktural, *linting*, dan deteksi perubahan yang menyebabkan kerusakan (*breaking-change detection*) secara bersamaan, pola OpenAPI-in-CI menggeneralisasi melampaui alat tunggal mana pun. Memperlakukan spesifikasi sebagai kode adalah pola pikir yang membuat semua ini bertahan.
Di mana Spectral menuntut banyak dari Anda
Spectral hebat dalam apa yang dilakukannya. Tangkapan jujurnya adalah ia melakukan satu hal, dan sisa siklus hidup spesifikasi adalah masalah Anda untuk menyatukannya. Beberapa kenyataan muncul setelah sebuah tim mengadopsinya melewati demo.
Anda memiliki *ruleset*. Aturan spectral:oas bawaan bersifat generik. Panduan gaya asli Anda berada dalam aturan kustom yang Anda tulis, tinjau, buat versinya, dan pertahankan agar tetap mutakhir seiring berkembangnya konvensi. *Ruleset* tersebut menjadi *codebase* kecil dengan beban pemeliharaannya sendiri, dan JSONPath ditambah fungsi kustom adalah keterampilan yang tidak dimiliki oleh semua orang di tim.
Ini melakukan *lint* pada dokumen, bukan API. Spectral membaca file. Ia tidak dapat memberi tahu Anda apakah layanan yang berjalan benar-benar mengembalikan apa yang dijanjikan spesifikasi. Sebuah spesifikasi dapat melewati setiap aturan *lint* dan masih mendeskripsikan *endpoint* yang implementasinya menyimpang berbulan-bulan yang lalu. Menutup celah itu berarti mengirimkan permintaan nyata dan menegaskan respons, yang merupakan alat yang sama sekali berbeda.
Ini adalah salah satu bagian dari rantai yang lebih panjang. Setelah *linting*, Anda masih membutuhkan *mock* untuk tim *frontend*, situs dokumentasi, dan *suite* pengujian otomatis. Masing-masing adalah alat terpisah untuk diinstal, dikonfigurasi, dan disinkronkan dengan spesifikasi. *Linter* tidak mengetahui semua itu, sehingga spesifikasi di-*parse* ulang dan diinterpretasikan ulang di setiap tahapan.
Semua ini bukan kritik terhadap Spectral. Ini adalah *linter* yang fokus dan jujur tentang cakupannya. Namun "fokus" berarti pekerjaan integrasi ada pada Anda.
Cara yang lebih mudah: konsistensi yang dibangun ke dalam permukaan desain
Berikut adalah jalur lainnya. Alih-alih memperlakukan konsistensi sebagai langkah *lint* yang ditempelkan setelah spesifikasi ditulis, Apidog memperlakukannya sebagai bagian dari penulisan spesifikasi.
Apidog adalah platform API serba ada: Anda mendesain skema, melakukan *debug* permintaan, membangun skenario pengujian, membuat *mock endpoint*, dan menerbitkan dokumentasi dalam satu *workspace*. Karena desain terjadi di dalam alat, pemeriksaan konsistensi terjadi saat Anda mengetik. Desainer visual menampilkan masalah struktural saat mereka muncul, seperti bagaimana *compiler* menggarisbawahi kesalahan sintaks, sehingga Anda memperbaikinya sebelum mencapai *commit*. Anda tidak menjalankan *linter* terpisah setelah fakta; editor adalah *linter*nya.
Perbedaan yang lebih besar adalah segalanya di hilir. Kontrak yang sama yang Anda desain menjadi *mock server* Anda, dokumentasi interaktif Anda, dan skenario pengujian Anda, tanpa *parsing* ulang dan tanpa alat kedua untuk tetap sinkron. Ketika Anda menginginkan pemeriksaan tersebut dalam *pipeline*, Apidog CLI menjalankan skenario pengujian Anda tanpa kepala dari terminal dan keluar dengan kode bukan nol jika gagal, persis perilaku gerbang yang Anda inginkan dari *linter*, kecuali ia menguji API yang berjalan terhadap kontrak alih-alih hanya membaca file. Instal dengan satu perintah npm dan arahkan ke skenario:
npm install -g apidog-cli
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <scenarioId> -e <environmentId> -r cli
Itu mengisi celah yang ditinggalkan Spectral. Spectral mengonfirmasi bahwa dokumen mengikuti gaya Anda. Apidog CLI mengonfirmasi bahwa implementasi masih sesuai dengan dokumen. Untuk referensi *flag* lengkap, jalankan apidog run --help atau baca panduan CLI lengkap.
Jadi pertukarannya nyata dan patut dinyatakan dengan jelas. Spectral memberi Anda *linter* gratis, dapat diskrip, netral vendor yang Anda rakit dan pelihara. Apidog memberi Anda konsistensi, *mocking*, dokumentasi, dan pengujian yang dapat dijalankan dari satu sumber kebenaran, dengan lebih sedikit yang harus dihubungkan. Jika langkah *lint* portabel dalam *toolchain* yang ada adalah yang Anda butuhkan, Spectral adalah jawaban yang bagus. Jika Anda ingin seluruh siklus hidup bertahan tanpa menjadi proyek *tooling* sendiri, jalur terintegrasi akan lebih murah bagi Anda seiring waktu.
Spectral vs Apidog sekilas
| Kemampuan | Spectral | Apidog |
|---|---|---|
| *Linting* gaya OpenAPI | Ya, melalui spectral:oas + aturan kustom |
Ya, ditampilkan secara langsung di desainer |
| Aturan kustom | Ya, YAML atau JS/TS, Anda memeliharanya | Konvensi ditegakkan oleh editor, tanpa kode aturan |
| Validasi struktural | Dengan Redocly atau *validator* lainnya | Terintegrasi saat waktu desain |
| *Mock server* | Tidak | Ya |
| Dokumen yang dibuat otomatis | Tidak | Ya |
| Pengujian API yang dapat dijalankan | Tidak | Ya, melalui Apidog CLI |
| Gerbang CI | spectral lint --fail-severity=warn |
apidog run keluar dengan kode bukan nol |
| Biaya | Gratis, *open source* | Tingkat gratis, paket berbayar |
Gunakan tabel ini sebagai alat bantu keputusan, bukan sebagai papan skor. Pilihan yang tepat adalah yang sesuai dengan seberapa banyak siklus hidup yang Anda ingin satu alat tangani.
Pertanyaan yang Sering Diajukan
Apakah Spectral gratis? Ya. Spectral adalah *open source* di bawah lisensi Apache 2.0, dikelola oleh Stoplight. CLI, *ruleset* OpenAPI bawaan, dan penulisan aturan kustom semuanya gratis untuk digunakan.
Apakah Spectral memvalidasi bahwa spesifikasi saya legal OpenAPI? Sebagian. Aturan bawaan menangkap banyak masalah struktural, tetapi Spectral adalah *linter*, bukan *validator* skema khusus. Pasangkan dengan *validator* untuk cakupan struktural penuh. Panduan tentang memvalidasi spesifikasi OpenAPI membahas sisi itu, dan alat *validator* OpenAPI terbaik membandingkan pilihannya.
Bisakah Spectral menguji API saya yang sedang berjalan? Tidak. Spectral hanya membaca file spesifikasi. Untuk memeriksa apakah API langsung cocok dengan kontrak, Anda memerlukan *runner* yang mengirimkan permintaan nyata dan menegaskan respons, seperti Apidog CLI.
Bagaimana cara membuat peringatan Spectral menggagalkan *build* CI saya? Jalankan spectral lint openapi.yaml --fail-severity=warn. Secara *default*, hanya tingkat keparahan error yang menggagalkan *build*; --fail-severity=warn juga membuat peringatan mengembalikan kode keluar bukan nol.
Apa perbedaan antara Spectral dan Apidog? Spectral adalah *linter open-source* yang fokus yang Anda konfigurasi dan pelihara. Apidog adalah platform serba ada di mana desain, pemeriksaan konsistensi, *mocking*, dokumentasi, dan pengujian hidup bersama, sehingga Anda tidak perlu banyak merakit dan menjaga sinkronisasi. Lihat Apidog vs Swagger untuk perbandingan terkait lanskap alat desain.
Kesimpulan
Spectral memecahkan masalah nyata yang diabaikan oleh *validator* sederhana: menjaga spesifikasi OpenAPI konsisten dengan konvensi yang disepakati tim Anda. Instal @stoplight/spectral-cli, perluas spectral:oas, tambahkan beberapa aturan kustom, dan gerbang *pipeline* Anda dengan --fail-severity=warn. Bagi banyak tim, itu sudah cukup, dan tidak memakan biaya.
Biaya muncul kemudian, dalam aturan yang Anda pelihara dan sisa siklus hidup yang Anda rangkai di sekitar *linter*. Jika Anda lebih suka mendapatkan konsistensi, *mock*, dokumentasi, dan pengujian yang dapat dijalankan dari satu sumber kebenaran, unduh Apidog dan bangun spesifikasi Anda di mana pemeriksaan sudah menjadi bagian dari permukaan. Bagaimanapun, tujuannya sama: spesifikasi yang dapat dipercaya seluruh tim Anda, ditegakkan oleh mesin alih-alih harapan.
