Skip to content

Commit c108c31

Browse files
authored
docs(fern): sync announcement configuration (#3436)
* docs(fern): sync announcement configuration Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * fix(docs): scope announcements to synced channel Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(fern): use dev as source version Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> * docs(fern): use channel-neutral logo link Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com> --------- Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
1 parent 4443ae7 commit c108c31

4 files changed

Lines changed: 292 additions & 11 deletions

File tree

fern/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ OpenShell uses [Fern](https://buildwithfern.com/) to validate, preview, and publ
1313
| `fern/assets/` | Logos and other shared assets. |
1414
| `fern/main.css` | Site-wide styles. |
1515

16-
In a normal source checkout, `fern/docs.yml` points the `latest` version at `docs/index.yml`. Release automation builds the multi-version configuration on the generated `docs-website` branch.
16+
In a normal source checkout, `fern/docs.yml` points the `dev` version at `docs/index.yml`. Release automation builds the multi-version configuration on the generated `docs-website` branch and maps the source documentation to the channel being published.
1717

1818
## Local development
1919

@@ -54,6 +54,8 @@ The sync and publish workflows share the `docs-website` concurrency group. This
5454

5555
The `dev` snapshot also owns the shared Fern configuration, components, assets, and CSS on `docs-website`. The `latest` snapshot copies its documentation and navigation but does not replace those shared files. This keeps the site configuration aligned with `main` while preserving the released content.
5656

57+
A `dev` sync copies the top-level `announcement` from the source `fern/docs.yml`. This announcement is the global fallback, and removing it from the source removes it from `docs-website`. Each snapshot sync copies the source version announcement only to the channel being updated. A version announcement overrides the global announcement for that version, so Release Dev cannot change the `latest` announcement and Release Tag cannot change the `dev` announcement.
58+
5759
## Manual maintenance and publishing
5860

5961
Maintainers can run `.github/workflows/sync-docs.yml` manually to add, refresh, or remove a historical version snapshot. The workflow preserves snapshots that were not selected. Production publishing is disabled by default for a manual sync.

fern/docs.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# SPDX-License-Identifier: Apache-2.0
33
# Fern site config — merged with skills/convert-to-fern/assets/theme/nvidia/docs-theme.yml pattern
44
# Production: https://docs.nvidia.com/openshell/ — preview + custom-domain share path prefix `openshell`.
5-
# Internal MDX links use /latest/...; basepath-aware resolves them under /openshell/ on production.
5+
# Source checkouts and pull request previews expose the current documentation at /dev.
66
instances:
77
- url: openshell.docs.buildwithfern.com/openshell
88
custom-domain: docs.nvidia.com/openshell
@@ -38,7 +38,7 @@ logo:
3838
dark: ./assets/NVIDIA_dark.svg
3939
light: ./assets/NVIDIA_light.svg
4040
height: 20
41-
href: /openshell/latest
41+
href: /openshell
4242
right-text: OpenShell
4343

4444
favicon: ./assets/NVIDIA_symbol.svg
@@ -56,11 +56,10 @@ experimental:
5656
- ./components
5757

5858
versions:
59-
- display-name: Latest
59+
- display-name: Dev
6060
path: ../docs/index.yml
61-
slug: latest
62-
announcement:
63-
message: '<span style="display: block; padding: 0.375rem 0; text-align: left;"><strong>OpenShell 0.1.0 is coming soon.</strong> <a href="https://github.com/NVIDIA/OpenShell/milestone/10" target="_blank" rel="noreferrer">Track progress in the 0.1.0 milestone</a>, <a href="https://docs.nvidia.com/openshell/dev/index.html" target="_blank" rel="noreferrer">read the prerelease documentation</a>, or <a href="https://docs.nvidia.com/openshell/dev/about/installation#install-a-prerelease" target="_blank" rel="noreferrer">install a prerelease</a>.</span>'
61+
slug: dev
62+
availability: beta
6463

6564
redirects:
6665
- source: "/openshell/latest/sandboxes/providers-v2"

tasks/scripts/sync_docs_website.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class VersionEntry:
3636
display_name: str
3737
path: str
3838
availability: str | None = None
39+
announcement: YamlMapping | None = None
3940

4041

4142
def parse_args() -> argparse.Namespace:
@@ -312,6 +313,7 @@ def parse_versions(raw_versions: object) -> list[VersionEntry]:
312313
display_name = entry.get("display-name")
313314
path = entry.get("path")
314315
availability = entry.get("availability")
316+
announcement = entry.get("announcement")
315317
if (
316318
isinstance(slug, str)
317319
and isinstance(display_name, str)
@@ -325,6 +327,9 @@ def parse_versions(raw_versions: object) -> list[VersionEntry]:
325327
availability=availability
326328
if isinstance(availability, str)
327329
else None,
330+
announcement=cast("YamlMapping", announcement)
331+
if isinstance(announcement, dict)
332+
else None,
328333
)
329334
)
330335
return entries
@@ -349,8 +354,8 @@ def ordered_entries(
349354
return [by_slug[slug] for slug in order]
350355

351356

352-
def render_versions(entries: list[VersionEntry]) -> list[dict[str, str]]:
353-
rendered: list[dict[str, str]] = []
357+
def render_versions(entries: list[VersionEntry]) -> list[YamlMapping]:
358+
rendered: list[YamlMapping] = []
354359
for entry in entries:
355360
item = {
356361
"display-name": entry.display_name,
@@ -359,10 +364,36 @@ def render_versions(entries: list[VersionEntry]) -> list[dict[str, str]]:
359364
}
360365
if entry.availability is not None:
361366
item["availability"] = entry.availability
367+
if entry.announcement is not None:
368+
item["announcement"] = entry.announcement
362369
rendered.append(item)
363370
return rendered
364371

365372

373+
def sync_global_announcement(source_docs_yml: Path, target_docs_yml: Path) -> None:
374+
source_data = read_yaml(source_docs_yml)
375+
source_announcement = source_data.get("announcement")
376+
if source_announcement is not None and not isinstance(source_announcement, dict):
377+
raise ValueError("docs.yml announcement must be a mapping")
378+
379+
target_data = read_yaml(target_docs_yml)
380+
if source_announcement is None:
381+
target_data.pop("announcement", None)
382+
else:
383+
target_data["announcement"] = source_announcement
384+
write_yaml(target_docs_yml, target_data)
385+
386+
387+
def source_version_announcement(docs_yml: Path, slug: str) -> YamlMapping | None:
388+
entries = parse_versions(read_yaml(docs_yml).get("versions"))
389+
for entry in entries:
390+
if entry.slug == slug:
391+
return entry.announcement
392+
if len(entries) == 1:
393+
return entries[0].announcement
394+
return None
395+
396+
366397
def component_dirs(fern_dir: Path) -> list[str]:
367398
dirs: list[str] = []
368399
preferred = ["pages-latest", "pages-dev"]
@@ -408,6 +439,7 @@ def write_snapshot(
408439
copy_if_exists(
409440
source_fern / "fern.config.json", target_fern / "fern.config.json"
410441
)
442+
sync_global_announcement(source_fern / "docs.yml", target_fern / "docs.yml")
411443

412444
versions_dir = target_fern / "versions"
413445
versions_dir.mkdir(parents=True, exist_ok=True)
@@ -483,6 +515,9 @@ def sync_docs(args: argparse.Namespace) -> None:
483515
display_name=slug,
484516
path=f"./versions/{slug}.yml",
485517
availability=stable_availability,
518+
announcement=source_version_announcement(
519+
source_fern / "docs.yml", slug
520+
),
486521
),
487522
refresh_shared=False,
488523
)
@@ -509,6 +544,9 @@ def sync_docs(args: argparse.Namespace) -> None:
509544
display_name=display_override or f"Latest ({slug})",
510545
path="./versions/latest.yml",
511546
availability=stable_availability,
547+
announcement=source_version_announcement(
548+
source_fern / "docs.yml", "latest"
549+
),
512550
),
513551
refresh_shared=False,
514552
)
@@ -548,6 +586,7 @@ def sync_docs(args: argparse.Namespace) -> None:
548586
display_name=display_name,
549587
path=f"./versions/{slug}.yml",
550588
availability=availability,
589+
announcement=source_version_announcement(source_fern / "docs.yml", slug),
551590
),
552591
refresh_shared=channel == "dev",
553592
)

0 commit comments

Comments
 (0)