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
4 changes: 0 additions & 4 deletions .github/ci-path-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ rust_package:
- 'crates/ffi/nemo_relay.h'
- 'crates/ffi/src/**'
- 'justfile'
- 'packages/cli-bin/**'
- 'python/cli-bin/**'
- 'rust-toolchain.toml'
- 'scripts/package-cli-bin.py'
Expand All @@ -82,10 +81,8 @@ node_package:
- 'justfile'
- 'package.json'
- 'package-lock.json'
- 'packages/cli-bin/**'
- 'pyproject.toml'
- 'rust-toolchain.toml'
- 'scripts/package-cli-bin.py'
- 'scripts/package-node-bin.py'
- 'uv.lock'

Expand Down Expand Up @@ -132,7 +129,6 @@ dependencies:
- 'integrations/**/package.json'
- 'package.json'
- 'package-lock.json'
- 'packages/cli-bin/**'
- 'pyproject.toml'
- 'python/cli-bin/**'
- 'scripts/licensing/**'
Expand Down
28 changes: 0 additions & 28 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -310,12 +310,10 @@ jobs:
cli_binaries=(nemo-relay-cli-*)
cli_wheels=(nemo_relay_cli_bin-*.whl)
python_api_wheels=(nemo_relay-*.whl)
cli_npm=(nemo-relay-bin-npm-*.tgz)
node_npm=(nemo-relay-node-npm-*.tgz)
expect_count 7 "CLI binary" "${cli_binaries[@]}"
expect_count 7 "CLI wheel" "${cli_wheels[@]}"
expect_count 7 "Python API wheel" "${python_api_wheels[@]}"
expect_count 8 "CLI npm" "${cli_npm[@]}"
expect_count 8 "Node npm" "${node_npm[@]}"

mapfile -t distribution_assets < <(
Expand Down Expand Up @@ -523,13 +521,6 @@ jobs:
name: openclaw-npm
path: openclaw-package/

- name: Download CLI npm artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: cli-npm-package-*
merge-multiple: true
path: cli-packages/

- name: Select npm dist-tag
run: |
set -e
Expand Down Expand Up @@ -558,25 +549,6 @@ jobs:
npm publish "./$metapackage" --access public --tag "${NEMO_RELAY_NPM_DIST_TAG}"
fi

- name: Publish CLI packages to npm
run: |
set -euo pipefail
version="${{ github.ref_name }}"
for pkg in cli-packages/nemo-relay-bin-npm-{linux-x64,linux-arm64,linux-x64-musl,linux-arm64-musl,darwin-arm64,win32-x64,win32-arm64}-${version}.tgz; do
name="$(tar xOf "$pkg" package/package.json | node -p 'JSON.parse(require("fs").readFileSync(0, "utf8")).name')"
if npm view "${name}@${version}" version --registry https://registry.npmjs.org >/dev/null 2>&1; then
echo "${name} ${version} already exists on npm; skipping"
continue
fi
npm publish "./$pkg" --access public --tag "${NEMO_RELAY_NPM_DIST_TAG}"
done
launcher="cli-packages/nemo-relay-bin-npm-${version}.tgz"
if npm view "nemo-relay-cli-bin@${version}" version --registry https://registry.npmjs.org >/dev/null 2>&1; then
echo "nemo-relay-cli-bin ${version} already exists on npm; skipping"
else
npm publish "./$launcher" --access public --tag "${NEMO_RELAY_NPM_DIST_TAG}"
fi

- name: Publish OpenClaw plugin package to npm
run: |
set -euo pipefail
Expand Down
75 changes: 51 additions & 24 deletions .github/workflows/ci_rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,28 @@ jobs:
cache-bin: false
save-if: false

- uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: ${{ steps.ci-config.outputs.uv_version }}

- uses: taiki-e/install-action@c070f87102a1c75b3183910f391c1cb887fe13c8 # v2.77.6
with:
tool: just@${{ steps.ci-config.outputs.just_version }}

- name: Set CLI binary version
working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }}
env:
REF_NAME: ${{ github.ref_name }}
REF_TYPE: ${{ github.ref_type }}
run: |
set -euo pipefail
version="$REF_NAME"
if [[ "$REF_TYPE" != "tag" ]]; then
version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)+${GIT_COMMIT::8}"
fi
just set-cargo-version "$version"
printf 'NEMO_RELAY_CLI_PACKAGE_VERSION=%s\n' "$version" >> "$GITHUB_ENV"

