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
12 changes: 7 additions & 5 deletions docs/usage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ published package:
just pypi-smoke -- --package-spec outfitter-dispatch==0.5.0
```

The smoke installs with `uvx`, uses a temporary `DISPATCH_HOME`, verifies the
derived `models` schema, starts the daemon, reads the live App Server model
catalog, verifies the cached registry read, checks the empty first-run lane list,
and shuts the daemon down.
The smoke installs with `uvx --refresh-package outfitter-dispatch`, uses a
temporary `DISPATCH_HOME`, verifies the derived `models` schema, starts the
daemon, reads the live App Server model catalog, verifies the cached registry
read, checks the empty first-run lane list, and shuts the daemon down.

For an agent-level live scenario against the in-tree CLI, run:

Expand Down Expand Up @@ -178,7 +178,9 @@ just check
```

After the GitHub Release publishes to PyPI, run `just pypi-smoke -- --package-spec
outfitter-dispatch==<version>` to verify the public install path.
outfitter-dispatch==<version>` to verify the public install path. The smoke
refreshes the package under test in uv's cache, so an immediate post-publish
check does not reuse an early "version not found" resolver result.

Then create and publish a GitHub Release for the same tag, for example
`v0.1.0`. Do not upload with a long-lived PyPI token unless the trusted
Expand Down
23 changes: 21 additions & 2 deletions scripts/check_pypi_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ def main(argv: list[str] | None = None) -> int:
_expect(models.get("source") == "app-server", models)
_expect(_nonempty_list(models.get("models")), models)
configured = models.get("configured_default")
_expect(isinstance(configured, dict), models)
if not isinstance(configured, dict):
_expect(False, models)
raise AssertionError("unreachable")
_expect(isinstance(configured.get("model"), str), models)

cached = _dispatch_json(
Expand Down Expand Up @@ -105,8 +107,17 @@ def _dispatch(
timeout: float = 90.0,
check: bool = True,
) -> subprocess.CompletedProcess[str]:
package_name = _package_name(package_spec)
result = subprocess.run(
["uvx", "--from", package_spec, "dispatch", *args],
[
"uvx",
"--refresh-package",
package_name,
"--from",
package_spec,
"dispatch",
*args,
],
env=env,
text=True,
capture_output=True,
Expand All @@ -121,6 +132,14 @@ def _dispatch(
return result


def _package_name(package_spec: str) -> str:
spec = package_spec.strip()
for separator in ("[", " @ ", "===", "==", "~=", "!=", ">=", "<=", ">", "<"):
if separator in spec:
return spec.split(separator, 1)[0].strip()
return spec


def _dispatch_json(
package_spec: str,
args: list[str],
Expand Down
51 changes: 51 additions & 0 deletions tests/test_pypi_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Tests for the published-package smoke helper."""

from __future__ import annotations

import subprocess
from pathlib import Path

import pytest
from scripts import check_pypi_smoke


def test_package_name_from_package_spec() -> None:
assert check_pypi_smoke._package_name("outfitter-dispatch==0.8.0") == "outfitter-dispatch"
assert check_pypi_smoke._package_name("outfitter-dispatch[dev]>=0.8") == "outfitter-dispatch"
assert (
check_pypi_smoke._package_name(
"outfitter-dispatch @ https://example.test/outfitter-dispatch.whl"
)
== "outfitter-dispatch"
)


def test_dispatch_refreshes_target_package_cache(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
calls: list[list[str]] = []

def fake_run(cmd: list[str], **_kwargs: object) -> subprocess.CompletedProcess[str]:
calls.append(cmd)
return subprocess.CompletedProcess(cmd, 0, stdout="dispatch 0.8.0\n", stderr="")

monkeypatch.setattr(subprocess, "run", fake_run)

result = check_pypi_smoke._dispatch(
"outfitter-dispatch==0.8.0",
["--version"],
{"DISPATCH_HOME": str(tmp_path)},
)

assert result.stdout == "dispatch 0.8.0\n"
assert calls == [
[
"uvx",
"--refresh-package",
"outfitter-dispatch",
"--from",
"outfitter-dispatch==0.8.0",
"dispatch",
"--version",
]
]