季節の変わり目に心まで震えてます。chotaroです。
ICPチームでは日々、OpenAPI V3に即してAPIの設計を行なっています。gitlabでは、GUIでSpecを閲覧することができるため、大変便利です。
ですが、この閲覧機能lintまではやってくれないため、気づいたらエラー出るようになってるじゃん!ということであったり、細かい部分の表記揺れはどうしても出てきます。typeはstringで記載されているのに、exampleは数字じゃん!ということもままあります。
致命的な問題には今の所なっていないのですが、後から検知して直すというのも面倒だし、何か起きたら嫌なのでlintするツールないのかな?というのが今回の動機です。
Spectralを使ってみよう
spactralは、JSONやymlファイルをlintすることに特化したツールです。
与えられたルールをもとに、各ファイルの文法や記法をチェックすることができる作りになっており、汎用性高く設計されています。
ルールはrulesetsという形式で定まっていて、デフォルトで利用できるRulesetsにOpenAPI V2, V3用のものも含まれているため、すぐにICPのSpecをlintするために利用することができます。
インストール
コマンドとしてのinstallはnpmで一発です。
npm install -g @stoplight/spectral-cli
もしくはnpxで実行することも可能
npx @stoplight/spectral-cli lint target.yml
OpenAPIのlint設定
先述のようにOpenAPI用のルールセットはデフォルトで用意されているので、それを使う設定をlint対象と同じdirに作成する
echo '{\n\t"extends": ["spectral:oas"]\n}' > .spectral.json
ルールの詳細はこちらのページに記載されているのに加えて、手動でカスタマイズすることもできる。(今回の私のように表記方法を統一したい、くらいのモチベーションであればデフォルトのルールで十分な印象があります。デフォルトの時点でとても細かい。)
lintの実行
/repos/api-docs/v1: spectral --version 6.1.0 /repos/api-docs/v1: spectral lint openapi.yml /repos/api-docs/v1/openapi.yml 2:6 warning info-contact Info object must have "contact" object. info ...[省略]... ✖ 91 problems (34 errors, 57 warnings, 0 infos, 0 hints)
😱
ログは丁寧に出ているし、確認すると確かに矛盾している部分とかもあったので、間違いが内在しているのは事実なようなので歯を噛み締めて対応したいところですね、、、
Spectralの良いところと困ること
ICPのSpecは $refを利用して、機能ごとに分割されています。
Spectralでは、デフォルトのrulesetsでもこのrefを深掘りして不適切ながないかをチェックしてくれます。えらい。
反面で困りごとでもあります。深掘りをするのはいいんですが、深掘りした先まではネストして行数を表示してくれないため、該当箇所の参照元まで行って、どの要素で怒られてるのかを調べる必要があります。仕方ない。。。
メリットの裏返しですが、特に導入時点ですこし手間がかかってしまうかも。
活用方法などの応用編
gitlab-ciに入れ込んでみる
npmが使えるimageを利用すれば、簡単にnpxで実行することもできるので、Circle CI向けの設定を参考に
lint-openapi: image: node:16.12-alpine stage: test script: - cd ${CI_PROJECT_DIR}/api-docs/v1 - npx @stoplight/spectral-cli lint openapi.yml
これでよし。
spectral-cli
のinstall含めても20秒ほどで完了しているため、CIとして実行する分には良さそうです。
vscode plugin
2021/10/27時点でPreviewですが、vscodeのプラグインも用意されています。
ローカルではこれで確認しつつ、CIでもチェックする、が良さそう。
lint結果の制御
defaultだとerror以上でexit codeが1になります。
-F, --fail-severity results of this level or above will trigger a failure exit code [string] [choices: "error", "warn", "info", "hint"] [default: "error"]
Optionで閾値を制御可能。Errorが出てても成功にする、というのはなさそうなので上述のErrorくん達はどうしても対応しなきゃいけない。
そういえばrulesetsってどんなのがあるの?
先述したように、Spectralのlintのルールはrulesetと呼ばれるものによって定義されます。
ルールさえあれば、どんなjsonもymlもlintできるはず。
公式提供はOpenAPIとAsyncAPIの二種類 が用意されています。そのほかに有志のユーザーが作ったものがあればそれも利用してチェックできると。
OpenAPI以外で公開されているルールは・・・?
https://github.com/search?q=spectral+rulesets
githubだとほぼないですね。。。
実質ほぼ公式提供のOpenAPI向けに使われているのが現状なのかな?
終わりに
ここまで見てきて、
導入時点でError取り切る -> ローカルではvscodeでlintチェック -> CIでもlintして警告出してくれるようにする
がいい気がしています。初期導入時には直しきらないといけないので大変ですが、一度通したらあとは常に警告を気にするようになるので、フォーマット面での迷いはなくなりそう。
カスタマイズするかどうかは難しいとこですが、内容が一見して細かすぎるのでひとまずはデフォルトで利用しつつ、窮屈さを感じてきたら検討かなと。とりあえずこれ書いてる現時点ではまだチーム共有してないので、上記のたくさんのErrorを消しつつ共有して活用していけたらかなと思います。
それではー。