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
26 changes: 26 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,32 @@ jobs:
merge-multiple: true
path: dist/

- name: Download Python source distribution artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: python-sdist
path: dist/

- name: Verify Python API wheel artifacts
run: |
set -euo pipefail
shopt -s nullglob
wheels=(dist/nemo_relay-*.whl)
if [ "${#wheels[@]}" -ne 7 ]; then
echo "Error: expected 7 Python API wheel artifacts, found ${#wheels[@]}" >&2
exit 1
fi

- name: Verify Python source distribution artifact
run: |
set -euo pipefail
shopt -s nullglob
sdists=(dist/nemo_relay-*.tar.gz)
if [ "${#sdists[@]}" -ne 1 ]; then
echo "Error: expected one Python API source distribution artifact, found ${#sdists[@]}" >&2
exit 1
fi

- name: Publish to PyPI with trusted publishing
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
with:
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/ci_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,24 @@ jobs:
path: ${{ env.NEMO_RELAY_CI_WORKSPACE_TMP }}/wheels/*.whl
if-no-files-found: error

- name: Package Python source distribution
if: ${{ matrix.platform == 'linux-amd64' }}
working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }}
run: |
set -e
just \
--set output_dir "${{ env.NEMO_RELAY_CI_WORKSPACE_TMP }}" \
--set ref_name "${NEMO_RELAY_PACKAGE_VERSION}" \
package-python-sdist

- name: Upload Python source distribution artifact
if: ${{ matrix.platform == 'linux-amd64' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: python-sdist
path: ${{ env.NEMO_RELAY_CI_WORKSPACE_TMP }}/sdists/nemo_relay-*.tar.gz
if-no-files-found: error

- name: Package Python plugin SDK wheel
if: ${{ matrix.platform == 'linux-amd64' }}
working-directory: ${{ env.NEMO_RELAY_CI_WORKSPACE }}
Expand Down
17 changes: 12 additions & 5 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/node collected/cli-npm downloaded
mkdir -p collected/wheels collected/sdists collected/node collected/cli-npm downloaded

tag="${CI_COMMIT_TAG:-}"
if [ -z "$tag" ]; then
Expand Down Expand Up @@ -135,17 +135,23 @@ collect:github-artifacts:
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
echo "Error: collected GitHub wheel artifacts did not contain any .whl files." >&2
exit 1
fi
if ! ls collected/sdists/nemo_relay-*.tar.gz >/dev/null 2>&1; then
echo "Error: collected GitHub Python source distribution artifact did not contain a nemo-relay sdist." >&2
exit 1
fi
if ! ls collected/node/*.tgz >/dev/null 2>&1; then
echo "Error: collected GitHub Node artifacts did not contain any .tgz files." >&2
exit 1
Expand All @@ -169,6 +175,7 @@ collect:github-artifacts:
expire_in: 7 days
paths:
- collected/wheels/*.whl
- collected/sdists/nemo_relay-*.tar.gz
- collected/node/*.tgz
- collected/cli-npm/*.tgz
- collected/github-run.json
Expand All @@ -189,18 +196,18 @@ publish:artifactory:wheels:
set -eu

if [ -z "${NEMO_RELAY_CI_ARTIFACTORY_USER:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_KEY:-}" ] || [ -z "${NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL:-}" ]; then
echo "Error: uploading wheels to Artifactory requires NEMO_RELAY_CI_ARTIFACTORY_USER, NEMO_RELAY_CI_ARTIFACTORY_KEY, and NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL." >&2
echo "Error: uploading Python package artifacts to Artifactory requires NEMO_RELAY_CI_ARTIFACTORY_USER, NEMO_RELAY_CI_ARTIFACTORY_KEY, and NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL." >&2
exit 1
fi
if ! ls collected/wheels/*.whl >/dev/null 2>&1; then
echo "Error: no collected wheel artifacts found." >&2
if ! ls collected/wheels/*.whl >/dev/null 2>&1 || ! ls collected/sdists/nemo_relay-*.tar.gz >/dev/null 2>&1; then
echo "Error: no complete set of collected Python package artifacts found." >&2
exit 1
fi

UV_PUBLISH_USERNAME="${NEMO_RELAY_CI_ARTIFACTORY_USER}" \
UV_PUBLISH_PASSWORD="${NEMO_RELAY_CI_ARTIFACTORY_KEY}" \
UV_PUBLISH_URL="${NEMO_RELAY_CI_ARTIFACTORY_PYPI_URL}" \
uv publish --no-progress collected/wheels/*.whl
uv publish --no-progress collected/wheels/*.whl collected/sdists/nemo_relay-*.tar.gz

publish:artifactory:cargo:
stage: publish
Expand Down
16 changes: 10 additions & 6 deletions RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ The release pipeline publishes these package surfaces from a tag push:
| Ecosystem | Published Surface |
|---|---|
| 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`, `nemo-relay-plugin`, `nemo-relay-cli-bin` |
| 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 |
| Fern | The documentation site |
Expand Down Expand Up @@ -216,6 +216,7 @@ just --set output_dir "$PWD/target/release-artifacts" --set ref_name 0.1.0 packa
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-rust
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-python-sdist
```

Be aware that the local packaging recipes intentionally rewrite version fields
Expand Down Expand Up @@ -262,6 +263,8 @@ The release pipeline then:
- `package-openclaw` packs the npm OpenClaw plugin package.
- `package-python` builds platform `nemo-relay` wheels, including
`musllinux_1_2_x86_64` and `musllinux_1_2_aarch64` wheels.
- `package-python-sdist` builds one platform-independent `nemo-relay` source
distribution.
- `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
Expand All @@ -286,9 +289,10 @@ The release pipeline then:
`nemo-relay-switchyard`, `nemo-relay-ffi`, and `nemo-relay-cli` through
trusted publishing from
the top-level workflow
- `publish-python` downloads the `nemo-relay`, `nemo-relay-plugin`, and
`nemo-relay-cli-bin` wheel artifacts and uploads them to PyPI with trusted
publishing from the top-level workflow
- `publish-python` downloads the `nemo-relay` wheel and source distribution
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
publishing from the top-level workflow
Expand Down Expand Up @@ -316,8 +320,8 @@ NVIDIA Artifactory publication for the same tag:
- GitLab starts the pipeline from a tag push through `CI_COMMIT_TAG`; no GitLab
cron or pipeline schedule is required.
- The collector waits for the mirrored GitHub tag and matching GitHub Actions
run, then downloads the wheel, Cargo, and Node.js package
artifacts produced by GitHub Actions.
run, then downloads the Python wheel and source distribution, Cargo, and
Node.js package artifacts produced by GitHub Actions.
- The Artifactory jobs publish those collected artifacts to the configured
Python, Cargo, and npm Artifactory registries.

Expand Down
28 changes: 28 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -1704,6 +1704,34 @@ package-python:
exit 1
fi

# --set [output_dir=<path>] [ref_name=<name>]
package-python-sdist:
#!/usr/bin/env bash
{{ bash_helpers }}
output_dir="{{ output_dir }}"
export_uv_python_runtime
cd "$NEMO_RELAY_REPO_ROOT"
package_dir="$(prepare_package_dir sdists)"
sync_args=(--no-install-project --no-install-package nemo-relay)
uv sync --inexact "${sync_args[@]}"
activate_project_venv
if [[ -z "{{ ref_name }}" ]]; then
sha="$(head_git_sha)"
version="$(read_workspace_version)"
echo "Non-release build: appending commit hash to version"
set_python_package_version "${version}+${sha}" true
else
echo "Using explicit version {{ ref_name }}"
set_python_package_version "{{ ref_name }}" true
fi
maturin sdist --out "$package_dir"
shopt -s nullglob
sdists=("$package_dir"/nemo_relay-*.tar.gz)
if ((${#sdists[@]} == 0)); then
echo "Error: No nemo-relay source distributions found in $package_dir"
exit 1
fi

# --set [output_dir=<path>] [ref_name=<name>]
package-python-plugin:
#!/usr/bin/env bash
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ manifest-path = "crates/python/Cargo.toml"
python-source = "python"
module-name = "nemo_relay._native"
features = ["pyo3/extension-module"]
include = [{ path = "LICENSE", format = ["sdist", "wheel"] }]

[tool.maturin.sbom]
rust = true
Expand Down
Loading