使用 Swagger 检测 API 的破坏性更改

  2015 年 10 月 08 日

作者:Jeff Cousens,Civis - Analytics 高级工程师

不久前,我们决定 Civis 平台 中的所有新功能都将通过 API 端点和前端代码的组合来实现。与此同时,我们决定所有端点都将对我们的客户开放。也就是说,如果您可以通过 Civis UI 使用某项功能,您也可以利用底层 API 进行编程访问。这已经是一个巨大的力量倍增器,您可以在Civis API:扩展您的数据科学中阅读相关内容。这也意味着我们的工程团队不能仅仅为了满足 UI 的需求而破坏我们的 API 契约。

一种解决方案是依赖于 API 版本,该版本从一开始就内置于 Civis API 中。但即使有了版本,我们仍然需要知道更改是否构成破坏性更改。我们认为以下情况属于破坏性更改:

  • 删除端点
  • 添加新的必需请求参数
  • 删除或更改请求参数或响应属性的类型

发布的指南很好,但可能会出错。我们更喜欢利用自动化解决方案来编纂我们的最佳实践,并明确和执行我们的策略。考虑到这一点,我们编写了 Swagger::Diff。Swagger::Diff 比较两个 Swagger 规范并识别任何破坏性更改。例如,要将 Swagger 项目的扩展 petstore 示例与最小 petstore 示例进行比较,验证扩展示例与最小示例向后兼容

$ 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

- 缺少端点

- delete /pets/{}

- get /pets/{}

- post /pets

- 不兼容的请求参数

- get /pets

- 缺少请求参数:tags (type: array)

- 缺少请求参数:limit (type: integer)

- 不兼容的响应属性

- get /pets

- 缺少默认响应

Swagger::Diff 还直接与我们的测试套件集成。人们可能会忘记运行检查,但持续集成 (CI) 不会。再加上一个返回我们当前 Swagger 规范的 API 端点,它允许我们通过 请求规范 简单轻松地比较 API 的两个版本

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。

我们已在 BSD 3-Clause 许可下开源了 Swagger::Diff,并将 gem 发布到 RubyGems.org,并在 GitHub 上提供了源代码。我们鼓励您将其添加到您的 CLI 工具集、项目 CI 或测试套件中,并且我们欢迎问题或拉取请求。

这篇文章最初发表在 Civis 博客上。