Skip to content

Conversation

@tang-mm
Copy link
Contributor

@tang-mm tang-mm commented Dec 17, 2025

Description

This pull request introduces the functionality to:

  • (Server) export the server's OpenAPI specification into a JSON file stored in the repository (This file will be the same as the one in the web application at the /docs URL)
    • Created a minimal Flask app entry using TESTING mode, so that Flask CLI can be used for spec generation without MongoDB
    • Add the initial/current version of API spec at server/openapi.json
  • (docs) serve the API reference within Read the Docs documentation, making it publicly accessible
  • (CI check) keep the OpenAPI specification file in sync with the server API code
    • Added openapi-check tox environment that compares the spec file in the working directory against a newly generated version
    • Added CI validation step in server-tox.yml workflow

Resolved issues

Resolves CERTTF-243

Documentation

  • Added docs/reference/openapi.rst with Swagger UI integration. The JSON file is copied from the server/ directory to docs/ during doc build, and the copy only exists in the build output. (Same changes as in docs: Add Swagger UI for OpenAPI reference documentation hardware-api#456)
  • Updated a few titles and section descriptions in the Reference section for clarity (page URLs are unchanged)
  • Updated Contributing guide with instructions about how to check and update the API spec.

Preview: https://canonical-testflinger--852.com.readthedocs.build/852/reference/openapi/#/

Web service API changes

(No API changes introduced. This PR adds infrastructure to document the existing API.)

Tests

  • PR check will fail if the current spec file cannot be generated, or is not consistent with the server API code
  • Local test:
    # generate the spec file
    cd server/
    FLASK_APP=devel.openapi_app uv run flask spec --output ./openapi.json --quiet
    
    # Check if update needed
    uvx --with tox-uv tox -e openapi-check  

@tang-mm tang-mm force-pushed the certtf-243-docs-openapi branch from 7f0c1ac to 0a506ca Compare December 17, 2025 03:07
@tang-mm tang-mm force-pushed the certtf-243-docs-openapi branch from 0a506ca to 8be0e10 Compare December 17, 2025 03:12
@codecov
Copy link

codecov bot commented Dec 17, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.31%. Comparing base (e8f6add) to head (3023c18).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #852   +/-   ##
=======================================
  Coverage   71.31%   71.31%           
=======================================
  Files         108      108           
  Lines        9651     9651           
  Branches      858      858           
=======================================
  Hits         6883     6883           
  Misses       2595     2595           
  Partials      173      173           
Flag Coverage Δ *Carryforward flag
agent 72.85% <ø> (ø) Carriedforward from cf26f57
cli 87.78% <ø> (ø) Carriedforward from cf26f57
device 55.21% <ø> (ø) Carriedforward from cf26f57
server 87.71% <100.00%> (ø)

*This pull request uses carry forward flags. Click here to find out more.

Components Coverage Δ
Agent 72.85% <ø> (ø)
CLI 87.78% <ø> (ø)
Common ∅ <ø> (∅)
Device Connectors 55.21% <ø> (ø)
Server 87.71% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Contributor

@rene-oromtz rene-oromtz left a comment

Choose a reason for hiding this comment

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

This looks really great, thanks for taking care of this!
I just added couple comments that I think will make more "simple" running the flask spec but let me know what you think.

Also, do you think we should also remove the awful to maintain API.md in this PR? The whole purpose of that file was not rely in a testflinger connection to review the /docs but this PR already solves that so I think it can go...

@pedro-avalos
Copy link
Collaborator

I agree with @rene-oromtz I think the API.md file should go. The openapi.yaml file is a good standard to define the API endpoints. However, I think the API.md document has more metadata (such as error responses) that should be added to our endpoint definitions.

I think this PR can move along and merge without removing the API.md file, and a follow-up PR should both delete it and update any endpoints with any missing metadata. That should simplify the work that @tang-mm needs to do for this documentation update.

@rene-oromtz
Copy link
Contributor

rene-oromtz commented Dec 17, 2025

Ah I was about to open a Jira issue to track this when I realized @tang-mm already created one! (CERTTF-780).

Please ignore my comment then related to API.md, just remains the minor nitpick about using uv

@pedro-avalos
Copy link
Collaborator

pedro-avalos commented Dec 17, 2025

@tang-mm you inspired me with this PR to look at how we check and generate it in hardware-api, and I think I found a simpler solution. See: canonical/hardware-api#483. Also, I'd like to standardize the tox environment; I think schema and check-schema (verb first) makes sense since we don't really provide any other schemas in our projects, but I'm open to using openapi and check-openapi if you'd like.

Hardware API uses FastAPI rather that APIFlask, so there are some differences. However, I think you can use what I wrote and change the .openapi() call with .spec to get the dictionary version of the OpenAPI schema, and then use the json package instead of yaml. See: https://apiflask.com/openapi/.

tang-mm and others added 2 commits December 18, 2025 11:12
Co-authored-by: rene-oromtz <157750458+rene-oromtz@users.noreply.github.com>
change to use the APIFlask.spec attribute to get the schema object
in dict form, instead of using the string-based CLI output.
@tang-mm
Copy link
Contributor Author

tang-mm commented Dec 18, 2025

@pedro-avalos @rene-oromtz I updated the implementation - instead of using Flask CLI to get the string output, it now calls the APIFlask.spec attribute to retrieve the JSON object.

With regards to naming, I agree with the verb-first format. I'm open to validating all schemas (if we have new ones other than the API) in the same tox env. So I updated the name to check-schema, and also moved the JSON file to a new directory server/schemas/openapi.json

@tang-mm tang-mm requested a review from rene-oromtz December 18, 2025 14:36
Copy link
Collaborator

@pedro-avalos pedro-avalos left a comment

Choose a reason for hiding this comment

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

One minor change, otherwise looks good to me

parser.add_argument(
"--output",
type=Path,
default=Path("./openapi.json"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

The docstring for this script says that running without arguments will print to stdout. This should therefore be default=None

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fix added in 3023c18

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.

4 participants