Run unsloth_cli/tests in Backend CI (#7598)

unsloth_cli/tests had no CI at all. unsloth_cli/** was a paths trigger and a
ruff target, so the Backend CI job already fired on CLI changes but never ran
these 673 tests, which cover the studio launcher, the pre-exposure gate and the
auth secret writers. Four had been failing on main unnoticed.

Two were stale rather than broken code:

- test_studio_default_exposes_parallel_option pinned the plain --parallel
  default to 1, but #7455 deliberately moved _PARALLEL_DEFAULT_PLAIN to 4 so a
  new chat does not queue behind the previous one. Assert against the constant
  so the two cannot drift again.
- test_reexec_forwards_api_only expected --secure --api-only to re-exec. The
  pre-exposure gate now refuses that combination, because api-only serves no
  login page and the bootstrap deadline does not apply, so a seeded password
  could never be changed. Drop the case and assert the refusal instead.

Two only passed when a built frontend dist happened to be present, which it is
not in a fresh clone or on a runner. Both reach a public-launch path where the
missing-dist gate exits first, so they never got to the backend check and the
run_server call they are about. Stub _find_frontend_dist the way their siblings
already do.

Own step rather than folding into the tests/ discovery: pyproject's testpaths is
tests/, and this suite needs no PYTHONPATH or CUDA spoof, importing neither
unsloth nor torch. Its deps are already installed by the job (pydantic and
uvicorn, which brings click, via studio.txt; pyyaml explicitly).
This commit is contained in:
Daniel Han 2026-07-29 01:15:06 -07:00 committed by GitHub
commit 0ed26297ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 40 additions and 3 deletions

View file

@ -626,6 +626,12 @@ def test_studio_default_in_venv_broken_backend_exits_before_stripping_bootstrap(
# Pretend we are already inside the studio venv, with a broken backend.
monkeypatch.setattr(sys, "prefix", str(tmp_path / "unsloth_studio"))
# A built dist is not present in a fresh clone. The missing-frontend gate
# runs first and has its own test below; stub it so this one reaches the
# backend check it is actually about.
monkeypatch.setattr(
studio_mod, "_find_frontend_dist", lambda: Path("/fake/studio/frontend/dist")
)
def _boom():
raise ImportError("cannot import backend run.py")

View file

@ -606,8 +606,8 @@ def test_studio_default_exposes_parallel_option():
assert "--parallel" in decls
assert "--n-parallel" in decls
assert (
getattr(opt, "default", None) == 1
), "studio_default --parallel must default to 1 (pre-PR); `run` is 4"
getattr(opt, "default", None) == studio_mod._PARALLEL_DEFAULT_PLAIN
), "studio_default --parallel must use _PARALLEL_DEFAULT_PLAIN"
assert getattr(opt, "min", None) == 1
assert getattr(opt, "max", None) == 64
@ -679,7 +679,6 @@ def test_api_only_option_is_registered():
"extra,present",
[
(["--api-only"], True),
(["--secure", "--api-only"], True), # secure headless path
([], False),
],
)
@ -691,6 +690,21 @@ def test_reexec_forwards_api_only(monkeypatch, extra, present):
assert ("--api-only" in argv) is present, argv
def test_secure_api_only_is_refused_before_any_reexec(monkeypatch, tmp_path):
"""`--secure --api-only` used to re-exec; the pre-exposure gate now refuses
it, because api-only has no login page and the bootstrap deadline does not
apply, so the seeded password could never be changed."""
studio_mod = _load_run_command()
monkeypatch.setattr(studio_mod, "STUDIO_HOME", tmp_path)
result, captured = _invoke_run(monkeypatch, _BASE + ["--secure", "--api-only"])
assert captured == [], captured
assert result.exit_code != 0
combined = (result.output or "") + (getattr(result, "stderr", "") or "")
assert "default admin password was never changed" in combined.lower()
@pytest.mark.parametrize("extra,expected", [(["--api-only"], True), ([], False)])
def test_in_venv_path_passes_api_only_to_run_server(monkeypatch, extra, expected):
"""In-venv path must forward --api-only to run_server(api_only=...)."""

View file

@ -261,6 +261,11 @@ def test_run_in_venv_passes_secure_and_forces_host(monkeypatch, tmp_path):
fake_venv = tmp_path / "unsloth_studio"
monkeypatch.setattr(sys, "prefix", str(fake_venv))
# A built dist is not present in a fresh clone, and without it the public
# launch gate exits before run_server is ever reached.
monkeypatch.setattr(
studio_mod, "_find_frontend_dist", lambda: Path("/fake/studio/frontend/dist")
)
from unsloth_cli import _tool_policy as _tp_mod