From a6f872bf692740c8c70591a79fdbe150c210bc7b Mon Sep 17 00:00:00 2001 From: Donkie Date: Mon, 3 Apr 2023 19:25:27 +0200 Subject: [PATCH] Added docs generation --- .github/workflows/apidocs.yml | 41 +++++++++++++++++++++ .gitignore | 1 + pyproject.toml | 10 ++++++ spoolman/api/v1/router.py | 2 +- spoolman/docs.py | 67 +++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/apidocs.yml create mode 100644 spoolman/docs.py diff --git a/.github/workflows/apidocs.yml b/.github/workflows/apidocs.yml new file mode 100644 index 0000000..78f69b5 --- /dev/null +++ b/.github/workflows/apidocs.yml @@ -0,0 +1,41 @@ +name: Generate and deploy API documentation +on: + push: + branches: ["master"] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + - run: pip install -e . + - run: spoolman_docs + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Upload artifact + uses: actions/upload-pages-artifact@v1 + with: + path: 'docs/' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/.gitignore b/.gitignore index f994a35..3889b93 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ instance/ # Sphinx documentation docs/_build/ +docs/ # PyBuilder .pybuilder/ diff --git a/pyproject.toml b/pyproject.toml index 99da56a..5fe939f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,10 @@ version = "0.1.0" requires-python = ">=3.9" readme = "README.md" license = {text = "AGPL-3.0-only"} +dynamic = ["dependencies"] + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} [tool.ruff] select = ["ALL"] @@ -16,3 +20,9 @@ target-version = "py39" line-length = 120 target-version = ['py39'] +[build-system] +requires = ["setuptools>=67.0"] +build-backend = "setuptools.build_meta" + +[project.scripts] +spoolman_docs = "spoolman.docs:generate_docs" diff --git a/spoolman/api/v1/router.py b/spoolman/api/v1/router.py index d075c11..5bc0405 100644 --- a/spoolman/api/v1/router.py +++ b/spoolman/api/v1/router.py @@ -12,7 +12,7 @@ from . import filament, models, spool, vendor # ruff: noqa: D103 app = FastAPI( - title="Spoolson REST API v1", + title="Spoolman REST API v1", version="1.0.0", root_path_in_servers=False, responses={404: {"model": models.Message}}, diff --git a/spoolman/docs.py b/spoolman/docs.py new file mode 100644 index 0000000..6a9b2da --- /dev/null +++ b/spoolman/docs.py @@ -0,0 +1,67 @@ +"""Functions for generating documentation.""" + +from contextlib import suppress +import json +from pathlib import Path +from typing import Any + +from fastapi import FastAPI +from fastapi.openapi.utils import get_openapi + +from spoolman.api.v1.router import app as v1_app + + +def generate_openapi(app: FastAPI) -> dict[str, Any]: + """Generate the OpenAPI document for a specific FastAPI app. + + Args: + app (FastAPI): The FastAPI app. + + Returns: + dict[str, Any]: The OpenAPI document. + """ + return get_openapi( + title=app.title, + version=app.version, + openapi_version=app.openapi_version, + description=app.description, + routes=app.routes, + contact=app.contact, + license_info=app.license_info, + servers=app.servers, + tags=app.openapi_tags, + terms_of_service=app.terms_of_service, + ) + + +def generate_docs() -> None: + """Generate documentation for this service in the docs/ directory.""" + + with suppress(FileExistsError): + Path("docs").mkdir() + + spec = json.dumps(generate_openapi(v1_app)) + + with Path("docs", "index.html").open("w") as f: + f.write( + f""" + + + + Spoolson REST API v1 - ReDoc + + + + + + + +
+ + + + """, + )