From ba53eb91ea3c4683a3ed579b9fe9f9968c96fce7 Mon Sep 17 00:00:00 2001 From: Jeremy Manning Date: Sat, 1 Aug 2026 10:58:26 -0400 Subject: [PATCH] Add `--version` to the CLI Found by a release rehearsal against the built wheel, not by any test: `orchestrator --version` failed with "No such option. Did you mean '--verbose'?". There was no way to ask an installed copy what version it is, which is the first thing anyone does with a release. Uses click's `package_name` form, which reads the version from installed distribution metadata rather than importing the package. That keeps the CLI hermetic: answering `--version` must not run anything on the credential-discovery path. Both properties are now tested -- the output carries the real version, and a decoy ~/.orchestrator/.env is never read. Verified against the built wheel in a clean venv, through both the `orchestrator` and `py-orc` entry points. Blocking gate 390 -> 392. Co-Authored-By: Claude Opus 5 (1M context) --- src/orchestrator/cli.py | 4 ++++ tests/test_cli_hermetic_and_quiet.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/orchestrator/cli.py b/src/orchestrator/cli.py index 4659e132..c5eee910 100644 --- a/src/orchestrator/cli.py +++ b/src/orchestrator/cli.py @@ -60,6 +60,10 @@ def setup_logging(verbose: bool = False): @click.group() +# `package_name` reads the version from installed distribution metadata, so +# this does not import the package -- the CLI stays hermetic and no +# credential-touching import runs just to answer `--version`. +@click.version_option(package_name="py-orc", prog_name="orchestrator") @click.option("--log-level", type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], case_sensitive=False), diff --git a/tests/test_cli_hermetic_and_quiet.py b/tests/test_cli_hermetic_and_quiet.py index e1387a3a..af1e0632 100644 --- a/tests/test_cli_hermetic_and_quiet.py +++ b/tests/test_cli_hermetic_and_quiet.py @@ -73,6 +73,42 @@ def _run_cli(args, cwd, home): ) +# --------------------------------------------------------------------------- +# 0. the CLI can state its own version +# --------------------------------------------------------------------------- + +def test_cli_reports_its_version(tmp_path): + """`--version` is the first thing anyone runs against a release. + + A release rehearsal against the built wheel found this missing entirely: + `orchestrator --version` failed with "No such option". There is no other + way to ask an installed copy what it is. + """ + import orchestrator + + result = _run_cli(["--version"], tmp_path, _decoy_home(tmp_path)) + + assert result.returncode == 0, f"--version failed: {result.stderr}" + assert orchestrator.__version__ in result.stdout, ( + f"version {orchestrator.__version__!r} missing from {result.stdout!r}" + ) + + +def test_version_does_not_read_credentials(tmp_path): + """Asking the version must not touch the user's provider credentials. + + The version is read from distribution metadata rather than by importing + the package, so nothing on the credential path runs. + """ + home = _decoy_home(tmp_path) + result = _run_cli(["--version"], tmp_path, home) + + assert result.returncode == 0 + combined = result.stdout + result.stderr + assert DECOY_ANTHROPIC not in combined + assert DECOY_OPENAI not in combined + + # --------------------------------------------------------------------------- # 1. hermetic boundary # ---------------------------------------------------------------------------