Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .agents/skills/prepare-code-freeze/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: prepare-code-freeze
description: Prepare a NeMo Flow code freeze by creating the release branch, updating nightly alpha branch config, bumping main to the next version, and opening the required PR
author: NVIDIA Corporation and Affiliates
license: Apache-2.0
---

Comment thread
willkill07 marked this conversation as resolved.
# Prepare Code Freeze

Use this skill when the user asks to start, prepare, or automate a NeMo Flow
code freeze.

## Companion Guidance

Use `update-project-version` for version bump semantics and `prepare-pr` before
opening the PR.

## Workflow

This workflow assumes `upstream` is the NVIDIA repository remote
(`NVIDIA/NeMo-Flow`). The `origin` remote can be a maintainer's personal fork.

1. Confirm or infer the target release version from `upstream/main:Cargo.toml`.
Derive the release branch as `release/<major>.<minor>`.
2. Prompt for `<next-version>` if the user did not provide it. This is the
version that `main` moves to after the release branch is cut.
3. Fetch the latest `main` and create the release branch from `upstream/main`:

```bash
git fetch upstream main
git branch release/<major>.<minor> upstream/main
git push upstream release/<major>.<minor>
```

If the remote release branch already exists, verify it points where expected
before continuing.
4. Create a PR branch from latest `upstream/main`, for example
`docs/code-freeze-<major>.<minor>`.
5. Update `.github/nightly-alpha-branches.yaml` to include the new release
branch.
6. Run `just set-version <next-version>` to bump all release-versioned package
surfaces on `main`.
7. Validate with targeted checks:

```bash
ruby -e 'require "yaml"; YAML.load_file(".github/nightly-alpha-branches.yaml"); YAML.load_file(".github/workflows/nightly-alpha-tag.yaml")'
just set-version <next-version>
git diff --check
```

8. Open a PR targeting `main` using `.github/pull_request_template.md`. The PR
must mention:
- the new release branch
- the nightly alpha branch config update
- the `just set-version <next-version>` bump
- that release-bound PRs now target the new `release/*` branch

## Guardrails

- Do not create release tags. Code freeze only creates the branch and the main
PR.
- Do not target the code-freeze PR at the release branch. It targets `main`.
- Do not leave uncommitted user changes mixed into the code-freeze PR branch.
21 changes: 14 additions & 7 deletions .agents/skills/update-project-version/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ pre-release or build-metadata variants used during packaging.
workspace version changes.
- `crates/node/package.json` carries its own npm package version and must stay
aligned with the workspace-root `package-lock.json`.
- `package-lock.json` records the Node package version under
`packages["crates/node"].version`. The workspace-root lockfile may not have a
top-level `version` field.
- `integrations/openclaw/package.json` carries the OpenClaw npm plugin version
and must stay aligned with the workspace-root `package-lock.json`.
- `package-lock.json` records Node package versions under
`packages["crates/node"].version` and
`packages["integrations/openclaw"].version`. The workspace-root lockfile may
not have a top-level `version` field.
- `crates/wasm/package.json` is a local dev manifest. Do not treat it as the
publishable package manifest unless it gains an explicit `version` field.
- The publishable WebAssembly npm package version is derived from
Expand All @@ -44,11 +47,14 @@ pre-release or build-metadata variants used during packaging.
- `workspace.dependencies.nemo-flow-adaptive.version`
- `workspace.dependencies.nemo-flow-ffi.version`
- `crates/node/package.json` `version`
- `integrations/openclaw/package.json` `version`
- `package-lock.json` `packages["crates/node"].version`
- `package-lock.json` `packages["integrations/openclaw"].version`
3. If editing helper code, keep `set_project_version`,
`set_cargo_workspace_version`, and `set_node_package_version` aligned with
those same fields. `set_npm_package_version` remains the reusable npm JSON
helper for Node and WebAssembly packaging recipes.
`set_cargo_workspace_version`, and `set_node_package_versions` aligned with
those same fields. `set_node_package_version` remains a compatibility alias.
`set_npm_package_version` remains the reusable npm JSON helper for Node and
WebAssembly packaging recipes.
4. Refresh generated surfaces:
- Run `cargo check --workspace` to refresh `Cargo.lock` if workspace package
entries changed.
Expand All @@ -69,7 +75,7 @@ pre-release or build-metadata variants used during packaging.
## Validation

- `rg -n '^version =|nemo-flow = \\{ version =|nemo-flow-adaptive = \\{ version =' Cargo.toml`
- `rg -n '\"version\"' crates/node/package.json package-lock.json`
- `rg -n '\"version\"' crates/node/package.json integrations/openclaw/package.json package-lock.json`
- `cargo check --workspace`
- If Rust attribution files are expected to stay current:
`./scripts/generate_attributions.sh rust`
Expand Down Expand Up @@ -101,6 +107,7 @@ pre-release or build-metadata variants used during packaging.
- `package.json`
- `package-lock.json`
- `crates/node/package.json`
- `integrations/openclaw/package.json`
- `crates/wasm/Cargo.toml`
- `crates/wasm/package.json`
- `crates/wasm/scripts/prepare_pkg.mjs`
Expand Down
5 changes: 5 additions & 0 deletions .github/nightly-alpha-branches.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

branches:
- main
45 changes: 40 additions & 5 deletions .github/workflows/nightly-alpha-tag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,34 @@ concurrency:
cancel-in-progress: false

jobs:
nightly-alpha-config:
name: Load nightly alpha branches
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
branches: ${{ steps.config.outputs.branches }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

- name: Load nightly alpha branch config
id: config
run: |
set -euo pipefail
branches_json="$(ruby -ryaml -rjson -e 'puts JSON.generate(YAML.load_file(".github/nightly-alpha-branches.yaml").fetch("branches"))')"
printf 'branches=%s\n' "$branches_json" >> "$GITHUB_OUTPUT"

tag-nightly-alpha:
name: Tag nightly alpha
if: ${{ github.ref == 'refs/heads/main' }}
needs: nightly-alpha-config
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
branch: ${{ fromJSON(needs.nightly-alpha-config.outputs.branches) }}
permissions:
contents: read
steps:
Expand All @@ -26,9 +50,11 @@ jobs:
with:
fetch-depth: 0
persist-credentials: false
ref: ${{ matrix.branch }}

- name: Create nightly alpha tag
env:
NEMO_FLOW_NIGHTLY_BRANCH: ${{ matrix.branch }}
NEMO_FLOW_NIGHTLY_TAG_TOKEN: ${{ secrets.NEMO_FLOW_NIGHTLY_TAG_TOKEN }}
run: |
set -euo pipefail
Expand All @@ -50,9 +76,18 @@ jobs:

tag_date="$(date -u +%Y%m%d)"
tag="${version}-alpha.${tag_date}"
target_sha="$(git rev-parse HEAD)"
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
echo "Nightly alpha tag already exists: ${tag}"
exit 0
existing_sha="$(git ls-remote --tags origin "refs/tags/${tag}^{}" | awk '{print $1}' || true)"
if [[ -z "$existing_sha" ]]; then
existing_sha="$(git ls-remote --tags origin "refs/tags/${tag}" | awk '{print $1}' || true)"
fi
if [[ "$existing_sha" == "$target_sha" ]]; then
echo "Nightly alpha tag already exists for ${NEMO_FLOW_NIGHTLY_BRANCH}: ${tag}"
exit 0
fi
echo "Error: nightly alpha tag ${tag} already exists at ${existing_sha}, not ${NEMO_FLOW_NIGHTLY_BRANCH} HEAD ${target_sha}" >&2
exit 1
fi

git config user.name "github-actions[bot]"
Expand All @@ -61,7 +96,7 @@ jobs:
--annotate \
--message "NeMo Flow ${version} Nightly ${tag_date}" \
"$tag" \
"$GITHUB_SHA"
"$target_sha"
git remote set-url origin "https://x-access-token:${NEMO_FLOW_NIGHTLY_TAG_TOKEN}@github.com/${GITHUB_REPOSITORY}.git"
git push origin "refs/tags/${tag}"
echo "Created nightly alpha tag: ${tag}"
echo "Created nightly alpha tag for ${NEMO_FLOW_NIGHTLY_BRANCH}: ${tag}"
108 changes: 81 additions & 27 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ The release pipeline publishes these package surfaces from a tag push:
|---|---|
| crates.io | `nemo-flow`, `nemo-flow-adaptive`, `nemo-flow-ffi`, `nemo-flow-cli` |
| PyPI | `nemo-flow` |
| npm | `nemo-flow-node`, `nemo-flow-wasm` |
| npm | `nemo-flow-node`, `nemo-flow-openclaw`, `nemo-flow-wasm` |
| GitHub Pages | The documentation site, including the versioned docs build |

Go remains source-first. There is no separate Go package-manager publication
Expand All @@ -51,6 +51,8 @@ NeMo Flow versions are anchored on the workspace SemVer in the repository root
- `crates/node/package.json` carries the base npm version for the Node.js
package. The repository-root `package-lock.json` carries the npm workspace
lock entries and must be updated with it.
- `integrations/openclaw/package.json` carries the base npm version for the
OpenClaw plugin package and must stay aligned with the same release version.
- The Python package version is derived at packaging time. `pyproject.toml`
stays `dynamic = ["version"]` in the repository, and the packaging recipe
writes a concrete version into `pyproject.toml` and `crates/python/Cargo.toml`
Expand All @@ -76,12 +78,50 @@ CI rejects tags that do not match the required format.

The tag text must match the version that the packaging jobs publish.

Release tags for a frozen release line should be created from the matching
`release/*` branch, not from `main`.

## Code Freeze

When code freeze begins for a target release, create a release branch from the
latest `main` commit. Name the branch from the target release major and minor
version:

These examples assume `upstream` is the NVIDIA repository remote
(`NVIDIA/NeMo-Flow`). The `origin` remote is usually a maintainer's personal
fork.

```bash
git fetch upstream main
git checkout -b release/0.2 upstream/main
git push upstream release/0.2
```

After creating the release branch, open a PR against `main` that does both of
the following:

1. Add the new `release/*` branch to
[`.github/nightly-alpha-branches.yaml`](.github/nightly-alpha-branches.yaml)
so nightly alpha tags continue for the frozen release line.
2. Bump all package versions on `main` to the next release line:

```bash
just set-version <next-version>
```

New PRs that must go into the upcoming release must target the new `release/*`
branch. Changes intended for later releases should continue to target `main`.

When a release branch no longer needs nightly alpha tags, open a PR against
`main` to remove that branch from
[`.github/nightly-alpha-branches.yaml`](.github/nightly-alpha-branches.yaml).

## Before You Cut A Release

Before you create a release tag, confirm the following:

1. The intended release commit is already on `main` or on the release branch
you intend to tag.
1. The intended release commit is already on the release branch you intend to
tag. For frozen release lines, tag the matching `release/*` branch.
2. The release commit contains the final version bump, docs updates, and any
public API changes that belong in the release.
3. The working tree you use for local validation is clean or disposable.
Expand All @@ -97,20 +137,31 @@ Before you create a release tag, confirm the following:

## Prepare The Release Commit

Update the versioned source files in the release PR or release-prep commit:

1. Update the root [`Cargo.toml`](Cargo.toml) workspace version.
2. Update the root [`Cargo.toml`](Cargo.toml) `workspace.dependencies` versions
for `nemo-flow`, `nemo-flow-adaptive`, `nemo-flow-ffi`, and
`nemo-flow-cli`.
3. Update [`crates/node/package.json`](crates/node/package.json) and the
`crates/node` entry in the root [`package-lock.json`](package-lock.json) to
the same release version.
4. Review docs and snippets that mention explicit versions, including:
- [`README.md`](README.md)
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
- [`docs/getting-started/installation.md`](docs/getting-started/installation.md)
- Any binding README or example that pins a release number
Update the versioned source files in the release PR or release-prep commit.
Prefer the repository helper:

```bash
just set-version <release-version>
```

The helper updates:

1. The root [`Cargo.toml`](Cargo.toml) workspace version.
2. The root [`Cargo.toml`](Cargo.toml) `workspace.dependencies` versions for
`nemo-flow`, `nemo-flow-adaptive`, `nemo-flow-ffi`, and `nemo-flow-cli`.
3. [`crates/node/package.json`](crates/node/package.json) and the `crates/node`
entry in the root [`package-lock.json`](package-lock.json) to the same
release version.
4. [`integrations/openclaw/package.json`](integrations/openclaw/package.json)
and the `integrations/openclaw` entry in the root
[`package-lock.json`](package-lock.json) to the same release version.

Review docs and snippets that mention explicit versions, including:

- [`README.md`](README.md)
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
- [`docs/getting-started/installation.md`](docs/getting-started/installation.md)
- Any binding README or example that pins a release number

Comment thread
willkill07 marked this conversation as resolved.
Do not commit a static Python package version into `pyproject.toml` just to cut
the release. The packaging workflow stamps that file during the build.
Expand All @@ -135,6 +186,7 @@ If you want to validate the packaging recipes before pushing a tag, run:

```bash
just --set output_dir "$PWD/target/release-artifacts" --set ref_name 0.1.0 package-node
just --set output_dir "$PWD/target/release-artifacts" --set ref_name 0.1.0 package-openclaw
just --set output_dir "$PWD/target/release-artifacts" --set ref_name 0.1.0 package-python
just --set output_dir "$PWD/target/release-artifacts" --set ref_name 0.1.0 package-wasm
```
Expand All @@ -150,18 +202,18 @@ After the release commit is merged and validated, create and push the raw
SemVer tag:

```bash
git fetch origin
git checkout main
git pull --ff-only
git fetch upstream release/0.1
git checkout release/0.1
git pull --ff-only upstream release/0.1
git tag 0.1.0
git push origin 0.1.0
git push upstream 0.1.0
```

Use the prerelease form when needed:

```bash
git tag 0.1.0-rc.1
git push origin 0.1.0-rc.1
git push upstream 0.1.0-rc.1
```

## What CI Does On A Tag Push
Expand All @@ -178,6 +230,7 @@ The release pipeline then:
3. Builds and uploads the versioned GitHub Pages documentation artifact.
4. Builds publishable package artifacts with the exact tag version:
- `package-node` packs the npm Node.js package.
- `package-openclaw` packs the npm OpenClaw plugin package.
- `package-python` builds platform wheels.
- `package-wasm` packs the npm WebAssembly package.
5. Publishes packages from the top-level workflow after the reusable packaging
Expand All @@ -188,8 +241,8 @@ The release pipeline then:
the top-level workflow
- `publish-python` uploads the wheel artifacts to PyPI with trusted
publishing from the top-level workflow
- `publish-npm` publishes the Node.js and WebAssembly npm packages through npm
trusted publishing from the top-level workflow
- `publish-npm` publishes the Node.js, OpenClaw plugin, and WebAssembly npm
packages through npm trusted publishing from the top-level workflow
- Stable tags publish to the npm `latest` dist-tag
- Prerelease tags such as `0.1.0-rc.1` publish to the npm `next`
dist-tag so they do not become the default upgrade target
Expand All @@ -210,8 +263,8 @@ The workflow boundary is split intentionally:
npm trusted publishing has its own registry-side constraints:

- Each npm package can only have one trusted publisher configured at a time.
- Because this repository publishes both `nemo-flow-node` and
`nemo-flow-wasm`, configure trusted publishers for both packages before
- Because this repository publishes `nemo-flow-node`, `nemo-flow-openclaw`, and
`nemo-flow-wasm`, configure trusted publishers for all three packages before
pushing a release tag.
- npm trusted publishing currently supports GitHub-hosted runners, not
self-hosted runners.
Expand Down Expand Up @@ -242,7 +295,8 @@ After the release is live, verify:

1. The expected crates are visible on crates.io.
2. The `nemo-flow` wheel is visible on PyPI.
3. The `nemo-flow-node` and `nemo-flow-wasm` packages are visible on npm.
3. The `nemo-flow-node`, `nemo-flow-openclaw`, and `nemo-flow-wasm` packages
are visible on npm.
4. The GitHub Pages deployment completed successfully.
5. The GitHub Release page is complete and accurate.

Expand Down
Loading