Skip to content

Regenerate api.md

Regenerate api.md #19

Workflow file for this run

# 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