Swaggerを使用してAPIの破壊的変更を検出する

  2015年10月08日

著者:Jeff Cousens、Civis - Analyticsのシニアスタッフエンジニア

しばらく前、私たちはCivisプラットフォームのすべての新機能は、APIエンドポイントとフロントエンドコードの組み合わせとして実装されると決定しました。同時に、すべてのエンドポイントがお客様に利用可能になると決定しました。つまり、Civis UIを介して機能の一部を使用できる場合、プログラムによるアクセスには基盤となるAPIも活用できます。これについては、The Civis API: Scale Up Your Data Scienceで読むことができるように、これは大きな相乗効果をもたらしました。また、これは当社のエンジニアリングチームが、UIのニーズに合うからといって、API契約を破ることができないことを意味します。

1つの解決策は、Civis APIに最初から組み込まれていたAPIバージョンに依存することです。しかし、バージョンがあったとしても、変更が破壊的変更を構成するかどうかを知る必要があります。私たちは以下を破壊的変更と見なします。

  • エンドポイントを削除する
  • 新しい必須リクエストパラメータを追加する
  • リクエストパラメータまたはレスポンス属性のタイプを削除または変更する

公開されたガイドラインは良いものですが、誤りがある可能性があります。私たちは、ベストプラクティスを成文化し、ポリシーを明示して強制する自動化されたソリューションを活用することを好みます。これを念頭に置いて、私たちはSwagger::Diffを作成しました。Swagger::Diffは、2つのSwagger仕様を比較し、破壊的変更を特定します。たとえば、Swaggerプロジェクトの拡張ペットストア例と最小ペットストア例を比較し、拡張例が最小例と下位互換性があることを確認するには、次のようにします。

$ gem install swagger-diff

$ wget https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/json/petstore-minimal.json

$ wget https://raw.githubusercontent.com/swagger-api/swagger-spec/master/examples/v2.0/json/petstore-expanded.json

$ swagger-diff petstore-minimal.json petstore-expanded.json

引数の順序を入れ替えると、最小例と拡張例を比較し、最小例に欠落しているエンドポイント、パラメータ、属性をフラグ付けします。

$ swagger-diff petstore-expanded.json petstore-minimal.json

- 欠落しているエンドポイント

- /pets/{}を削除

- /pets/{}を取得

- /petsをPOST

- 互換性のないリクエストパラメータ

- /petsを取得

- 欠落しているリクエストパラメータ: tags (type: array)

- 欠落しているリクエストパラメータ: limit (type: integer)

- 互換性のないレスポンス属性

- /petsを取得

- デフォルトのレスポンスが欠落

Swagger::Diffは、テストスイートと直接統合もされています。人はチェックを忘れるかもしれませんが、継続的インテグレーション(CI)は忘れません。現在のSwagger仕様を返すAPIエンドポイントと組み合わせることで、リクエストスペックを介してAPIの2つのバージョンを簡単かつ容易に比較できます。

it 'is backwards compatible' do

production_swagger = open('https://host.domain/endpoints').read

get '/endpoints'

test_swagger = response.body

expect(test_swagger).to be_compatible_with(production_swagger)

end

コードをプッシュするたびに、CIは開発ブランチを本番仕様に対してテストし、下位互換性のない変更が導入された場合は、その詳細を示すメッセージとともに失敗します。これにより、下位互換性のない変更が誤ってAPIに紛れ込むことがないよう保証されます。

私たちはSwagger::DiffをBSD 3-Clause Licenseの下でオープンソース化し、gemをRubyGems.orgに公開し、ソースをGitHubで利用できるようにしました。CLIツールセット、プロジェクトのCI、またはテストスイートに追加することをお勧めします。また、問題やプルリクエストも歓迎します。

この記事は、元々Civisブログで公開されました。