Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON_API: Output payload schemas und examples in swagger.yaml #2345

Closed
6 tasks
Tracked by #301
carlobeltrame opened this issue Jan 8, 2024 · 3 comments · Fixed by #2369, hitobito/hitobito_sac_cas#234 or hitobito/hitobito_sww#178
Closed
6 tasks
Tracked by #301

Comments

@carlobeltrame
Copy link
Member

carlobeltrame commented Jan 8, 2024

!!! make sure to merge all PRs, or reopen ticket manually !!!

Als Nutzer der neuen JSON:API
möchte ich ein vollständigere und möglichst automatisch aktuell gehaltene API Dokumentation,
um Anbindungen einfacher und/oder automatisiert entwickeln zu können.

Im /api-docs/swagger.yaml fehlt bisher bei den Outputs ein schema und example. Neu soll dies ergänzt und in den Spec-Setup von graphiti bzw. rswag integriert werden, sodass die Specs failen falls die API Doku nicht mehr aktuell ist.

Mockup

Screenshot 2024-01-08 at 15-03-26 Swagger UI

Tech-Spec

  • Swagger ist (unter anderem?) der alte Name von OpenAPI, die beiden Begriffe werden hier synonym benutzt.
  • Graphiti ist das Gem mit dem wir Resourcen definieren und als API Endpoints exponieren
  • rswag ist das Gem das sich in unsere request specs einhängt, die aktuelle OpenAPI Doku mit den echten retournierten Payloads von der getesteten API vergleicht und bei Bedarf die OpenAPI Doku aktualisiert
  • Wir haben sehr spärliche Dev Documentation für die Arbeit mit Graphiti und rswag: https://github.com/hitobito/hitobito/blob/master/doc/development/05_json_api.md#hitobito-developer
  • Wir generieren eigentlich bereits example Payloads gemäss der Doku von rswag, aber sie haben seit 2020 noch vergessen die env variable SWAGGER_DRY_RUN=0 zu dokumentieren. Nur wenn diese Variable auf 0 gesetzt wird, werden die Specs beim Aufruf von rails rswag:specs:swaggerize auch wirklich ausgeführt und die resultierenden Mock-Daten als Examples ins OpenAPI yml geschrieben.
  • Graphiti hat auch noch einen Befehl GraphitiSpecHelpers::RSpec.schema! den man eigentlich in den spec_helper schreiben sollte, der aber unsere Wagon Specs kaputt gemacht hat und den wir daher auskommentiert haben.
    • Dieser Befehl generiert einen zusätzlichen Testcase der IMMER läuft (auch wenn man explizit nur einen einzigen Testcase mit rspec ausführen will) und die Rückwärtskompatibilität der API überprüft.
  • Für automatisierte Tools welche die OpenAPI Doku konsumieren können, kann man in OpenAPI zusätzlich zu Examples auch noch ein JSON Schema für die Response Payloads angeben.
    • In rswag ist es vorgesehen, dass man diese Schemas von Hand pflegt, und zwar direkt in den request specs bzw. im swagger_helper.rb drin. Das könnte dann ungefähr so aussehen:
        response(200, 'successful') do
          produces 'application/vnd.json+api'
          schema type: :object,
                 properties: {
                   data: {
                     type: :array,
                     items: {
                       type: :object,
                       properties: {
                         id: { type: :string },
                         type: { type: :string },
                         attributes: {
                           type: :object,
                           properties: {
                             first_name: { type: :string, nullable: true },
                             last_name: { type: :string, nullable: true },
                             nickname: { type: :string, nullable: true },
                             company_name: { type: :string, nullable: true },
                             company: { type: :boolean },
                             email: { type: :string, nullable: true },
                             address: { type: :string, nullable: true },
                             zip_code: { type: :string, nullable: true },
                             town: { type: :string, nullable: true },
                             country: { type: :string, nullable: true },
                             primary_group_id: { type: :integer, nullable: true },
                             gender: { type: :string, nullable: true },
                             birthday: { type: :string, nullable: true },
                             language: { type: :string, nullable: true },
                           },
                         },
                         required: [:id, :type, :attributes]
                       }
                     }
                   }
                 },
                 required: [ 'data' ]
    
          after do |example|
            example.metadata[:response][:content] = {
              'application/vnd.json+api' => {
                example: JSON.parse(response.body, symbolize_names: true)
              }
            }
          end
          run_test!
        end
    
    Um weniger Duplikation in den mehreren Tests zu haben, könnte man auch einen Teil davon in den swagger_helper.rb auslagern und nur noch referenzieren mit items: { '$ref': '#/components/schemas/indexPerson' }
    • Graphiti generiert allerdings bereits automatisch für alle unsere Resource Klassen ein Schema im JSON Format. Falls möglich könnten wir dieses auch ins benötigte JSON Schema für OpenAPI transformieren und automatisch in den components.schemas im swagger.yaml einsetzen.
    • Falls das zu kompliziert oder aufwändig ist, zurückfallen auf manuelles Up-To-Date halten in den Specs oder in swagger_helper.rb.
  • Noch unklar ist, wie das Ganze dann mit Wagon-Erweiterungen funktionieren soll... Das machen wir dann allenfalls noch in einem separaten Ticket. Erst mal sauber im Core lösen.

