使用 Swagger 检测破坏性 API 变更

  2015年10月8日

作者: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 (类型: array)

- 缺失请求参数:limit (类型: 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 博客

© . All rights reserved.