Skip to content

Use rswag to update openapi spec#2085

Merged
sanason merged 9 commits into
mainfrom
add-swagger-api-docs
Jul 1, 2026
Merged

Use rswag to update openapi spec#2085
sanason merged 9 commits into
mainfrom
add-swagger-api-docs

Conversation

@sanason

@sanason sanason commented Jun 24, 2026

Copy link
Copy Markdown
Member

The purpose of this PR is to update the OpenAPI spec for the V1 Touchpoints API. The updated spec adds documentation for the following endpoints:

  • /forms/{id}/responses
  • /service_providers
  • /services
  • /services/{id}
  • /cx_collection_details
  • /cx_collections
  • /cx_responses

It removes documentation for two digital registry endpoints:

  • /digital_products
  • /digital_service_accounts

Those endpoints still exist but, since the public-facing digital registry was shuttered in 2024, I'm not willing to maintain the documentation for the corresponding API endpoints. /websites is still documented because I know that GSA is still using the website registry as its internal inventory tool.

Adding a tool to automate generation of API documentation

I'm not sure how the OpenAPI spec was maintained previously but there weren't any spec automation libraries listed in the Gemfile. I adopted the Rswag tool to help with automation. Setting up Rswag is how this PR got so big.

With the addition of Rswag, the V1 spec file (public/api/v1/openapi.yml) becomes a generated file. It is generated by the command:

RSWAG_DRY_RUN=0 bundle exec rake rswag:specs:swaggerize

It's still a version controlled file because changes to it should be reviewed since it is human-facing documentation. Since it is a generated, version-controlled file, I added a CI step to check that developers are re-running the generation script before commits so the spec does not drift from the actual API.

Rswag doesn't really reduce the manual effort required to create the OpenAPI spec. But it helps the developer to write accurate documentation because it runs tests that actually call the API and validate the request/response against what the documentation says.

Other miscellaneous changes

  • Cleaned up a couple of abandoned API endpoints
  • Set the entire V1 API to be json by default. It's no longer required to add .json to the end of the URL in your API calls (though it still works if you do).

AI-assisted: authored with an AI coding agent under human review.

@sanason sanason linked an issue Jun 24, 2026 that may be closed by this pull request
Comment thread spec/factories/cx_collection_detail_upload.rb Fixed
Comment thread spec/factories/cx_collection_detail_upload.rb Fixed
Comment thread spec/factories/cx_collection_detail_upload.rb Fixed
Comment thread spec/factories/cx_collection_detail_upload.rb Fixed
@@ -1,19 +0,0 @@
# frozen_string_literal: true

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safe to delete - no routes are mapped to this controller.

@@ -27,6 +27,7 @@ def index
meta: {
current_page: cx_responses.current_page,
size: cx_responses.size,

@sanason sanason Jun 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this here so it matches the meta block in /forms/{id}/responses.

if current_user.organizational_admin?
render json: current_user.organization.forms
.order(:id)
.limit(100), each_serializer: FormSerializer

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this undocumented and arbitrary limit. A safer solution would be to add pagination but the API already has a bunch of unlimited endpoints and I don't think this one is more of a risk than any of them.

Comment thread config/routes.rb
end
namespace :v1 do
resources :organizations, only: [:index]
resources :collections, only: [:index]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleting because this route has no corresponding controller.

it 'expects volume to be 1,000 each (and not the sum of all responses: regression)' do
expect(csv.class).to eq(CSV::Table)
expect(csv.size).to eq(2)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed because the factory changed.

Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
Comment thread spec/factories/cx_collection_detail_upload.rb Dismissed
@sanason sanason merged commit 983d02e into main Jul 1, 2026
6 checks passed
@sanason sanason deleted the add-swagger-api-docs branch July 1, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve Touchpoints API documentation

2 participants