ToDo

  • Dev Dokumentation und/oder Docker Dev Setup für die Arbeit mit Graphiti und rswag erweitern, sodass die Examples in Zukunft im swagger.yaml landen
  • schema.json von Graphiti lesen, zu JSON Schema transformieren und im swagger_helper unter components.schemas in swagger_docs einsetzen
  • In den Request Specs, zumindest spec/requests/json_api/people_spec und spec/requests/json_api/groups_spec, die noch fehlenden produces und schema Direktiven einbauen, und dabei '$ref': '#/components/schemas/*' referenzieren
  • Gemäss der aktualisierten Dev Doku das swagger.yaml neu generieren lassen und manuell unter localhost:3000/api-docs überprüfen dass die Examples und Schemas für die dokumentierten Responses aufgelistet sind
  • Optional: Erneut überlegen, ob wir den GraphitiSpecHelpers::RSpec.schema! Befehl nutzen können und wollen, und wie wir ihn sinnvoll aktivieren können so dass er nicht im Weg ist aber trotzdem die Rückwärtskompatibilität überprüft wenn man alle Tests laufen lässt
  • Nicht optional: Sicherstellen dass die Wagon Tests weiterhin funktionieren. Sobald der Code auf einem Branch auf Master ist, kann man im Wagon manuell das CI anstossen und dabei den gewünschten Core Branch auswählen.
@daniel-illi
Copy link
Contributor

daniel-illi commented Jan 10, 2024

note to self:

daniel-illi added a commit to hitobito/hitobito_sac_cas that referenced this issue Jan 19, 2024
daniel-illi added a commit to hitobito/hitobito_sww that referenced this issue Jan 19, 2024
@daniel-illi daniel-illi removed their assignment Jan 19, 2024
@carlobeltrame carlobeltrame removed their assignment Jan 30, 2024
@daniel-illi daniel-illi self-assigned this Jan 31, 2024
daniel-illi added a commit to hitobito/hitobito_sww that referenced this issue Jan 31, 2024
daniel-illi added a commit to hitobito/hitobito_sww that referenced this issue Jan 31, 2024
daniel-illi added a commit to hitobito/hitobito_sac_cas that referenced this issue Jan 31, 2024
daniel-illi added a commit to hitobito/hitobito_sac_cas that referenced this issue Jan 31, 2024
@daniel-illi daniel-illi removed their assignment Mar 1, 2024
@patrickuhlmann
Copy link

Feedback aus dem Test von Cevi: Ich habe die Seite ausprobiert jedoch konnte ich keine gültigen Requests machen. Die angegebene Url war: https://cevi.puzzle.ch/api/://api/events?include=dates&token=xyz -> siehe /api/://api. Vermutlich ist das noch was falsch in der Konfiguration. In der Auswahlliste der Server wird auch nur :// - production angezeigt. Das sieht auch etwas komisch aus für eine Integrationsumgebung.

@carlobeltrame
Copy link
Member Author

carlobeltrame commented Mar 31, 2024

Ja, merci, das ist uns auch schon aufgefallen, wird in #2467 getrackt. Das Try It Out Feature zu fixen hat aber aktuell keine Priorität. Der SAC wollte primär mal dass man automatisch API-Clients generieren kann, wofür wir das JSON Schema in der OpenAPI Spec erweitern mussten.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment