fix(fern): make a 1.3.1 docs cut work — snapshot from the tag, address docs.yml by its real shape - #12582
Conversation
Backport of #11140, adapted to this branch. That fix landed on main on 2026-07-02; release/1.3.1 branched on 2026-06-29 and never received it, so this branch still cuts a version by copying pages-dev off docs-website. pages-dev tracks main, which has since moved to the docs/fern/ tab structure, so tagging v1.3.1 today would publish main documentation under a 1.3.1 label. Both halves had it: the pages came from pages-dev and the navigation came from versions/dev.yml. The snapshot now comes from a checkout of the tag. #11140 cannot be cherry-picked as written because it reads docs/fern/pages/, which does not exist here, so the rsync mirrors this branch dev sync instead: docs/ with digest and index.yml excluded. The version config is built from the tag index.yml with the same two path transforms the dev sync applies, in the same order, since digest is a sibling of the pages tree rather than part of it. Also carries the faithfulness guard from #11140, which aborts when a snapshot file has no counterpart in the tagged source. That is the check that would have caught this. Validation: replayed the cut against this branch docs/ and index.yml. All 233 navigation targets resolve; before the digest transform was added, 7 did not. release/1.4.0 branched after #11140 and is unaffected. Signed-off-by: Dan Gil <dagil@nvidia.com>
| # Update the comment at the top | ||
| sed -i "s/# Navigation structure for Latest version/# Navigation structure for $TAG version/" "$VERSION_FILE" | ||
| sed -i "s|# Matching https://docs.nvidia.com/dynamo/latest/|# Snapshot from tag $TAG|" "$VERSION_FILE" |
There was a problem hiding this comment.
🔍 Header-comment rewrites in the version config no longer match anything
The two sed calls still target the strings # Navigation structure for Latest version and # Matching https://docs.nvidia.com/dynamo/latest/. The version file is now a copy of docs/index.yml, whose header reads # Navigation structure matching https://docs.nvidia.com/dynamo/dev/ (see docs/index.yml:16-17). Both substitutions are therefore no-ops and the generated fern/versions/vX.Y.Z.yml will keep a header claiming it is the dev navigation. (Note this was already effectively broken before the PR, since versions/dev.yml is itself a verbatim copy of index.yml per the dev sync at .github/workflows/fern-docs.yml:126-127.) Purely cosmetic, but if the intent was the Snapshot from tag $TAG marker, the patterns need updating to match the real header text.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Fixed in ada7bfa — you were right, both substitutions matched nothing. Replaced them with one sed against the header index.yml actually has (# Navigation structure matching https://docs.nvidia.com/dynamo/dev/, line 16), verified it matches on the real file and the result still parses as YAML.
The two sed calls still aimed at the header versions/dev.yml carried. Now that the version config is copied from the tag index.yml, neither string exists in the file and both substitutions matched nothing, so a generated versions/vX.Y.Z.yml kept a header claiming it was the dev navigation. One substitution against the header index.yml actually has, verified to match line 16 and leave the file parsing as YAML. Signed-off-by: Dan Gil <dagil@nvidia.com>
Two places assumed the product-switcher wrapper that docs-website has since dropped for top-level versioning. Same root as the snapshot bug: this branch predates a docs-infrastructure migration that never reached it. The preview job saved .products[0] from docs-website and wrote it back after copying the source config. Against the current site that read returns null, so it wrote products: [null] and Fern rejected the file it had just produced: "Incorrect type at path $.products[0]: expected object but received null". That is why previews fail on every PR into this branch. It now reads the version list from either shape, refuses to continue when neither yields one, and restores into products[0].versions because this branch source config still carries the wrapper. The release job edits docs-website docs.yml directly and addressed .products[0].versions, which would have read null and then fabricated a product wrapper in the published config. It now uses .versions, matching both the file and what main does, and fails loudly when no dev entry is found instead of doing arithmetic on null. Validation: replayed both paths against the real docs-website docs.yml. The preview path recovers all 16 version entries where the old code produced null. The release path inserts v1.3.1 after dev for 17 total, repoints Latest, and creates no products key. Signed-off-by: Dan Gil <dagil@nvidia.com>
|
Scope grew: the snapshot fix alone was not enough for a working 1.3.1 cut. Chasing the failing Both now read and write the shape the file actually uses, with guards that fail loudly instead of operating on null. Replayed against the real Same root cause as the snapshot bug — this branch predates a docs-infrastructure migration that never reached it. |
|
/ok to test c87e3f8 |
Restoring only the version list left the source path in place, and that path is ../docs/index.yml, which describes the source repo rather than docs-website. Fern then failed with ENOENT on docs-checkout/docs/index.yml. The previous code avoided this by restoring the whole products[0] block, including docs-website own path. Derive the path from the Latest entry of the preserved list instead, so it stays correct as releases move. Validation: replayed against the real docs-website docs.yml. The product path resolves to ./versions/v1.3.0.yml, matching the Latest entry, and no ../docs/ path survives anywhere in the block. Signed-off-by: Dan Gil <dagil@nvidia.com>
|
/ok to test c0443ab |
The sync replaced fern/digest wholesale. The digest posts were renamed .md to .mdx at the source after this branch was cut, so the copy brought .md files while every released versions/v*.yml on docs-website points at .mdx. Fern then failed on the first digest page it could not open, and the same delete would have 404d those pages across every published version, not just this preview. Merge into the directory instead of replacing it, which is what main does. Released .mdx posts survive and this branch .md posts land beside them. Validation: replayed the sync against the real trees. Before, the two agentic-inference .mdx posts were gone. After, both resolve and the .md pair sits alongside. Signed-off-by: Dan Gil <dagil@nvidia.com>
|
/ok to test 2073941 |
The release job committed and pushed to docs-website and only then installed Fern and published, so a broken cut reached the branch before anything checked it. Every failure on this branch so far has been a composed tree that looks fine until Fern reads it, which is the worst case for that ordering. Port the gate from main and run it first. Every versioned navigation target must resolve or the cut aborts. Digest targets only warn, since the shared Digest syncs independently from main and a frozen nav can drift there without this release being wrong. Then fern check. Node and the Fern CLI move ahead of the gate because it needs them. Validation: replayed the gate against a simulated v1.3.1 cut. It passes a good tree with zero errors, and removing one page from the snapshot makes it report that page and abort. Signed-off-by: Dan Gil <dagil@nvidia.com>
|
/ok to test 736e1f0 |
docs-website carries fern/translations/zh-CN/pages-v1.3.0, but nothing in this branch workflow builds one, so v1.3.1 would have published with no Chinese mirror while v1.3.0 has one. Main step does not port directly. It walks a translations/<lang>/pages tree, and this branch keeps translations as .zh-CN siblings of the English page instead. The mirror is those files with the .zh-CN infix stripped, which is what pairs each one with its English page under fern/pages-$TAG. Snapshot from the tagged source rather than the docs-website dev mirror, for the reason main gives: dev links are already rewritten to dev URLs and copying them would pin a released translation to dev. Skips cleanly when a tag carries no translations. Validation: replayed against the tagged source. 13 files, and the resulting layout matches the real pages-v1.3.0 mirror exactly. Signed-off-by: Dan Gil <dagil@nvidia.com>
|
/ok to test 16fe51c |
The commit step added pages-$TAG, versions/$TAG.yml and docs.yml, so the zh-CN mirror the previous commit builds would have been written and then left untracked. The cut would have looked clean and published without it. Same staging loop main uses. The glob stays literal under bash when no translations exist, so the directory test is a no-op for tags that carry none. Validation: the glob matches the 13-file zh-CN mirror the snapshot step produces, and no-ops when the tree is absent. Signed-off-by: Dan Gil <dagil@nvidia.com>
Summary
Backport of #11140 to
release/1.3.1, adapted to this branch's layout.#11140 landed on
mainon 2026-07-02.release/1.3.1branched on 2026-06-29 and never received it, so this branch still cuts a release snapshot by copyingpages-devoffdocs-website:pages-devtracksmain, which has since moved to thedocs/fern/tab structure. Taggingv1.3.1today would publish currentmaindocumentation under a 1.3.1 label —pages-devisblog cli community developer-guide kubernetes recipes reference use-cases, whilepages-v1.3.0is the pre-restructure flat tree.A tag push runs the workflow from the tag's own ref, so
main's fixed job never applies to a cut off this branch.Approach
#11140 cannot be cherry-picked as written — it reads
docs/fern/pages/, which does not exist here. Instead:Checkout source at tagstep intosource-checkout/(second, since thedocs-websitecheckout owns the workspace root)rsync -a --exclude='digest' --exclude='index.yml' source-checkout/docs/, mirroring this branch's own dev syncindex.yml, with the same two path transforms the dev sync applies, in the same order —digest/first, because it is a sibling of the pages tree rather than part of itValidation
Replayed the cut locally against this branch's
docs/andindex.yml:digest/transform was added, 7 were missing — the replay caught itrelease/1.4.0branched 2026-07-29, after #11140, and is unaffected. Verified: it has the fix, hasdocs/fern/, and zerocp -r fern/pages-devoccurrences.