- name: Install musl tools
if: ${{ startsWith(matrix.target, 'x86_64-unknown-linux-musl') || startsWith(matrix.target, 'aarch64-unknown-linux-musl') }}
run: |
Expand Down Expand Up @@ -300,8 +322,17 @@ jobs:
docker run --rm \
--volume "${{ env.NEMO_RELAY_CI_WORKSPACE }}:${{ env.NEMO_RELAY_CI_WORKSPACE }}" \
--workdir "${{ env.NEMO_RELAY_CI_WORKSPACE }}" \
--env NEMO_RELAY_CI_WORKSPACE \
--env NEMO_RELAY_CLI_PACKAGE_VERSION \
"${{ matrix.runtime_image }}" \
"${{ env.NEMO_RELAY_CI_WORKSPACE }}/target/${{ matrix.target }}/release/nemo-relay" --version
/bin/sh -ec '
actual="$("$NEMO_RELAY_CI_WORKSPACE/target/${{ matrix.target }}/release/nemo-relay" --version)"
expected="nemo-relay $NEMO_RELAY_CLI_PACKAGE_VERSION"
if [ "$actual" != "$expected" ]; then
echo "Error: expected CLI version \"$expected\", got \"$actual\"" >&2
exit 1
fi
'

- name: Stage CLI binary artifact
working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }}
Expand All @@ -327,7 +358,7 @@ jobs:
mkdir -p "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli"
cp "$source" "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli/${asset}"

- name: Package CLI binary for PyPI and npm
- name: Package CLI binary for PyPI
working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }}
run: |
set -euo pipefail
Expand All @@ -337,22 +368,14 @@ jobs:
binary="${binary}.exe"
fi
source="${NEMO_RELAY_CI_WORKSPACE}/target/${target}/release/${binary}"
version="${{ github.ref_name }}"
if [ "${{ github.ref_type }}" != "tag" ]; then
version="$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)+${GIT_COMMIT::8}"
fi
version="$NEMO_RELAY_CLI_PACKAGE_VERSION"
rm -rf "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-packages"
mkdir -p "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-packages"
args=(
--binary "$source"
--target "$target"
--version "$version"
python scripts/package-cli-bin.py \
--binary "$source" \
--target "$target" \
--version "$version" \
--output-dir "${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-packages"
)
if [ "${{ matrix.platform }}" = "linux-amd64" ]; then
args+=(--npm-launcher)
fi
python scripts/package-cli-bin.py "${args[@]}"

- name: Install and run CLI wheel
if: ${{ !endsWith(matrix.target, '-musl') }}
Expand All @@ -369,7 +392,12 @@ jobs:
venv_cli="${NEMO_RELAY_CI_WORKSPACE_TMP}/cli-wheel-venv/bin/nemo-relay"
fi
"$venv_python" -m pip install --force-reinstall --no-deps "${wheels[0]}"
"$venv_cli" --version
actual="$("$venv_cli" --version)"
expected="nemo-relay $NEMO_RELAY_CLI_PACKAGE_VERSION"
if [[ "$actual" != "$expected" ]]; then
echo "Error: expected CLI version '$expected', got '$actual'" >&2
exit 1
fi

