Skip to content

Commit 5a953d7

Browse files
lbliiiclaude
andcommitted
ci(fern): install Fern docs CI workflows + basepath-aware for subpath site
Adds the bundled Fern CI suite from the convert-to-fern toolkit and the `experimental.basepath-aware: true` flag required for subpath-hosted sites (docs.nvidia.com/nemo/automodel). - fern-docs-ci.yml — `fern check` on PRs. Trigger uses the FW-CI mirror bot pattern (`push: branches: pull-request/[0-9]+`) — same as build-docs.yml — so DOCS_FERN_TOKEN is available even for fork PRs. This is the fix landed in NVIDIA-NeMo/Gym#1241. - fern-docs-preview-build.yml + fern-docs-preview-comment.yml — two-workflow split: build collects PR sources without secrets (safe for forks), comment workflow is triggered via workflow_run with the trusted base context, builds the preview, and posts a herb-emoji PR comment. - publish-fern-docs.yml — publishes to docs.nvidia.com/nemo/automodel on push to main with fern/** changes or via workflow_dispatch. Required org secret: DOCS_FERN_TOKEN (already present for build-docs.yml). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> Signed-off-by: Lawrence Lane <llane@nvidia.com>
1 parent 0b3751e commit 5a953d7

5 files changed

Lines changed: 320 additions & 0 deletions

File tree

