diff --git a/.github/workflows/update-api-docs.yml b/.github/workflows/update-api-docs.yml new file mode 100644 index 000000000..1c8ab4dcb --- /dev/null +++ b/.github/workflows/update-api-docs.yml @@ -0,0 +1,101 @@ +name: Update API docs + +# Weekly (and on-demand) regeneration of the lynx-stack-derived API reference +# docs, opened as a draft PR for review. Runs entirely in lynx-website and does +# not touch the lynx-stack release pipeline or require cross-repo secrets. + +on: + schedule: + - cron: '0 18 * * 0' # Weekly, Sunday 18:00 UTC + workflow_dispatch: + +permissions: {} + +jobs: + update: + name: Regenerate API docs from lynx-stack + if: github.repository == 'lynx-family/lynx-website' + runs-on: ubuntu-latest + timeout-minutes: 40 + # Serialize runs — both schedule and workflow_dispatch write to the same + # bot/update-api-docs branch, so overlapping runs would race. + concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout lynx-website + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + # peter-evans/create-pull-request handles its own auth; don't leave + # GITHUB_TOKEN persisted in git config for later steps to reuse. + persist-credentials: false + + - name: Checkout lynx-stack + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + with: + repository: lynx-family/lynx-stack + ref: main + path: .lynx-stack + persist-credentials: false + + - name: Setup Rust + # lynx-stack's build graph compiles wasm crates (e.g. react-transform, + # web-core). Match lynx-stack's rust-toolchain.toml (it lives in + # .lynx-stack/, so it isn't auto-detected from the repo root here). + uses: actions-rust-lang/setup-rust-toolchain@1780873c7b576612439a134613cc4cc74ce5538c # v1 + with: + toolchain: '1.92.0' + target: wasm32-unknown-unknown,wasm32-wasip1 + cache: false + + - name: Setup PNPM + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5 + + - name: Setup Node.js + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6 + with: + # Satisfies both repos (lynx-stack engines: ^22 || ^24). + node-version: 24 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Regenerate API docs + run: bash scripts/update-api-docs.sh .lynx-stack + + - name: Validate build + id: build + continue-on-error: true + run: pnpm run build + + - name: Create Pull Request + uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7 + with: + branch: bot/update-api-docs + delete-branch: true + draft: true + add-paths: | + docs/en/api + docs/zh/api + commit-message: 'docs(api): sync API reference from lynx-stack main' + title: 'docs(api): sync API reference from lynx-stack main' + body: | + Automated weekly regeneration of the lynx-stack-derived API docs. + + **Build validation:** `${{ steps.build.outcome }}` (GITHUB_TOKEN PRs don't trigger CI, so the build is run inside this job). + + Covered: + - `rspeedy/*` — API Extractor + API Documenter, from lynx-stack `main`. + - `reactlynx-testing-library`, `lynx-testing-environment` — TypeDoc. + + **Reviewer checklist** + - [ ] Reconcile `docs/{en,zh}/api/_meta.json` sidebar nav if API members were added/removed (not automated). + - [ ] `docs/{en,zh}/api/react` is **not** auto-regenerated (bespoke: custom intro + projectDocuments whose sources don't ship). Update manually if its API changed. + - [ ] If **Build validation** above is `failure`, check the workflow run logs. + + Generated by `.github/workflows/update-api-docs.yml` / + `scripts/update-api-docs.sh`. diff --git a/.gitignore b/.gitignore index 2ab6aa3dd..258a4185c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ node_modules dist/ doc_build/ +# lynx-stack checkout used by the update-api-docs workflow +.lynx-stack/ + # IDE .vscode/* !.vscode/extensions.json diff --git a/scripts/update-api-docs.sh b/scripts/update-api-docs.sh new file mode 100755 index 000000000..0481bedc6 --- /dev/null +++ b/scripts/update-api-docs.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash +# +# Regenerate the lynx-stack-derived API reference docs in place, against a +# lynx-stack checkout. Covers two pipelines: +# +# 1. rspeedy/* – Microsoft API Extractor + API Documenter, run +# inside the lynx-stack `website/` workspace. +# 2. reactlynx-testing-library, lynx-testing-environment – TypeDoc, run here +# in lynx-website (`pnpm run typedoc`), reading the +# freshly built lynx-stack packages. +# +# NOT covered: docs/{en,zh}/api/react (bespoke: custom intro + projectDocuments +# whose sources don't ship) and docs/{en,zh}/api/_meta.json (hand-curated +# sidebar nav). Review the diff and reconcile nav when members are added/removed. +# +# Usage: scripts/update-api-docs.sh + +set -euo pipefail + +STACK_ARG="${1:?usage: scripts/update-api-docs.sh }" +STACK="$(cd "$STACK_ARG" && pwd)" +WEBSITE="$(cd "$(dirname "$0")/.." && pwd)" + +# rspeedy-related packages mirrored under docs/api/rspeedy, with the package +# directories that hold their api-extractor config. +RSPEEDY_PKG_DIRS=( + packages/rspeedy/core + packages/rspeedy/plugin-react + packages/rspeedy/plugin-external-bundle + packages/rspeedy/plugin-qrcode + packages/rspeedy/lynx-bundle-rslib-config + packages/webpack/externals-loading-webpack-plugin +) +BUILD_FILTERS=( + --filter @lynx-js/rspeedy + --filter @lynx-js/react-rsbuild-plugin + --filter @lynx-js/external-bundle-rsbuild-plugin + --filter @lynx-js/qrcode-rsbuild-plugin + --filter @lynx-js/lynx-bundle-rslib-config + --filter @lynx-js/externals-loading-webpack-plugin + # Needed for the TypeDoc packages below. + --filter @lynx-js/react + --filter @lynx-js/testing-environment +) + +echo "::group::Build lynx-stack packages" +pushd "$STACK" >/dev/null +corepack enable +corepack pnpm install --frozen-lockfile +corepack pnpm exec turbo run build "${BUILD_FILTERS[@]}" +popd >/dev/null +echo "::endgroup::" + +echo "::group::Generate rspeedy docs (API Extractor + API Documenter)" +pushd "$STACK" >/dev/null +rm -rf website/temp && mkdir -p website/temp +for dir in "${RSPEEDY_PKG_DIRS[@]}"; do + (cd "$dir" && corepack pnpm run api-extractor) +done +(cd website && rm -rf docs/en/api docs/zh/api && corepack pnpm run docs) +popd >/dev/null +echo "::endgroup::" + +echo "::group::Sync rspeedy docs into lynx-website (preserving custom index.md)" +for loc in en zh; do + gen="$STACK/website/docs/$loc/api" + web="$WEBSITE/docs/$loc/api/rspeedy" + # Drop docs whose API member no longer exists. + for f in "$web"/*.md; do + bn="$(basename "$f")" + [ "$bn" = "index.md" ] && continue + [ -f "$gen/$bn" ] || rm "$f" + done + # Copy current docs (index.md is the hand-written overview, leave it). + for f in "$gen"/*.md; do + bn="$(basename "$f")" + [ "$bn" = "index.md" ] && continue + cp "$f" "$web/$bn" + done +done +echo "::endgroup::" + +echo "::group::Overlay built packages into node_modules for TypeDoc" +# TypeDoc reads node_modules. Overlay the freshly built source so the docs +# reflect main — including the testing-library README the published +# @lynx-js/react omits, and @lynx-js/testing-environment (unpublished). +react_nm="$WEBSITE/node_modules/@lynx-js/react" +te_nm="$WEBSITE/node_modules/@lynx-js/testing-environment" +cp -R "$STACK/packages/react/types/." "$react_nm/types/" +cp -R "$STACK/packages/react/testing-library/." "$react_nm/testing-library/" +cp -R "$STACK/packages/testing-library/testing-environment/dist/." "$te_nm/dist/" +cp -f "$STACK/packages/testing-library/testing-environment/README.md" "$te_nm/README.md" +echo "::endgroup::" + +echo "::group::Generate TypeDoc docs" +cd "$WEBSITE" +pnpm run typedoc +echo "::endgroup::" + +echo "API docs regenerated. Review the diff and update docs/{en,zh}/api/_meta.json" +echo "if API members were added or removed."