- name: Install and run CLI wheel on musllinux
if: ${{ endsWith(matrix.target, '-musl') }}
Expand All @@ -380,13 +408,19 @@ jobs:
--volume "${{ env.NEMO_RELAY_CI_WORKSPACE }}:${{ env.NEMO_RELAY_CI_WORKSPACE }}" \
--workdir "${{ env.NEMO_RELAY_CI_WORKSPACE }}" \
--env NEMO_RELAY_CI_WORKSPACE_TMP \
--env NEMO_RELAY_CLI_PACKAGE_VERSION \
"${{ matrix.runtime_image }}" \
/bin/sh -ec '
wheel="$(find "$NEMO_RELAY_CI_WORKSPACE_TMP/cli-packages" -maxdepth 1 -name "*.whl" -print -quit)"
test -n "$wheel"
/opt/python/cp311-cp311/bin/python -m venv /tmp/nemo-relay-cli-wheel-venv
/tmp/nemo-relay-cli-wheel-venv/bin/python -m pip install --force-reinstall --no-deps "$wheel"
/tmp/nemo-relay-cli-wheel-venv/bin/nemo-relay --version
actual="$(/tmp/nemo-relay-cli-wheel-venv/bin/nemo-relay --version)"
expected="nemo-relay $NEMO_RELAY_CLI_PACKAGE_VERSION"
if [ "$actual" != "$expected" ]; then
echo "Error: expected CLI version \"$expected\", got \"$actual\"" >&2
exit 1
fi
'