.github/workflows/fern-docs-ci.yml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Validates Fern docs configuration on pull requests.
17+
18+
name: Fern docs (check)
19+
20+
# Triggers on push to mirrored PR branches (`pull-request/<n>`) created by the
21+
# FW-CI mirror bot — same pattern as build-docs.yml. This runs in the trusted
22+
# base-repo context, so DOCS_FERN_TOKEN is available even for fork PRs.
23+
on:
24+
push:
25+
branches:
26+
- "pull-request/[0-9]+"
27+
paths:
28+
- 'fern/**'
29+
- '.github/workflows/fern-docs-ci.yml'
30+
31+
permissions:
32+
contents: read
33+
34+
jobs:
35+
check:
36+
runs-on: ubuntu-latest
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v6
40+
41+
- name: Setup Node.js
42+
uses: actions/setup-node@v6
43+
with:
44+
node-version: '20'
45+
46+
- name: Install Fern CLI
47+
run: npm install -g fern-api
48+
49+
- name: Validate Fern configuration
50+
working-directory: ./fern
51+
run: fern check
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Workflow 1 of 2 for Fern doc previews.
17+
#
18+
# Collects the fern/ sources and PR metadata from the (possibly untrusted) PR
19+
# branch and uploads them as an artifact. No secrets are used here, so this is
20+
# safe to run on fork PRs via the regular pull_request trigger.
21+
#
22+
# The companion workflow (fern-docs-preview-comment.yml) picks up the artifact,
23+
# builds the preview with DOCS_FERN_TOKEN, and posts the PR comment.
24+
25+
name: "Preview Fern Docs: Build"
26+
27+
on:
28+
pull_request:
29+
paths:
30+
- 'fern/**'
31+
- '.github/workflows/fern-docs-preview-build.yml'
32+
33+
permissions:
34+
contents: read
35+
36+
jobs:
37+
collect:
38+
runs-on: ubuntu-latest
39+
steps:
40+
- name: Checkout PR
41+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
42+
with:
43+
fetch-depth: 0
44+
45+
- name: Save PR metadata
46+
env:
47+
PR_NUMBER: ${{ github.event.pull_request.number }}
48+
HEAD_REF: ${{ github.head_ref }}
49+
BASE_REF: ${{ github.base_ref }}
50+
run: |
51+
mkdir -p preview-metadata
52+
echo "$PR_NUMBER" > preview-metadata/pr_number
53+
echo "$HEAD_REF" > preview-metadata/head_ref
54+
git diff --name-only "origin/${BASE_REF}...HEAD" -- '*.mdx' > preview-metadata/changed_mdx_files 2>/dev/null || true
55+
56+
- name: Upload fern sources and metadata
57+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
58+
with:
59+
name: fern-preview
60+
path: |
61+
fern/
62+
preview-metadata/
63+
retention-days: 1
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Workflow 2 of 2 for Fern doc previews.
17+
#
18+
# Triggered by workflow_run after "Preview Fern Docs: Build" completes.
19+
# Downloads the fern/ artifact, builds a preview with DOCS_FERN_TOKEN, and
20+
# posts a stable :herb: comment on the PR. This workflow never checks out the
21+
# PR branch directly, keeping secrets isolated from untrusted code.
22+
#
23+
# Required configuration:
24+
# - Organization secret: DOCS_FERN_TOKEN (from `fern token` for the nvidia Fern org)
25+
26+
name: "Preview Fern Docs: Comment"
27+
28+
on:
29+
workflow_run:
30+
workflows: ["Preview Fern Docs: Build"]
31+
types: [completed]
32+
33+
permissions:
34+
pull-requests: write
35+
actions: read
36+
37+
jobs:
38+
preview:
39+
runs-on: ubuntu-latest
40+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
41+
steps:
42+
- name: Download fern sources and metadata
43+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
44+
with:
45+
name: fern-preview
46+
run-id: ${{ github.event.workflow_run.id }}
47+
github-token: ${{ secrets.GITHUB_TOKEN }}
48+
49+
- name: Read PR metadata
50+
id: metadata
51+
run: |
52+
echo "pr_number=$(cat preview-metadata/pr_number)" >> "$GITHUB_OUTPUT"
53+
echo "head_ref=$(cat preview-metadata/head_ref)" >> "$GITHUB_OUTPUT"
54+
55+
- name: Setup Node.js
56+
uses: actions/setup-node@v6
57+
with:
58+
node-version: '20'
59+
60+
- name: Install Fern CLI
61+
run: npm install -g fern-api
62+
63+
- name: Generate preview URL
64+
id: generate-docs
65+
env:
66+
FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }}
67+
HEAD_REF: ${{ steps.metadata.outputs.head_ref }}
68+
working-directory: ./fern
69+
run: |
70+
OUTPUT=$(fern generate --docs --preview --id "$HEAD_REF" 2>&1)
71+
echo "$OUTPUT"
72+
URL=$(echo "$OUTPUT" | grep -oP 'Published docs to \K.*(?= \()')
73+
if [ -z "$URL" ]; then
74+
echo "::error::Failed to generate preview URL. See fern output above."
75+
exit 1
76+
fi
77+
echo "preview_url=$URL" >> "$GITHUB_OUTPUT"
78+
79+
- name: Build page links for changed MDX files
80+
id: page-links
81+
env:
82+
FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }}
83+
PREVIEW_URL: ${{ steps.generate-docs.outputs.preview_url }}
84+
run: |
85+
CHANGED_FILES=""
86+
if [ -f preview-metadata/changed_mdx_files ]; then
87+
CHANGED_FILES=$(cat preview-metadata/changed_mdx_files)
88+
fi
89+
90+
if [ -z "$CHANGED_FILES" ] || [ -z "$PREVIEW_URL" ]; then
91+
echo "page_links=" >> "$GITHUB_OUTPUT"; exit 0
92+
fi
93+
94+
BASE_URL=$(echo "$PREVIEW_URL" | grep -oP 'https?://[^/]+')
95+
FILES_PARAM=$(echo "$CHANGED_FILES" | tr '\n' ',' | sed 's/,$//' \
96+
| python3 -c "import sys, urllib.parse; print(urllib.parse.quote(sys.stdin.read().strip(), safe=',/'))")
97+
RESPONSE=$(curl -sf -H "FERN_TOKEN: $FERN_TOKEN" "${PREVIEW_URL}/api/fern-docs/get-slug-for-file?files=${FILES_PARAM}" 2>/dev/null) || {
98+
echo "page_links=" >> "$GITHUB_OUTPUT"; exit 0
99+
}
100+
101+
PAGE_LINKS=$(echo "$RESPONSE" | jq -r --arg url "$BASE_URL" \
102+
'.mappings[] | select(.slug != null) | "- [\(.slug)](\($url)/\(.slug))"')
103+
104+
if [ -n "$PAGE_LINKS" ]; then
105+
{ echo "page_links<<EOF"; echo "$PAGE_LINKS"; echo "EOF"; } >> "$GITHUB_OUTPUT"
106+
else
107+
echo "page_links=" >> "$GITHUB_OUTPUT"
108+
fi
109+
110+
- name: Post or update PR comment
111+
env:
112+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
113+
PR_NUMBER: ${{ steps.metadata.outputs.pr_number }}
114+
PREVIEW_URL: ${{ steps.generate-docs.outputs.preview_url }}
115+
PAGE_LINKS: ${{ steps.page-links.outputs.page_links }}
116+
run: |
117+
# Build comment body
118+
BODY=":herb: **Preview your docs:** <${PREVIEW_URL}>"
119+
if [ -n "${PAGE_LINKS}" ]; then
120+
BODY="${BODY}
121+
122+
Here are the markdown pages you've updated:
123+
${PAGE_LINKS}"
124+
fi
125+
126+
# Hidden marker for upsert
127+
MARKER="<!-- preview-docs -->"
128+
BODY="${BODY}
129+
130+
${MARKER}"
131+
132+
# Find existing comment with marker
133+
COMMENT_ID=$(gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
134+
--jq ".[] | select(.body | contains(\"${MARKER}\")) | .id" | tr -d '\r' | head -1)
135+
136+
if [ -n "$COMMENT_ID" ]; then
137+
gh api "repos/${{ github.repository }}/issues/comments/${COMMENT_ID}" \
138+
-X PATCH -f body="$BODY"
139+
else
140+
gh api "repos/${{ github.repository }}/issues/${PR_NUMBER}/comments" \
141+
-f body="$BODY"
142+
fi
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Publishes the Fern documentation site when a docs tag is pushed or manually triggered.
17+
#
18+
# To publish: git tag docs/v1.2.0 && git push origin docs/v1.2.0
19+
# Or use the "Run workflow" button in the Actions tab.
20+
#
21+
# Required configuration:
22+
# - Organization secret: DOCS_FERN_TOKEN (from `fern token` for the nvidia Fern org)
23+
24+
name: Publish Fern Docs
25+
26+
on:
27+
push:
28+
branches:
29+
- main
30+
paths:
31+
- 'docs/**'
32+
- 'fern/**'
33+
tags:
34+
- 'docs/v*'
35+
workflow_dispatch: {}
36+
37+
permissions:
38+
contents: read
39+
40+
concurrency:
41+
group: fern-publish
42+
cancel-in-progress: true
43+
44+
jobs:
45+
publish:
46+
runs-on: ubuntu-latest
47+
steps:
48+
- name: Checkout repository
49+
uses: actions/checkout@v6
50+
51+
- name: Setup Node.js
52+
uses: actions/setup-node@v6
53+
with:
54+
node-version: '20'
55+
56+
- name: Install Fern CLI
57+
run: npm install -g fern-api
58+
59+
- name: Publish Docs
60+
env:
61+
FERN_TOKEN: ${{ secrets.DOCS_FERN_TOKEN }}
62+
working-directory: ./fern
63+
run: fern generate --docs

fern/docs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ navbar-links:
3838
experimental:
3939
mdx-components:
4040
- ./components
41+
basepath-aware: true
4142

4243
versions:
4344
- display-name: Latest

0 commit comments

Comments
 (0)