Regenerate api.md #13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Regenerate `api.md` from the engine's RPC registry once a day. | |
| # | |
| # `api.md` used to live in `nasty-project/nasty` next to the source it | |
| # was generated from. After it moved here in 2026-03 the regeneration | |
| # pipeline didn't come with it, so the file went stale. | |
| # | |
| # This workflow checks out the nasty repo's `main`, runs the engine | |
| # binary in its `--dump-docs` CLI mode (which walks every | |
| # `JsonSchema`-derived type and emits the markdown + openapi.json), then: | |
| # | |
| # 1. Copies api.md on top of this repo's api.md and commits if changed. | |
| # 2. Bundles openapi.json + the vendored Swagger UI assets from the | |
| # nasty repo into a tiny static site and deploys it to Cloudflare | |
| # Pages (nasty-api.pages.dev). Same UX the engine serves at | |
| # /api/docs on a real box, but published publicly so users can | |
| # browse the API surface without installing anything. | |
| # | |
| # The generator was a standalone `nasty-apidoc` binary until | |
| # nasty PR #350; that crate was deleted and its responsibility folded | |
| # into `nasty-engine --dump-docs` so the registry and the dispatcher | |
| # live in the same crate and stop drifting. | |
| # | |
| # Up to ~24h lag behind the engine's RPC surface — fine for an API | |
| # reference, and avoids the cross-repo PAT setup the on-every-push | |
| # variant would need. | |
| name: Regenerate api.md | |
| on: | |
| schedule: | |
| # 04:00 UTC = quiet on the runner side, well after the integration | |
| # tests have finished their nightly cycle in the source repo. | |
| - cron: '0 4 * * *' | |
| workflow_dispatch: | |
| permissions: | |
| # Needed for the final `git push` of the regenerated file. | |
| contents: write | |
| concurrency: | |
| group: regen-api-md | |
| # Cancel any already-running daily — if the previous one is still | |
| # going we'd just race it to the same commit. | |
| cancel-in-progress: true | |
| jobs: | |
| regen: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # 1. Check this repo out so we can commit the result back. | |
| - name: Checkout nasty-docs | |
| uses: actions/checkout@v5 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| # 2. Check the source repo (nasty) out into a sibling dir. The | |
| # engine's --dump-docs mode writes `api.md` (and `openapi.json`) | |
| # into whatever directory we point it at; we pick `nasty/docs/` | |
| # to match the historical location the standalone apidoc | |
| # binary used. | |
| - name: Checkout nasty | |
| uses: actions/checkout@v5 | |
| with: | |
| repository: nasty-project/nasty | |
| ref: main | |
| path: nasty | |
| # 3. Rust toolchain pinned to what the source repo uses. Keep in | |
| # sync with `engine/rust-toolchain.toml` in the nasty repo — | |
| # bumping there is the trigger to bump here. | |
| - name: Set up Rust | |
| uses: dtolnay/rust-toolchain@1.95.0 | |
| # 4. Cache cargo artifacts across runs so this stays a 1-2 min | |
| # job in steady state. Cold cache is now ~15 min (was ~10 with | |
| # apidoc; the engine binary is heavier — Axum, schemars, the | |
| # whole router workspace); cache hit stays a couple of minutes. | |
| - name: Cargo cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: nasty/engine -> target | |
| - name: Generate api.md | |
| working-directory: nasty/engine | |
| # `--dump-docs <dir>` writes `api.md` + `openapi.json` into | |
| # `<dir>`. We only consume the markdown here; the OpenAPI spec | |
| # is served live by the running engine at /api/openapi.json. | |
| run: cargo run --release -p nasty-engine -- --dump-docs ../docs | |
| - name: Copy generated api.md | |
| run: cp nasty/docs/api.md api.md | |
| # 5. Commit only if anything moved. `git diff --quiet` returns | |
| # 1 (= changes present) when api.md content drifted from the | |
| # last checked-in version. No-op runs are normal between | |
| # real engine changes. | |
| - name: Commit if changed | |
| run: | | |
| if git diff --quiet api.md; then | |
| echo "api.md unchanged, nothing to commit" | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| # Source-repo HEAD SHA goes in the commit message so it's | |
| # obvious which engine state the regeneration captured. | |
| NASTY_SHA=$(git -C nasty rev-parse --short HEAD) | |
| git add api.md | |
| git commit -m "api.md: regenerate from nasty@${NASTY_SHA}" | |
| git push | |
| # 6. Bundle the static Swagger UI site and push it to | |
| # Cloudflare Pages (nasty-api.pages.dev). | |
| # | |
| # Same shape as the /api/docs page the engine serves on a real | |
| # box: a tiny index.html mounting SwaggerUIBundle against an | |
| # openapi.json sibling, plus the vendored swagger-ui assets | |
| # from nasty/vendor/swagger-ui/ (pinned upstream in the nasty | |
| # repo — bumping the version there propagates here on the next | |
| # nightly). | |
| # | |
| # `persistAuthorization` is intentionally omitted (it lives on | |
| # the engine's /api/docs because there's a real session cookie | |
| # in scope; there's no engine to authenticate against from a | |
| # public CDN page). | |
| - name: Bundle static site | |
| run: | | |
| mkdir -p site | |
| cp nasty/docs/openapi.json site/openapi.json | |
| cp nasty/vendor/swagger-ui/swagger-ui.css site/ | |
| cp nasty/vendor/swagger-ui/swagger-ui-bundle.js site/ | |
| cat > site/index.html <<'HTML' | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>NASty API</title> | |
| <link rel="stylesheet" href="./swagger-ui.css"> | |
| <style>body { margin: 0; background: #fafbfc; }</style> | |
| </head> | |
| <body> | |
| <div id="swagger-ui"></div> | |
| <script src="./swagger-ui-bundle.js"></script> | |
| <script> | |
| window.onload = () => { | |
| window.ui = SwaggerUIBundle({ | |
| url: './openapi.json', | |
| dom_id: '#swagger-ui', | |
| deepLinking: true | |
| }); | |
| }; | |
| </script> | |
| </body> | |
| </html> | |
| HTML | |
| - name: Deploy to Cloudflare Pages | |
| uses: cloudflare/wrangler-action@v3 | |
| with: | |
| apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| # `--branch=main` flags this as a production deployment so the | |
| # nasty-api.pages.dev apex points at it; without it, each push | |
| # would land on a preview URL only. | |
| command: pages deploy site --project-name=nasty-api --branch=main |