- name: Upload CLI binary artifact
Expand All @@ -402,10 +436,3 @@ jobs:
name: cli-python-wheel-${{ matrix.platform }}
path: ${{ env.NEMO_RELAY_CI_WORKSPACE_TMP }}/cli-packages/*.whl
if-no-files-found: error

- name: Upload CLI npm artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: cli-npm-package-${{ matrix.platform }}
path: ${{ env.NEMO_RELAY_CI_WORKSPACE_TMP }}/cli-packages/*.tgz
if-no-files-found: error
14 changes: 1 addition & 13 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ collect:github-artifacts:
fi
export GH_TOKEN="${NEMO_RELAY_CI_GITHUB_TOKEN}"

mkdir -p collected/wheels collected/sdists collected/node collected/cli-npm downloaded
mkdir -p collected/wheels collected/sdists collected/node downloaded

tag="${CI_COMMIT_TAG:-}"
if [ -z "$tag" ]; then
Expand Down Expand Up @@ -133,15 +133,13 @@ collect:github-artifacts:

gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'wheel-*' --dir downloaded/wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'cli-python-wheel-*' --dir downloaded/cli-wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'cli-npm-package-*' --dir downloaded/cli-npm
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --name 'plugin-wheel' --dir downloaded/wheels
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --name 'python-sdist' --dir downloaded/sdists
gh run download "$run_id" --repo "$NEMO_RELAY_CI_GITHUB_REPOSITORY" --pattern 'node-npm-package-*' --dir downloaded/node

find downloaded/wheels -type f -name '*.whl' -exec cp {} collected/wheels/ \;
find downloaded/cli-wheels -type f -name '*.whl' -exec cp {} collected/wheels/ \;
find downloaded/sdists -type f -name 'nemo_relay-*.tar.gz' -exec cp {} collected/sdists/ \;
find downloaded/cli-npm -type f -name '*.tgz' -exec cp {} collected/cli-npm/ \;
find downloaded/node -type f -name '*.tgz' -exec cp {} collected/node/ \;

if ! ls collected/wheels/*.whl >/dev/null 2>&1; then
Expand All @@ -156,10 +154,6 @@ collect:github-artifacts:
echo "Error: collected GitHub Node artifacts did not contain any .tgz files." >&2
exit 1
fi
if ! ls collected/cli-npm/*.tgz >/dev/null 2>&1; then
echo "Error: collected GitHub CLI npm artifacts did not contain any .tgz files." >&2
exit 1
fi

{
printf '{\n'
Expand All @@ -177,7 +171,6 @@ collect:github-artifacts:
- collected/wheels/*.whl
- collected/sdists/nemo_relay-*.tar.gz
- collected/node/*.tgz
- collected/cli-npm/*.tgz
- collected/github-run.json

publish:artifactory:wheels:
Expand Down Expand Up @@ -337,8 +330,3 @@ publish:artifactory:npm:
npm publish --tag dev "$package"
done
npm publish --tag dev "collected/node/nemo-relay-node-npm-${CI_COMMIT_TAG}.tgz"
for platform in linux-x64 linux-arm64 linux-x64-musl linux-arm64-musl darwin-arm64 win32-x64 win32-arm64; do
package="collected/cli-npm/nemo-relay-bin-npm-${platform}-${CI_COMMIT_TAG}.tgz"
npm publish --tag dev "$package"
done
npm publish --tag dev "collected/cli-npm/nemo-relay-bin-npm-${CI_COMMIT_TAG}.tgz"
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,6 @@ Install the prebuilt CLI from PyPI:
pip install nemo-relay-cli-bin
```

Install the prebuilt CLI from npm:

```bash
npm install --global nemo-relay-cli-bin
```

Python API users can install the matching CLI through the optional extra:

```bash
Expand Down
41 changes: 17 additions & 24 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ The release pipeline publishes these package surfaces from a tag push:
|---|---|
| crates.io | `nemo-relay-types`, `nemo-relay-plugin`, `nemo-relay-worker-proto`, `nemo-relay-worker`, `nemo-relay`, `nemo-relay-adaptive`, `nemo-relay-pii-redaction`, `nemo-relay-switchyard`, `nemo-relay-ffi`, `nemo-relay-cli` |
| PyPI | `nemo-relay` wheels and source distribution, `nemo-relay-plugin` and `nemo-relay-cli-bin` wheels |
| npm | `nemo-relay-node` and its seven platform packages, `nemo-relay-openclaw`, `nemo-relay-cli-bin`, and its seven platform packages |
| GitHub Releases | CLI binaries, `nemo-relay` and `nemo-relay-cli-bin` wheels, CLI and Node npm tarballs, and checksums |
| npm | `nemo-relay-node` and its seven platform packages, and `nemo-relay-openclaw` |
| GitHub Releases | CLI binaries, `nemo-relay` and `nemo-relay-cli-bin` wheels, Node npm tarballs, and checksums |
| Fern | The documentation site |

Go remains source-first. There is no separate Go package-manager publication
step in the repository release workflow.

The former npm `nemo-relay-cli-bin` metapackage and its seven platform
packages are retired and must not be republished.

The mirrored GitLab pipeline also publishes the same tag's collected package
artifacts to NVIDIA Artifactory. It is driven by the tag push, not by a GitLab
pipeline schedule.
Expand All @@ -61,9 +64,8 @@ NeMo Relay versions are anchored on the workspace SemVer in the repository root
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.
- `packages/cli-bin/package.json` and `python/cli-bin/pyproject.toml` carry the
base CLI package versions in their registry-specific SemVer and PEP 440
spellings. The `nemo-relay[cli]` extra must pin the exact PyPI version.
- `python/cli-bin/pyproject.toml` carries the base CLI package version in its
PEP 440 spelling. The `nemo-relay[cli]` extra must pin the exact PyPI 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 Down Expand Up @@ -151,11 +153,6 @@ Before you create a release tag, confirm the following:
`nemo-relay-node-linux-x64-musl`, `nemo-relay-node-linux-arm64-musl`,
`nemo-relay-node-darwin-arm64`, `nemo-relay-node-win32-x64-msvc`, and
`nemo-relay-node-win32-arm64-msvc`
- npm trusted publishers are configured for `nemo-relay-cli-bin` and
`nemo-relay-cli-bin-linux-x64`, `nemo-relay-cli-bin-linux-arm64`,
`nemo-relay-cli-bin-linux-x64-musl`, `nemo-relay-cli-bin-linux-arm64-musl`,
`nemo-relay-cli-bin-darwin-arm64`, `nemo-relay-cli-bin-win32-x64`, and
`nemo-relay-cli-bin-win32-arm64`
5. The GitHub Release entry is ready to become the only canonical release-notes
surface.

Expand All @@ -182,7 +179,7 @@ The helper updates:
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.
5. The Python and npm `nemo-relay-cli-bin` metadata, including the exact
5. The Python `nemo-relay-cli-bin` metadata, including the exact
`nemo-relay[cli]` dependency version.
Review docs and snippets that mention explicit versions, including:

Expand Down Expand Up @@ -268,18 +265,15 @@ The release pipeline then:
- `package-python-plugin` builds the `nemo-relay-plugin` wheel.
- The Rust CLI matrix builds GNU Linux binaries in manylinux containers and
musl Linux binaries natively, validates each in its matching container, and
packages each prebuilt binary as a
`nemo-relay-cli-bin` wheel and npm platform package, and creates the npm
launcher package once.
packages each prebuilt binary as a `nemo-relay-cli-bin` wheel.
- The distribution release-asset job uploads the CLI binaries, `nemo-relay`
API wheels, CLI wheels, CLI npm packages, and split Node npm packages.
API wheels, CLI wheels, and split Node npm packages.
`SHA256SUMS` covers every attached distribution artifact, and raw CLI
binaries also receive individual `.sha256` files for installer
compatibility.
GitHub-facing npm artifacts use
`nemo-relay-bin-npm[-<os>-<cpu>]-<version>.tgz` for the CLI and
`nemo-relay-node-npm[-<os>-<cpu>]-<version>.tgz` for Node.js; their
registry package names remain in the tarball manifests.
`nemo-relay-node-npm[-<os>-<cpu>]-<version>.tgz`; their registry package
names remain in the tarball manifests.
4. Publishes packages from the top-level workflow after the reusable packaging
jobs complete:
- `publish-rust` stamps Cargo workspace versions from the release tag, then
Expand All @@ -293,8 +287,8 @@ The release pipeline then:
artifacts plus the `nemo-relay-plugin` and `nemo-relay-cli-bin` wheels,
then uploads them to PyPI with trusted publishing from the top-level
workflow
- `publish-npm` publishes the Node.js and CLI native packages before their
metapackages, then publishes the OpenClaw package, through npm trusted
- `publish-npm` publishes the Node.js native packages before their
metapackage, then publishes the OpenClaw package, 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`
Expand Down Expand Up @@ -329,8 +323,7 @@ npm trusted publishing has its own registry-side constraints:

- Each npm package can only have one trusted publisher configured at a time.
- Configure trusted publishers for `nemo-relay-node`, all seven Node platform
packages, `nemo-relay-openclaw`, `nemo-relay-cli-bin`, and all seven CLI
platform packages before pushing a release tag.
packages, and `nemo-relay-openclaw` before pushing a release tag.
- npm trusted publishing currently supports GitHub-hosted runners, not
self-hosted runners.

Expand Down Expand Up @@ -363,8 +356,8 @@ After the release is live, verify:
are visible on crates.io.
2. The `nemo-relay` and `nemo-relay-cli-bin` wheels are visible on PyPI, and
`pip install "nemo-relay[cli]"` exposes `nemo-relay`.
3. The `nemo-relay-node`, its seven platform packages, `nemo-relay-openclaw`,
`nemo-relay-cli-bin`, and its seven platform packages are visible on npm.
3. The `nemo-relay-node`, its seven platform packages, and
`nemo-relay-openclaw` are visible on npm.
4. The Unix and Windows installers resolve the new stable tag and verify
matching CLI release asset checksums on their supported platforms.
5. The Fern documentation site shows the expected version and release notes.
Expand Down
6 changes: 0 additions & 6 deletions crates/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,6 @@ Install the prebuilt CLI from PyPI:
pip install nemo-relay-cli-bin
```

Install the prebuilt CLI from npm:

```bash
npm install --global nemo-relay-cli-bin
```

Install the Python API and matching CLI with the optional extra:

```bash
Expand Down
Loading
Loading