Skip to content

fix(fern): make a 1.3.1 docs cut work — snapshot from the tag, address docs.yml by its real shape - #12582

Merged
dagil-nvidia merged 8 commits into
release/1.3.1from
dagil-nvidia/backport-11140-release-1.3.1
Aug 4, 2026
Merged

fix(fern): make a 1.3.1 docs cut work — snapshot from the tag, address docs.yml by its real shape#12582
dagil-nvidia merged 8 commits into
release/1.3.1from
dagil-nvidia/backport-11140-release-1.3.1

Conversation

@dagil-nvidia

@dagil-nvidia dagil-nvidia commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Backport of #11140 to release/1.3.1, adapted to this branch's layout.

#11140 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 release snapshot by copying pages-dev off docs-website:

cp -r fern/pages-dev "fern/pages-$TAG"     # content
cp fern/versions/dev.yml "$VERSION_FILE"   # navigation

pages-dev tracks main, which has since moved to the docs/fern/ tab structure. Tagging v1.3.1 today would publish current main documentation under a 1.3.1 labelpages-dev is blog cli community developer-guide kubernetes recipes reference use-cases, while pages-v1.3.0 is 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:

  • Added a Checkout source at tag step into source-checkout/ (second, since the docs-website checkout owns the workspace root)
  • Snapshot via rsync -a --exclude='digest' --exclude='index.yml' source-checkout/docs/, mirroring this branch's own dev sync
  • Version config built from the tag's index.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 it
  • Carried over fix(fern): build release snapshots from tagged commits #11140's faithfulness guard, which aborts when a snapshot file has no counterpart in the tagged source

Validation

Replayed the cut locally against this branch's docs/ and index.yml:

  • 233 navigation targets, 0 missing
  • Before the digest/ transform was added, 7 were missing — the replay caught it
  • Workflow YAML parses

release/1.4.0 branched 2026-07-29, after #11140, and is unaffected. Verified: it has the fix, has docs/fern/, and zero cp -r fern/pages-dev occurrences.


Open in Devin Review

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>
@dagil-nvidia
dagil-nvidia requested a review from a team as a code owner August 3, 2026 18:35

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

Open in Devin Review

Comment thread .github/workflows/fern-docs.yml Outdated
Comment on lines 475 to 477
# 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"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Aug 3, 2026
@dagil-nvidia dagil-nvidia changed the title fix(fern): build the 1.3.1 release snapshot from the tag fix(fern): make a 1.3.1 docs cut work — snapshot from the tag, address docs.yml by its real shape Aug 3, 2026
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

Scope grew: the snapshot fix alone was not enough for a working 1.3.1 cut.

Chasing the failing Preview or publish docs check turned up a second, independent blocker on this branch — and I was wrong when I first called it Fern version skew. It is a schema mismatch. The preview job saved .products[0] from docs-website and wrote it back, but docs-website dropped the product switcher for top-level versions:, so that read returns null and the job wrote products: [null] — then Fern rejected the file it had just created. Same for the release job, which addressed .products[0].versions and would have fabricated a product wrapper in the published config.

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 docs-website/fern/docs.yml: preview recovers all 16 version entries, release inserts v1.3.1 after dev for 17 total and creates no products key.

Same root cause as the snapshot bug — this branch predates a docs-infrastructure migration that never reached it.

@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/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>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/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>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/ok to test 2073941

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

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>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/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>
@dagil-nvidia

Copy link
Copy Markdown
Collaborator Author

/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>
@dagil-nvidia
dagil-nvidia merged commit 90a045f into release/1.3.1 Aug 4, 2026
80 of 99 checks passed
@dagil-nvidia
dagil-nvidia deleted the dagil-nvidia/backport-11140-release-1.3.1 branch August 4, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant