Repository navigation
fix(docs): sanitize emoji shortcodes in generated SDK docs - #780
Conversation
Original prompt from jason.schrader
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Closing in favor of coordination with our vendor |
3173df0 to
08655a5
Compare
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
There was a problem hiding this comment.
Perry's Review
Verdict: 💬 Comments / questions — the review is LGTM (both prior findings verified fixed; probe-tested, idempotent, CI green). Posted as a comment rather than an approval because the maintainer GitHub App on OpenRouterTeam currently lacks pull_requests:write, so the approval gate cannot carry the maintainer identity. A maintainer should re-approve once the permission is granted.
Risk: 🟢 Low
Findings, verification & risk assessment
Third-round review on ca54649. Both prior findings are verified fixed in the working tree, the sanitize script is correct and idempotent, and CI is green (gen-docs-nav SUCCESS, validate / validate SUCCESS).
Prior findings — resolved
- Concurrent workflow push race —
docs-nav.yamlandspeakeasy_run_on_pr.yamlnow shareconcurrency: generated-files-${{ github.event.pull_request.number || github.ref }}withcancel-in-progress: false, so the two auto-committing workflows serialize instead of racing non-fast-forward pushes to the PR head branch. workflow_dispatchcould auto-commit straight tomain— fixed inca54649: the auto-commit step is now gated withif: github.event_name == 'pull_request', so a manual dispatch runs sanitize + nav regeneration but never pushes tomain.
What was verified this round
- Sanitize script (
scripts/sanitize-docs-emoji.sh):set -euo pipefail, repo-root resolution viaBASH_SOURCE,docs/existence check, scoped todocs/**/*.mdxonly. Re-run against the branch's docs tree produces zero diff (idempotent).perlis preinstalled on GitHub-hosted runners. - Residual guard:
grep -HnP '(?<![\w:]):[a-z][a-z0-9_+-]*:(?![\w:])'with|| truesoset -edoesn't abort on grep's no-match exit,[[ -n "$matches" ]]gating the error path, actionable stderr,exit 1. Probe-tested: an injected unmapped:sparkles:shortcode correctly fails the script; a URN-only line (urn:ietf:params:oauth:token-type:jwt) correctly passes — the lookbehind/lookahead fixed the false positive the earlier:params:match would have produced. - Sanitize ordering in
speakeasy_run_on_pr.yamlis correct: afterspeakeasy run, beforegen-docs-nav.sh. - README.md diff in this PR (the
byok.list()→batch.list()example change) is part of the already-merged Speakeasy regeneration commits on the branch, not authored logic — those commits are ancestors ofmain.
Delta scope
The four PR-author commits (all Devin AI) are: the original sanitize pass, the URN-guard regex fix, the docs rewrite applying the replacements, and the dispatch auto-commit gate. The large src/ and tests/ churn in the file list belongs to the regenerated-spec commits already on main and is not part of this review's delta.
Estimated impact: worst case is a false-positive failure of the residual guard on a future generated-docs pattern that looks like a :word: shortcode — a one-line mapping or content fix in the docs generation workflow, with no runtime, data, or security surface affected.
Risk assessment & full factor table
| Dimension | Severity | Risk | Reasoning |
|---|---|---|---|
| Implementation risk | 🟩 | Low | Script and workflow wiring are correct, idempotent, and probe-tested in review. |
| Premise risk | 🟩 | Low | Post-generation sanitization is the right fix given Speakeasy rewrites the MDX on every run. |
| Estimated impact | 🟩 | Low | Worst case is a contained CI failure in the docs pipeline, trivially correctable. |
| Risk Factor | Severity | Risk | Reasoning |
|---|---|---|---|
| Reversibility | 🟩 | Low | Revert restores the prior state; regeneration recreates output. |
| Detectability | 🟩 | Low | The residual guard fails CI on any unmapped shortcode immediately. |
| Blast radius | 🟩 | Low | Confined to the docs subtree mounted into the docs site. |
| Data integrity | None | No persisted state is touched. | |
| Financial exposure | None | No billing surface. | |
| Security and privacy exposure | None | No credential or auth path changed. | |
| Propagation | 🟩 | Low | Only the docs rendering pipeline consumes the output. |
| Availability | None | No serving path affected. | |
| Recovery cost | 🟩 | Low | A revert or one-line mapping fixes any issue. |
| Time to correct | 🟩 | Low | Guard failures surface in the same workflow run. |
…docs-emoji-shortcodes # Conflicts: # docs/models/operations/createkeysdata.mdx # docs/models/operations/createkeysresponse.mdx # docs/models/operations/getkeydata.mdx # docs/models/operations/getkeyresponse.mdx # docs/models/operations/listdata.mdx # docs/models/operations/updatekeysdata.mdx # docs/models/operations/updatekeysresponse.mdx
jason-schrader-openrouter
left a comment
There was a problem hiding this comment.
LGTM, that changelog size though 👀
all for emojis! 😆 🎉 🫶 💪 🥇
Summary
The Parameters tables on
openrouter.ai/docs/client-sdks/typescript/**render:heavy_check_mark:as literal text. Speakeasy emits GitHub-flavored emoji shortcodes; GitHub expands them, Mintlify does not, and the docs site mounts this repo'sdocs/tree directly through asourceRefentry in openrouter-web'sprojects/docs/docs.json.Editing the generated MDX alone would not hold, because the next
speakeasy runrewrites it. So this PR pairs a one-time pass with a post-generation step:scripts/sanitize-docs-emoji.shrewritesdocs/**/*.mdxin place:Scoped to
docs/only. RootREADME.mdand the workflow YAML keep their shortcodes, which render correctly on GitHub and npm.The script runs immediately after
speakeasy runand beforegen-docs-nav.shinspeakeasy_run_on_pr.yaml, so spec-change PRs land sanitized.A new
docs-nav.yamlmirrors the workflow python-sdk and go-sdk already have. This repo had nopull_request-triggered docs job, so the scheduled generation path insdk_generation.yamlopens PRs that neither sanitize emoji nor regenerate navigation. The new workflow covers both on that path.docs-nav.yamlandspeakeasy_run_on_pr.yamlshare one concurrency group keyed on the PR number, withcancel-in-progress: false. Both end withint128/update-generated-files-action@v2pushing to the PR head branch, and a Speakeasy regeneration PR touches both.speakeasy/in.openapi.yamlanddocs/**, so without serialization the second push would be rejected as non-fast-forward.The one-time pass: 1,428 files, 6,933 shortcodes replaced (rebased onto
mainon 2026-10-03).scripts/sanitize-docs-emoji.shends with a residual guard: if any standalone:[a-z][a-z0-9_+-]*:token (not preceded or followed by a word character or:) survives the substitution, it prints the file and line and exits non-zero, so a new shortcode Speakeasy starts emitting fails at generation time instead of shipping as literal text. Zero matches remain today, so the guard passes on current output.Verification
docs/; the six:warning:occurrences in workflow YAML are untouched.Durability, now confirmed
Speakeasy regeneration PR #784 landed on
mainwhile this PR was open. It ranPR Validation, a plainpull_requestworkflow, which establishes thatpull_requestworkflows do fire on the bot-authored regeneration PRs, so the sanitize step will run on future generations.auto-merge-speakeasy-pr.yamlwaits for checks to complete before merging, so the sanitize commit has a window to land, but the poll can observe a momentarily-empty pending set between commits. That race predates this change and applies equally togen-docs-nav.sh.Rebase (2026-10-03)
Reopened after Pylon #4403 reported the same bug from a customer. The vendor's suggested script only rewrites
descriptionfields in OpenAPI files, and the spec has no shortcodes in it, so it doesn't fix this. The shortcodes come from Speakeasy's docs templates.Rebuilt on current
main: same.githubandscriptschanges, then the one-time pass was re-run fresh instead of replaying the old generated-docs commits.The residual guard now ignores URN-style colon runs. New OAuth docs on
maincontainurn:ietf:params:oauth:token-type:jwt, which the old pattern flagged as:params:etc.:Link to Devin session: https://openrouter.devinenterprise.com/sessions/1589ee9058c442958d427eac4e989f11
Open in Devin Desktop: https://openrouter.devinenterprise.com/desktop/session/1589ee9058c442958d427eac4e989f11?variant=devin