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: 4 additions & 0 deletions .github/scripts/smoke_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ set -euo pipefail

bin_dir=${1:?usage: smoke_test.sh <venv-bin-dir>}
holoscan="$bin_dir/holoscan"
holoscan_cli="$bin_dir/holoscan-cli"
python="$bin_dir/python"

"$holoscan" --help
"$holoscan" version
"$holoscan" lint --dryrun
"$holoscan_cli" --help
diff -u <("$holoscan" version | sed '/^Executable:/d') \
<("$holoscan_cli" version | sed '/^Executable:/d')

# Every registered command must surface working `--help`. Pull the list
# from the registry so this cannot drift if a subcommand is renamed.
Expand Down
46 changes: 46 additions & 0 deletions .github/scripts/tool_runner_smoke.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Verify that package-name based tool runners can execute holoscan-cli
# directly from the wheel built by this workflow.
#
# Usage: tool_runner_smoke.sh <wheel-dir-or-wheel-path>
set -euo pipefail

wheel_input=${1:-dist}
if [[ -d "$wheel_input" ]]; then
wheel=$(find "$wheel_input" -name 'holoscan_cli-*.whl' | head -n1)
else
wheel="$wheel_input"
fi

if [[ -z "${wheel:-}" || ! -f "$wheel" ]]; then
echo "no holoscan_cli-*.whl found at $wheel_input" >&2
exit 1
fi

if ! command -v uvx >/dev/null; then
echo "uvx is required for tool-runner smoke tests" >&2
exit 1
fi
if ! command -v pipx >/dev/null; then
echo "pipx is required for tool-runner smoke tests" >&2
exit 1
fi

wheel=$(python -c 'from pathlib import Path; import sys; print(Path(sys.argv[1]).resolve())' "$wheel")
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' EXIT

export UV_TOOL_DIR="$tmp_dir/uv/tools"
export UV_CACHE_DIR="$tmp_dir/uv/cache"
export PIPX_HOME="$tmp_dir/pipx/home"
export PIPX_BIN_DIR="$tmp_dir/pipx/bin"
mkdir -p "$UV_TOOL_DIR" "$UV_CACHE_DIR" "$PIPX_HOME" "$PIPX_BIN_DIR"

echo "--- uvx --from $wheel holoscan-cli version"
uvx --from "$wheel" holoscan-cli version

echo "--- pipx run --spec $wheel holoscan-cli version"
pipx run --spec "$wheel" holoscan-cli version
6 changes: 6 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ jobs:
- name: Smoke test
run: .github/scripts/smoke_test.sh /tmp/holoscan-cli-smoke/bin

- name: Install tool runners
run: python -m pip install --upgrade uv pipx

- name: Tool-runner smoke test
run: .github/scripts/tool_runner_smoke.sh dist

cpu-cli-docker-smoke:
name: CPU CLI + Docker smoke test
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,10 @@ jobs:
/tmp/holoscan-cli-smoke/bin/pip install "${wheel}"
- name: Smoke Test
run: .github/scripts/smoke_test.sh /tmp/holoscan-cli-smoke/bin
- name: Install tool runners
run: python -m pip install --upgrade uv pipx
- name: Tool-runner smoke test
run: .github/scripts/tool_runner_smoke.sh dist
Comment thread
wyli marked this conversation as resolved.

testpypi-deploy:
name: publish-test-pypi
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ pip install holoscan-cli
holoscan --help
```

For transient use without keeping an installed environment, package-name based
Comment thread
jcfr marked this conversation as resolved.
tool runners can use the compatibility alias:

```bash
uvx holoscan-cli --help
pipx run holoscan-cli --help
```

The primary CLI command remains `holoscan`. Explicit package/command forms also
work when you want the canonical command name from a transient runner:

```bash
uvx --from holoscan-cli holoscan --help
pipx run --spec holoscan-cli holoscan --help
```

## Versioning

`holoscan-cli` release versions are aligned with Holoscan SDK GA release
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ poetry-dynamic-versioning = { version = ">=1.5.0,<2.0.0", extras = ["plugin"] }

[project.scripts]
holoscan = 'holoscan_cli.__main__:main'
holoscan-cli = 'holoscan_cli.__main__:main'

[tool.codespell]
skip = '.ruff_cache,.cache,build,dist,htmlcov,tests/reports'
Expand Down
13 changes: 8 additions & 5 deletions tests/unit/test_package_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
files an installed ``holoscan-cli`` wheel must ship: the ``py.typed``
marker, the project metadata JSON schemas under ``holoscan_cli.metadata``,
the logging configuration, and the CTest scripts under ``holoscan_cli.testing``.
The tests also pin the public ``holoscan`` console script entry point so the
installed package keeps a single, stable command name on disk.
The tests also pin the public ``holoscan`` console script entry point and the
``holoscan-cli`` package-name tool-runner alias.

Entry-point checks read ``pyproject.toml`` directly (the ground truth for
what a fresh ``pip install`` will register) instead of the runtime
Expand Down Expand Up @@ -161,10 +161,13 @@ def test_bundled_template_script_uses_bundled_requirements(tmp_path):
# ---- pyproject.toml entry-point declarations --------------------------------


def test_pyproject_declares_only_holoscan_console_script():
"""The shipped wheel must register exactly one console script."""
def test_pyproject_declares_expected_console_scripts():
"""The shipped wheel must register the canonical CLI and tool-runner alias."""
declared = _pyproject().get("project", {}).get("scripts", {})
assert declared == {"holoscan": "holoscan_cli.__main__:main"}, declared
assert declared == {
"holoscan": "holoscan_cli.__main__:main",
"holoscan-cli": "holoscan_cli.__main__:main",
}, declared


def test_pyproject_does_not_declare_legacy_console_scripts():
Expand Down
Loading