From a3731b6f8a063e7d746ed4db0e2b737da900be04 Mon Sep 17 00:00:00 2001 From: Brandon Pelfrey Date: Tue, 7 Apr 2026 20:39:44 -0700 Subject: [PATCH 1/4] fix(scripts): remove static issue line from release PR template --- scripts/bump-version.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/bump-version.ts b/scripts/bump-version.ts index b662660c0..5f4dd784c 100644 --- a/scripts/bump-version.ts +++ b/scripts/bump-version.ts @@ -406,7 +406,10 @@ function createReleasePr(options: Options, previousVersion: string, tagName: str git(["commit", "-m", `chore(release): bump version to ${tagName}`]); git(["push", "-u", "origin", options.branchName]); - const prBody = buildPrBody(previousVersion, options.version); + const prBody = buildPrBody(previousVersion, options.version, { + ranTests: !options.skipTests, + ranFormat: false, + }); const prUrl = run( "gh", [ @@ -441,7 +444,12 @@ function gitRemoteBranchExists(branchName: string): boolean { return run("git", ["ls-remote", "--exit-code", "--heads", "origin", branchName], { allowFailure: true }).exitCode === 0; } -function buildPrBody(previousVersion: string, nextVersion: string): string { +type PrBodyOptions = { + ranTests: boolean; + ranFormat: boolean; +}; + +function buildPrBody(previousVersion: string, nextVersion: string, options: PrBodyOptions): string { const gitUserName = run("git", ["config", "user.name"]).trim(); const gitUserEmail = run("git", ["config", "user.email"]).trim(); @@ -457,9 +465,6 @@ function buildPrBody(previousVersion: string, nextVersion: string): string { `Bump NemoClaw from ${previousVersion} to ${nextVersion} across the CLI package, plugin package,`, "blueprint manifest, installer defaults, and versioned docs references.", "", - "## Related Issue", - "Fixes #1577.", - "", "## Changes", `- bump release version from ${previousVersion} to ${nextVersion}`, "- update installer and docs version references to match the npm/package version", @@ -472,8 +477,8 @@ function buildPrBody(previousVersion: string, nextVersion: string): string { "- [ ] Doc only. Includes code sample changes.", "", "## Testing", - "- [ ] `npx prek run --all-files` passes (or equivalently `make check`).", - "- [x] `npm test` passes.", + `- [${options.ranFormat ? "x" : " "}] \`npx prek run --all-files\` passes (or equivalently \`make check\`).`, + `- [${options.ranTests ? "x" : " "}] \`npm test\` passes.`, "- [ ] `make docs` builds without warnings. (for doc-only changes)", "", "## Checklist", @@ -484,7 +489,7 @@ function buildPrBody(previousVersion: string, nextVersion: string): string { "- [ ] I have read and followed the [style guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md). (for doc-only changes)", "", "### Code Changes", - "- [x] Formatters applied — `npx prek run --all-files` auto-fixes formatting (or `make format` for targeted runs).", + `- [${options.ranFormat ? "x" : " "}] Formatters applied — \`npx prek run --all-files\` auto-fixes formatting (or \`make format\` for targeted runs).`, "- [ ] Tests added or updated for new or changed behavior.", "- [x] No secrets, API keys, or credentials committed.", "- [x] Doc pages updated for any user-facing behavior changes (new commands, changed defaults, new features, bug fixes that contradict existing docs).", From 623edea3540f7f5c012d4b2de53d03963db1271b Mon Sep 17 00:00:00 2001 From: Brandon Pelfrey Date: Wed, 8 Apr 2026 07:30:34 -0700 Subject: [PATCH 2/4] chore(release): update docs metadata during version bumps --- docs/versions1.json | 7 +++ scripts/bump-version.ts | 117 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 docs/versions1.json diff --git a/docs/versions1.json b/docs/versions1.json new file mode 100644 index 000000000..706fea0c6 --- /dev/null +++ b/docs/versions1.json @@ -0,0 +1,7 @@ +[ + { + "preferred": true, + "version": "0.1.0", + "url": "https://docs.nvidia.com/nemoclaw/0.1.0/" + } +] diff --git a/scripts/bump-version.ts b/scripts/bump-version.ts index 5f4dd784c..b28cfc1db 100644 --- a/scripts/bump-version.ts +++ b/scripts/bump-version.ts @@ -30,11 +30,25 @@ type BlueprintManifest = { [key: string]: unknown; }; +type DocsProjectJson = { + name?: string; + version?: string; + [key: string]: unknown; +}; + +type DocsVersionEntry = { + preferred?: boolean; + version: string; + url: string; +}; + const REPO_ROOT = process.cwd(); const ROOT_PACKAGE_JSON = path.join(REPO_ROOT, "package.json"); const PLUGIN_PACKAGE_JSON = path.join(REPO_ROOT, "nemoclaw", "package.json"); const BLUEPRINT_YAML = path.join(REPO_ROOT, "nemoclaw-blueprint", "blueprint.yaml"); const DOCS_CONF = path.join(REPO_ROOT, "docs", "conf.py"); +const DOCS_PROJECT_JSON = path.join(REPO_ROOT, "docs", "project.json"); +const DOCS_VERSIONS_JSON = path.join(REPO_ROOT, "docs", "versions1.json"); const INSTALL_SH = path.join(REPO_ROOT, "scripts", "install.sh"); const README_MD = path.join(REPO_ROOT, "README.md"); const QUICKSTART_MD = path.join(REPO_ROOT, "docs", "get-started", "quickstart.md"); @@ -44,6 +58,8 @@ const FILES_TO_STAGE = [ PLUGIN_PACKAGE_JSON, BLUEPRINT_YAML, DOCS_CONF, + DOCS_PROJECT_JSON, + DOCS_VERSIONS_JSON, INSTALL_SH, ...VERSIONED_DOC_LINK_FILES, ]; @@ -79,6 +95,8 @@ function main(): void { updateBlueprintVersion(options.version); updateInstallScriptDefaultVersion(previousVersion, options.version); updateDocsConf(options.version); + updateDocsProjectJson(options.version); + updateDocsVersionsJson(options.version); updateDocsVersionLinks(nextDocsPublicUrl); updateInstallAndUninstallDocs(nextDocsVersion); @@ -310,6 +328,66 @@ function updateDocsConf(nextVersion: string): void { writeFileSync(DOCS_CONF, updated, "utf8"); } +function updateDocsProjectJson(version: string): void { + const project = readJson(DOCS_PROJECT_JSON); + project.version = version; + writeFileSync(DOCS_PROJECT_JSON, `${JSON.stringify(project, null, 2)}\n`, "utf8"); +} + +function updateDocsVersionsJson(version: string): void { + const currentEntries = readDocsVersionsJson(); + const filteredEntries = currentEntries.filter((entry) => entry.version !== version); + const nextEntries: DocsVersionEntry[] = [ + { + preferred: true, + version, + url: buildDocsVersionUrl(version), + }, + ...filteredEntries.map((entry) => ({ + version: entry.version, + url: buildDocsVersionUrl(entry.version), + })), + ].slice(0, 5); + + writeFileSync(DOCS_VERSIONS_JSON, `${JSON.stringify(nextEntries, null, 2)}\n`, "utf8"); +} + +function readDocsVersionsJson(): DocsVersionEntry[] { + try { + const parsed = JSON.parse(readText(DOCS_VERSIONS_JSON)) as unknown; + if (!Array.isArray(parsed)) { + throw new Error("docs/versions1.json must contain an array"); + } + return parsed.map((entry) => { + if (!entry || typeof entry !== "object") { + throw new Error("Invalid docs/versions1.json entry"); + } + const candidate = entry as Partial; + if (typeof candidate.version !== "string") { + throw new Error("Each docs/versions1.json entry must include a string version"); + } + return { + preferred: candidate.preferred === true ? true : undefined, + version: candidate.version, + url: + typeof candidate.url === "string" && candidate.url.length > 0 + ? candidate.url + : buildDocsVersionUrl(candidate.version), + }; + }); + } catch (error) { + const err = error as NodeJS.ErrnoException; + if (err.code === "ENOENT") { + return []; + } + throw error; + } +} + +function buildDocsVersionUrl(version: string): string { + return `https://docs.nvidia.com/nemoclaw/${version}/`; +} + function updateDocsVersionLinks(nextDocsPublicUrl: string): void { for (const filePath of VERSIONED_DOC_LINK_FILES) { const current = readText(filePath); @@ -362,6 +440,8 @@ function verifyVersionState(version: string, docsPublicUrl: string, docsDisplayV requireContains(INSTALL_SH, `DEFAULT_NEMOCLAW_VERSION="${version}"`); requireContains(DOCS_CONF, `release = "${version}"`); + assertEqual(readJson(DOCS_PROJECT_JSON).version, version, "docs/project.json version mismatch"); + verifyDocsVersionsJson(version); requireContains(README_MD, docsPublicUrl); requireContains(README_MD, docsDisplayVersion); requireContains(QUICKSTART_MD, docsDisplayVersion); @@ -539,6 +619,43 @@ function requireContains(filePath: string, text: string): void { } } +function verifyDocsVersionsJson(expectedNewestVersion: string): void { + const entries = readJson(DOCS_VERSIONS_JSON); + if (!Array.isArray(entries)) { + throw new Error("docs/versions1.json must contain an array"); + } + if (entries.length === 0) { + throw new Error("docs/versions1.json must contain at least one version entry"); + } + if (entries.length > 5) { + throw new Error(`docs/versions1.json must contain at most 5 entries; found ${entries.length}`); + } + + entries.forEach((entry, index) => { + if (typeof entry.version !== "string" || entry.version.length === 0) { + throw new Error(`docs/versions1.json entry ${index} is missing a valid version`); + } + const expectedUrl = buildDocsVersionUrl(entry.version); + if (entry.url !== expectedUrl) { + throw new Error( + `docs/versions1.json entry ${index} has url '${entry.url}', expected '${expectedUrl}'`, + ); + } + if (index === 0) { + if (entry.version !== expectedNewestVersion) { + throw new Error( + `docs/versions1.json first entry must be ${expectedNewestVersion}; found ${entry.version}`, + ); + } + if (entry.preferred !== true) { + throw new Error("docs/versions1.json first entry must have preferred: true"); + } + } else if ("preferred" in entry && entry.preferred !== undefined) { + throw new Error("Only the first docs/versions1.json entry may set preferred"); + } + }); +} + function verifyDocsLinks(filePath: string, expectedDocsPublicUrl: string): void { const content = readText(filePath); const matches = Array.from( From 36b0eb3780446a2bdaaf17901a92c6c5323bd87e Mon Sep 17 00:00:00 2001 From: Brandon Pelfrey Date: Wed, 8 Apr 2026 11:53:25 -0700 Subject: [PATCH 3/4] Update docs version from 0.1.0 to 0.0.9 in JSON --- docs/versions1.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/versions1.json b/docs/versions1.json index 706fea0c6..2ac6ca102 100644 --- a/docs/versions1.json +++ b/docs/versions1.json @@ -1,7 +1,7 @@ [ { "preferred": true, - "version": "0.1.0", - "url": "https://docs.nvidia.com/nemoclaw/0.1.0/" + "version": "0.0.9", + "url": "https://docs.nvidia.com/nemoclaw/0.0.9/" } ] From 8d59686aca9379b66ae3aad203619d338e9dc6e6 Mon Sep 17 00:00:00 2001 From: Brandon Pelfrey Date: Wed, 8 Apr 2026 11:54:13 -0700 Subject: [PATCH 4/4] Increase the slice limit for nextEntries to 10 --- scripts/bump-version.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/bump-version.ts b/scripts/bump-version.ts index b28cfc1db..d70201d3a 100644 --- a/scripts/bump-version.ts +++ b/scripts/bump-version.ts @@ -347,7 +347,7 @@ function updateDocsVersionsJson(version: string): void { version: entry.version, url: buildDocsVersionUrl(entry.version), })), - ].slice(0, 5); + ].slice(0, 10); writeFileSync(DOCS_VERSIONS_JSON, `${JSON.stringify(nextEntries, null, 2)}\n`, "utf8"); }