diff --git a/.github/workflows/docs-nav.yaml b/.github/workflows/docs-nav.yaml new file mode 100644 index 00000000..fc4c8152 --- /dev/null +++ b/.github/workflows/docs-nav.yaml @@ -0,0 +1,32 @@ +name: Docs navigation + +permissions: + contents: write + pull-requests: write + +on: + workflow_dispatch: + pull_request: + paths: + - "docs/sdks/**" + - "scripts/gen-docs-nav.sh" + - ".github/workflows/docs-nav.yaml" + +jobs: + gen-docs-nav: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + ref: ${{ github.event.pull_request.head.ref }} + token: ${{ secrets.GITHUB_TOKEN }} + + # jq is preinstalled on GitHub-hosted ubuntu runners. + - name: Regenerate docs navigation + run: scripts/gen-docs-nav.sh + + - name: Auto-commit docs.json navigation + uses: int128/update-generated-files-action@v2 + with: + commit-message: "Chore: regenerate docs navigation" diff --git a/docs/docs.json b/docs/docs.json index e7e14135..2a0e3fd0 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -11,37 +11,39 @@ "groups": [ { "group": "Getting Started", - "pages": ["overview"] + "pages": [ + "overview" + ] }, { "group": "API Reference", "pages": [ + "sdks/analytics/README", + "sdks/apikeys/README", + "sdks/benchmarks/README", + "sdks/betaanalytics/README", + "sdks/byok/README", "sdks/chat/README", - "sdks/responses/README", - "sdks/models/README", - "sdks/embeddings/README", - "sdks/rerank/README", - "sdks/images/README", - "sdks/tts/README", - "sdks/stt/README", - "sdks/videogeneration/README", "sdks/classifications/README", - "sdks/generations/README", - "sdks/endpoints/README", - "sdks/providers/README", "sdks/credits/README", - "sdks/apikeys/README", - "sdks/oauth/README", - "sdks/byok/README", - "sdks/presets/README", - "sdks/guardrails/README", "sdks/datasets/README", + "sdks/embeddings/README", + "sdks/endpoints/README", "sdks/files/README", - "sdks/analytics/README", - "sdks/betaanalytics/README", - "sdks/benchmarks/README", + "sdks/generations/README", + "sdks/guardrails/README", + "sdks/images/README", + "sdks/models/README", + "sdks/oauth/README", "sdks/observability/README", "sdks/organization/README", + "sdks/presets/README", + "sdks/providers/README", + "sdks/rerank/README", + "sdks/responses/README", + "sdks/stt/README", + "sdks/tts/README", + "sdks/videogeneration/README", "sdks/workspaces/README" ] } diff --git a/scripts/gen-docs-nav.sh b/scripts/gen-docs-nav.sh new file mode 100755 index 00000000..436b3dc2 --- /dev/null +++ b/scripts/gen-docs-nav.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash +# Regenerate the "API Reference" navigation group in docs/docs.json from the +# service pages Speakeasy emits under docs/sdks//README.mdx. +# +# Run this after `speakeasy run` so new API sections appear in the sidebar +# without hand-editing docs.json. Only the "API Reference" group's `pages` +# array is rewritten; every other part of docs.json is preserved untouched. +# Pages are listed alphabetically by tag. Idempotent: running with no doc +# changes leaves docs.json byte-identical. +# +# Requires: bash, jq. No network, no toolchain. +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$ROOT" + +DOCS_JSON="docs/docs.json" +GROUP="API Reference" + +if [[ ! -f "$DOCS_JSON" ]]; then + echo "missing $DOCS_JSON" >&2 + exit 1 +fi + +# Collect service page paths (docs.json paths are repo-doc-root-relative and +# carry no extension), sorted alphabetically by tag. +pages=() +while IFS= read -r readme; do + # docs/sdks//README.mdx -> sdks//README + rel="${readme#docs/}" + pages+=("${rel%.mdx}") +done < <(find docs/sdks -mindepth 2 -maxdepth 2 -name 'README.mdx' | sort) + +if ((${#pages[@]} == 0)); then + echo "no service pages found under docs/sdks/*/README.mdx" >&2 + exit 1 +fi + +# Build a JSON array of the page paths. +pages_json="$(printf '%s\n' "${pages[@]}" | jq -R . | jq -s .)" + +# Rewrite only the matching group's pages. Fail loudly if the group is absent +# so a renamed/missing group never silently produces an empty sidebar. +tmp="$(mktemp)" +jq --indent 2 \ + --arg group "$GROUP" \ + --argjson pages "$pages_json" ' + (.navigation.groups + | map(select(.group == $group)) + | length) as $matches + | if $matches == 0 then + error("group \"" + $group + "\" not found in navigation.groups") + else . end + | .navigation.groups |= map( + if .group == $group then .pages = $pages else . end + ) +' "$DOCS_JSON" >"$tmp" + +mv "$tmp" "$DOCS_JSON" +echo "updated $DOCS_JSON: ${#pages[@]} pages in \"$GROUP\""