From aa212f9c93701d4e5a866a0add43292efc8ad911 Mon Sep 17 00:00:00 2001 From: Caio Pizzol <97641911+caio-pizzol@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:55:49 -0300 Subject: [PATCH 1/8] docs(intro): tighten installation card copy (#2991) * docs(intro): tighten installation card copy * chore: retrigger docs preview workflow --- apps/docs/getting-started/introduction.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/getting-started/introduction.mdx b/apps/docs/getting-started/introduction.mdx index a7bd32e415..b00afe7777 100644 --- a/apps/docs/getting-started/introduction.mdx +++ b/apps/docs/getting-started/introduction.mdx @@ -28,7 +28,7 @@ SuperDoc renders and edits DOCX files directly in the browser. Built on OOXML icon="download" href="/getting-started/installation" > - Get started in minutes + Get started in seconds Date: Wed, 29 Apr 2026 08:07:37 -0300 Subject: [PATCH 2/8] docs(intro): broaden AI Agents card to agent workflows (#2993) --- apps/docs/getting-started/introduction.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/docs/getting-started/introduction.mdx b/apps/docs/getting-started/introduction.mdx index b00afe7777..ce05d258fb 100644 --- a/apps/docs/getting-started/introduction.mdx +++ b/apps/docs/getting-started/introduction.mdx @@ -35,7 +35,7 @@ SuperDoc renders and edits DOCX files directly in the browser. Built on OOXML icon="sparkles" href="/getting-started/ai-agents" > - Headless mode and LLM workflows + Headless mode and agent workflows Date: Wed, 29 Apr 2026 07:28:40 -0300 Subject: [PATCH 3/8] ci(release): gate production docs on stable release success (#2989) * ci(release): gate production docs on stable release success Mintlify currently deploys from main, so docs ship as soon as a doc commit lands, often weeks before the underlying packages reach npm via the weekly stable release. Move production docs onto a `docs-stable` branch that the release workflow only advances after every publish step succeeds, so docs and packages move together. - release-stable.yml pushes stable -> docs-stable as its final step, only reachable on full success - new preview-stable-docs.yml triggers a Mintlify preview for any PR targeting stable so the promote-stable PR shows reviewers the exact docs that will go live - requires manual setup before this can take effect: create the docs-stable branch from current stable, switch Mintlify's deployment branch in the dashboard, and add MINTLIFY_API_KEY / MINTLIFY_PROJECT_ID repo secrets (preview workflow no-ops without them) * fix(release): gate docs-stable promote on verified release SHA Address review on PR 2989. Two issues: - The promote step refetched `origin/stable` and pushed it, so a newer commit landing on stable while the release was still publishing would be promoted to docs-stable before the next run actually published it. The orchestrator now emits `promote_sha` (current HEAD) only when no package failed and no deferral happened; the workflow gates the push on that output and pushes the explicit SHA instead of refetching. - The preview workflow called `gh pr comment` without checking out the repo, so gh had no repo context. Added `--repo "$GITHUB_REPOSITORY"`. --- .github/workflows/preview-stable-docs.yml | 56 +++++++++++++++++++++++ .github/workflows/release-stable.yml | 13 ++++++ scripts/release-local-stable.mjs | 8 ++++ 3 files changed, 77 insertions(+) create mode 100644 .github/workflows/preview-stable-docs.yml diff --git a/.github/workflows/preview-stable-docs.yml b/.github/workflows/preview-stable-docs.yml new file mode 100644 index 0000000000..f52f8041b6 --- /dev/null +++ b/.github/workflows/preview-stable-docs.yml @@ -0,0 +1,56 @@ +# Triggers a Mintlify preview deployment for any PR targeting `stable`. +# Promote-stable PRs target this branch, so reviewers see the docs that will +# go live the moment the release succeeds. +name: 👀 Preview docs for stable PRs + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: + - stable + +permissions: + pull-requests: write + +concurrency: + group: preview-stable-docs-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + trigger-preview: + runs-on: ubuntu-latest + steps: + - name: Trigger Mintlify preview + id: preview + env: + MINTLIFY_API_KEY: ${{ secrets.MINTLIFY_API_KEY }} + MINTLIFY_PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} + BRANCH: ${{ github.head_ref }} + run: | + set -euo pipefail + if [ -z "${MINTLIFY_API_KEY}" ] || [ -z "${MINTLIFY_PROJECT_ID}" ]; then + echo "MINTLIFY_API_KEY or MINTLIFY_PROJECT_ID not set; skipping." + echo "preview_url=" >> "$GITHUB_OUTPUT" + exit 0 + fi + + response=$(curl -sS -X POST \ + -H "Authorization: Bearer ${MINTLIFY_API_KEY}" \ + -H "Content-Type: application/json" \ + -d "{\"branch\": \"${BRANCH}\"}" \ + "https://api.mintlify.com/v1/project/preview/${MINTLIFY_PROJECT_ID}") + + echo "Mintlify response: ${response}" + preview_url=$(echo "${response}" | jq -r '.previewUrl // empty') + echo "preview_url=${preview_url}" >> "$GITHUB_OUTPUT" + + # Comment only on first open. Mintlify reuses the same URL for the same + # branch on redeploys, so subsequent pushes refresh content in place. + - name: Comment preview URL on PR + if: steps.preview.outputs.preview_url != '' && github.event.action == 'opened' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} + PREVIEW_URL: ${{ steps.preview.outputs.preview_url }} + run: | + gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body "📖 Docs preview: ${PREVIEW_URL}" diff --git a/.github/workflows/release-stable.yml b/.github/workflows/release-stable.yml index 08611c6a1a..15a9c56422 100644 --- a/.github/workflows/release-stable.yml +++ b/.github/workflows/release-stable.yml @@ -171,3 +171,16 @@ jobs: with: packages-dir: packages/sdk/langs/python/dist/ skip-existing: true + + # Stable docs deploy from `docs-stable`. The orchestrator emits + # `promote_sha` only when the run released (or no-op'd) on the SHA it + # checked out; it stays empty on failure or deferral, so production docs + # never advance past a commit whose packages were not actually published. + - name: Promote stable docs + if: steps.stable_release.outputs.promote_sha != '' + env: + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + PROMOTE_SHA: ${{ steps.stable_release.outputs.promote_sha }} + run: | + set -euo pipefail + git push origin "${PROMOTE_SHA}:refs/heads/docs-stable" diff --git a/scripts/release-local-stable.mjs b/scripts/release-local-stable.mjs index b4fe84ca04..b1e4697b39 100644 --- a/scripts/release-local-stable.mjs +++ b/scripts/release-local-stable.mjs @@ -696,6 +696,7 @@ for (const arg of process.argv.slice(2)) { setStepOutput('sdk_python_snapshot_tag', ''); setStepOutput('sdk_python_snapshot_companion_dir', ''); setStepOutput('sdk_python_snapshot_main_dir', ''); +setStepOutput('promote_sha', ''); // --------------------------------------------------------------------------- // Branch guard @@ -923,6 +924,13 @@ if (deferredReason && !hasFailed) { console.log('\nCurrent run stopped before publishing from a stale checkout. The next queued stable run should continue from the latest branch head.'); } +// Emit the SHA the docs-stable promotion step should publish. Stays empty when +// the run failed or was deferred, so production docs never advance past a +// commit whose packages are not actually published. +if (!hasFailed && !deferredReason) { + setStepOutput('promote_sha', getCurrentHead()); +} + // Remind operator about @semantic-release/git behavior on stable const anyReleased = [...results.values()].some((r) => r.status === 'released'); if (anyReleased && !isDryRun) { From 14642bc053f67583835974eb3f67885f0fb98f7a Mon Sep 17 00:00:00 2001 From: Caio Pizzol <97641911+caio-pizzol@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:51:46 -0300 Subject: [PATCH 4/8] ci(docs): trigger preview workflow on docs PRs to main (#2992) Doc authors who PR against main currently get no hosted preview because Mintlify's automatic previews only fire on PRs targeting the deployment branch (docs-stable) and our preview workflow only fired on PRs targeting stable. They'd only see a preview when their work reached the promote-stable PR, days later. Add main as a trigger branch so doc-touching PRs to main get an instant preview URL. Path filter on apps/docs, document-api contract, and the generator script keeps the 5 req/min Mintlify API quota from being spent on unrelated code PRs. The path filter also applies to stable PRs but that's fine: promote-stable PRs always include docs, and code-only stable hotfixes don't need a docs preview. --- .github/workflows/preview-stable-docs.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/preview-stable-docs.yml b/.github/workflows/preview-stable-docs.yml index f52f8041b6..a5d11dffd8 100644 --- a/.github/workflows/preview-stable-docs.yml +++ b/.github/workflows/preview-stable-docs.yml @@ -1,13 +1,22 @@ -# Triggers a Mintlify preview deployment for any PR targeting `stable`. -# Promote-stable PRs target this branch, so reviewers see the docs that will -# go live the moment the release succeeds. -name: 👀 Preview docs for stable PRs +# Triggers a Mintlify preview deployment for docs-touching PRs targeting +# `main` or `stable`. The `stable` case covers promote-stable PRs so reviewers +# see the docs that will go live the moment the release succeeds. The `main` +# case gives doc authors a hosted preview during normal development, since +# Mintlify's automatic previews only fire on PRs targeting the deployment +# branch (`docs-stable`). Path filter keeps the 5 req/min Mintlify API quota +# from being spent on unrelated code PRs. +name: 👀 Preview docs for main and stable PRs on: pull_request: types: [opened, reopened, synchronize] branches: + - main - stable + paths: + - 'apps/docs/**' + - 'packages/document-api/src/contract/**' + - 'scripts/generate-all.mjs' permissions: pull-requests: write From 779dd60e091d18156e43c1b874b159ee28c572a5 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 29 Apr 2026 07:54:34 -0300 Subject: [PATCH 5/8] ci(docs): always post preview URL once per PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous gate `action == 'opened'` skipped the comment whenever the workflow first ran on a `synchronize` event, which happens whenever the workflow file didn't exist on the base branch when the PR was opened (or on reopens). Replace it with an idempotency check that lists existing PR comments and only posts if none starts with the `📖 Docs preview:` marker. --- .github/workflows/preview-stable-docs.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/workflows/preview-stable-docs.yml b/.github/workflows/preview-stable-docs.yml index a5d11dffd8..df5ec49ce0 100644 --- a/.github/workflows/preview-stable-docs.yml +++ b/.github/workflows/preview-stable-docs.yml @@ -53,13 +53,24 @@ jobs: preview_url=$(echo "${response}" | jq -r '.previewUrl // empty') echo "preview_url=${preview_url}" >> "$GITHUB_OUTPUT" - # Comment only on first open. Mintlify reuses the same URL for the same - # branch on redeploys, so subsequent pushes refresh content in place. + # Comment once per PR. Mintlify reuses the same URL for the same branch + # on redeploys, so subsequent pushes refresh content in place at the same + # URL. We can't gate on `action == 'opened'` because the workflow may + # first run on a `synchronize` event (e.g., when this workflow file + # didn't exist on the base branch when the PR was opened), so we check + # for an existing preview comment instead. - name: Comment preview URL on PR - if: steps.preview.outputs.preview_url != '' && github.event.action == 'opened' + if: steps.preview.outputs.preview_url != '' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number }} PREVIEW_URL: ${{ steps.preview.outputs.preview_url }} run: | + set -euo pipefail + existing=$(gh pr view "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --json comments \ + --jq '[.comments[] | select(.body | startswith("📖 Docs preview:"))] | length') + if [ "$existing" -gt 0 ]; then + echo "Preview comment already exists; skipping." + exit 0 + fi gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body "📖 Docs preview: ${PREVIEW_URL}" From 4f4c417842593f7b5e8df0e853962bc1d6d0a6d4 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 29 Apr 2026 08:12:41 -0300 Subject: [PATCH 6/8] ci(docs): refresh main docs preview on push Add a workflow that fires on docs-touching pushes to main and re-triggers Mintlify's preview for the main branch. Gives the team a persistent superdoc-main.mintlify.app URL that always reflects the current state of main, without anyone needing to open a draft PR. Production docs continue to come from docs-stable so this is purely additive. --- .../workflows/refresh-main-docs-preview.yml | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .github/workflows/refresh-main-docs-preview.yml diff --git a/.github/workflows/refresh-main-docs-preview.yml b/.github/workflows/refresh-main-docs-preview.yml new file mode 100644 index 0000000000..d1527048a3 --- /dev/null +++ b/.github/workflows/refresh-main-docs-preview.yml @@ -0,0 +1,54 @@ +# Refreshes the persistent Mintlify preview for `main` so the team can see the +# current "next" state of the docs at superdoc-main.mintlify.app without +# opening a draft PR. Mintlify reuses the URL per branch, so each push +# refreshes content in place. Production docs stay on docs-stable; this is +# unrelated to the production gate. +name: 👀 Refresh main docs preview + +on: + push: + branches: + - main + paths: + - 'apps/docs/**' + - 'packages/document-api/src/contract/**' + - 'scripts/generate-all.mjs' + +permissions: + contents: read + +concurrency: + group: refresh-main-docs-preview + cancel-in-progress: true + +jobs: + trigger-preview: + runs-on: ubuntu-latest + steps: + - name: Trigger Mintlify preview for main + env: + MINTLIFY_API_KEY: ${{ secrets.MINTLIFY_API_KEY }} + MINTLIFY_PROJECT_ID: ${{ secrets.MINTLIFY_PROJECT_ID }} + run: | + set -euo pipefail + if [ -z "${MINTLIFY_API_KEY}" ] || [ -z "${MINTLIFY_PROJECT_ID}" ]; then + echo "MINTLIFY_API_KEY or MINTLIFY_PROJECT_ID not set; skipping." + exit 0 + fi + + response=$(curl -sS -X POST \ + -H "Authorization: Bearer ${MINTLIFY_API_KEY}" \ + -H "Content-Type: application/json" \ + -d '{"branch": "main"}' \ + "https://api.mintlify.com/v1/project/preview/${MINTLIFY_PROJECT_ID}") + + echo "Mintlify response: ${response}" + preview_url=$(echo "${response}" | jq -r '.previewUrl // empty') + + if [ -n "$preview_url" ]; then + { + echo "## Next docs preview refreshed" + echo + echo "URL: $preview_url" + } >> "$GITHUB_STEP_SUMMARY" + fi From 86d3d9eba646958cd2d105a4d7aec54fce79e592 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 29 Apr 2026 08:13:05 -0300 Subject: [PATCH 7/8] ci(docs): allow manual workflow_dispatch on main docs preview --- .github/workflows/refresh-main-docs-preview.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/refresh-main-docs-preview.yml b/.github/workflows/refresh-main-docs-preview.yml index d1527048a3..16209f462b 100644 --- a/.github/workflows/refresh-main-docs-preview.yml +++ b/.github/workflows/refresh-main-docs-preview.yml @@ -13,6 +13,7 @@ on: - 'apps/docs/**' - 'packages/document-api/src/contract/**' - 'scripts/generate-all.mjs' + workflow_dispatch: permissions: contents: read From f976c4decf00750556b03ac6fe12866a1b6147dc Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 29 Apr 2026 08:22:40 -0300 Subject: [PATCH 8/8] ci(docs): rename docs preview workflows for clarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename `preview-stable-docs.yml` to `docs-preview-pr.yml` (the file covered both main and stable PRs since #2992, so the old name was misleading) and `refresh-main-docs-preview.yml` to `docs-preview-main.yml`. Both now share the `docs-preview-` prefix so they sort together in the Actions UI, with display names "📖 Docs preview (PR)" and "📖 Docs preview (main)". Production promotion stays as a step inside release-stable.yml since it's gated on the orchestrator's `promote_sha` output and benefits from sharing a job with the release steps. --- .../{refresh-main-docs-preview.yml => docs-preview-main.yml} | 2 +- .../workflows/{preview-stable-docs.yml => docs-preview-pr.yml} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename .github/workflows/{refresh-main-docs-preview.yml => docs-preview-main.yml} (97%) rename .github/workflows/{preview-stable-docs.yml => docs-preview-pr.yml} (98%) diff --git a/.github/workflows/refresh-main-docs-preview.yml b/.github/workflows/docs-preview-main.yml similarity index 97% rename from .github/workflows/refresh-main-docs-preview.yml rename to .github/workflows/docs-preview-main.yml index 16209f462b..7a2bdfa793 100644 --- a/.github/workflows/refresh-main-docs-preview.yml +++ b/.github/workflows/docs-preview-main.yml @@ -3,7 +3,7 @@ # opening a draft PR. Mintlify reuses the URL per branch, so each push # refreshes content in place. Production docs stay on docs-stable; this is # unrelated to the production gate. -name: 👀 Refresh main docs preview +name: 📖 Docs preview (main) on: push: diff --git a/.github/workflows/preview-stable-docs.yml b/.github/workflows/docs-preview-pr.yml similarity index 98% rename from .github/workflows/preview-stable-docs.yml rename to .github/workflows/docs-preview-pr.yml index df5ec49ce0..572b8bc77d 100644 --- a/.github/workflows/preview-stable-docs.yml +++ b/.github/workflows/docs-preview-pr.yml @@ -5,7 +5,7 @@ # Mintlify's automatic previews only fire on PRs targeting the deployment # branch (`docs-stable`). Path filter keeps the 5 req/min Mintlify API quota # from being spent on unrelated code PRs. -name: 👀 Preview docs for main and stable PRs +name: 📖 Docs preview (PR) on: pull_request: