OpenAPI-docs-for-the-endpoints
We introduced here the feature of auto generating OpenAPI schema for our endpoints starting from the request specs.
We forked the gem (rspec-openapi) used for this feature in order to customise some behaviours.
The generated schema files can also be edited manually because rspec-openapi will append or update (no removal of data) only the information that can be extracted from the specs.
The request specs don't require special changes, see below for more information.
API docs project
The updated schema files can be published with a PR to the project uala-api-docs.
Development
Development flow in that project is easier than the one for uala-backend, and it just require the PR to be open and reviewed by the team.
Once the PR is merged to master branch, the Drone CI build in the uala-api-docs repo will also deploy it to production without further actions needed. Note this is unrelated to uala-backend's own CI/CD, which is on GitHub Actions — see CI - Continuous Integration.
Access to API documentation
The OpenAPI application is deployed in our infrastructure as a swagger application available at:
!ref uala-backend API documentation
If access credentials are needed, ask the team for them.
Usage
You can update the wanted endpoints running:
OPENAPI=1 OPENAPI_OUTPUT_BASEDIR=~/projects/uala-api-docs/spec bundle exec rspec spec/controllers/api/v2/account
OPENAPI=1env var will trigger the generation process;OPENAPI_OUTPUT_BASEDIR=...permit to specify the output schema base directory (it should match thespec/directory inside your local checkout of uala-api-docs repository) - if skipped it will usedoc/;
Specs
Optionally, it's possible to override specific information of an example:
describe 'GET /api/v1/posts', openapi: {
summary: 'list all posts',
description: 'list all posts ordered by pub_date',
tags: %w[v1 posts],
} do
# ...
end
While working on a new endpoint it can be useful to create an empty spec to generate the OpenAPI contract, example:
# spec/test_spec.rb
RSpec.describe 'Api::V1::MyController', type: :request do
describe 'GET /test2' do
before do
# Controller setup
class MyController < Api::V1::BaseController
def test2
render json: 'boh'
end
end
# Routes setup
app.routes.draw do
namespace :api do
namespace :v1 do
resources :checkouts do
collection do
get '/test2', to: ->(env) do
request = ActionDispatch::Request.new(env)
response = MyController.make_response!(request)
MyController.dispatch('test2', request, response)
end
end
end
end
end
## Simple route
# get '/test' => ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['A TEST']] }
end
end
it 'returns "boh"', :aggregate_failures do
# get '/test'
get '/api/v1/checkouts/test2'
expect(response).to be_successful
expect(response.body).to eq 'boh'
end
end
end
And generate the schema with:
OPENAPI=1 bundle exec rspec spec/test_spec.rb
# => doc/path/to/schema.yaml
Caveats
Updating an existing schema
rspec-openapi doesn't overwrite schemas, but merges them. So, if you change an endpoint let's say removing an attribute, when you generate the schema the attribute is going to be still present in the generated schema. A workaround for that is to remove the generated schema file that is going to be overwritten, so that when you generate the schema again rspec-openapi doesn't find it and rewrites the schema from scratch.