527 lines
20 KiB
Python
527 lines
20 KiB
Python
"""Tests for the ``omni upgrade`` command (omnigent.cli.upgrade)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from click.testing import CliRunner
|
|
|
|
from omnigent.cli import cli
|
|
from omnigent.host.local_server import LocalServerInfo
|
|
from omnigent.update_check import _InstalledWheelInfo
|
|
|
|
|
|
def _uv_registry_info() -> _InstalledWheelInfo:
|
|
"""A registry uv-tool install → ``uv tool upgrade omnigent`` (runnable)."""
|
|
return _InstalledWheelInfo(
|
|
install_time_epoch=0.0,
|
|
installer="uv",
|
|
vcs_url=None,
|
|
commit_sha=None,
|
|
is_editable=False,
|
|
package_version="0.1.0",
|
|
detected_installer="uv",
|
|
)
|
|
|
|
|
|
def _git_install_info() -> _InstalledWheelInfo:
|
|
"""A git/VCS uv-tool install → ``uv tool install --reinstall git+…``."""
|
|
return _InstalledWheelInfo(
|
|
install_time_epoch=0.0,
|
|
installer="uv",
|
|
vcs_url="git+https://github.com/omnigent-ai/omnigent.git",
|
|
commit_sha="a" * 40,
|
|
is_editable=False,
|
|
package_version="0.1.0",
|
|
detected_installer="uv",
|
|
)
|
|
|
|
|
|
@pytest.fixture
|
|
def _wheel_install(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
"""Make the running interpreter look like a registry uv-tool install.
|
|
|
|
Pins the resolved versions and stubs the install-shape detectors so
|
|
every upgrade test starts from "installed v0.1.0 via uv, not a clone".
|
|
The PyPI lookup and the server-stop side effects are stubbed per test.
|
|
"""
|
|
import importlib.metadata
|
|
|
|
monkeypatch.setattr(importlib.metadata, "version", lambda _name: "0.1.0")
|
|
monkeypatch.setattr("omnigent.update_check._find_repo_root", lambda: None)
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _uv_registry_info)
|
|
# Neutralize the process side effects unless a test opts in to assert them.
|
|
monkeypatch.setattr(
|
|
"omnigent.cli.local_server_status",
|
|
lambda: LocalServerInfo(running=False, pid=None, port=None, url=None),
|
|
)
|
|
monkeypatch.setattr("omnigent.cli._stop_local_server_and_daemon", lambda *, force: False)
|
|
|
|
|
|
def test_upgrade_up_to_date(monkeypatch: pytest.MonkeyPatch, _wheel_install: None) -> None:
|
|
"""Latest == installed → reports up to date, exit 0, nothing stopped/run."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.1.0")
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("upgrade command ran while already up to date")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "up to date" in result.output
|
|
assert "0.1.0" in result.output
|
|
|
|
|
|
def test_upgrade_check_reports_newer_and_exits_nonzero(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``--check`` with a newer release → prints the delta and exits non-zero, no upgrade."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("--check must not run the upgrade")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--check"])
|
|
|
|
assert result.exit_code == 1, result.output
|
|
assert "v0.1.0 → v0.2.0" in result.output
|
|
|
|
|
|
def test_upgrade_runs_installer_and_drains_first(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""A newer release → drain (no force), stop the server, run the uv command."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
|
|
events: list[str] = []
|
|
monkeypatch.setattr(
|
|
"omnigent.cli._wait_for_local_sessions_to_drain", lambda: events.append("drained")
|
|
)
|
|
|
|
def _stop(*, force: bool) -> bool:
|
|
events.append(f"stop(force={force})")
|
|
return True
|
|
|
|
monkeypatch.setattr("omnigent.cli._stop_local_server_and_daemon", _stop)
|
|
|
|
ran: list[str] = []
|
|
|
|
def _run(command: str, _console: object) -> int:
|
|
ran.append(command)
|
|
return 0
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _run)
|
|
# The post-upgrade verification re-reads the installed version in a fresh
|
|
# subprocess; stub it to report the version the installer "moved" to.
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.2.0", None)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
# Drain happened before the stop, before the install ran.
|
|
assert events == ["drained", "stop(force=False)"]
|
|
assert ran == ["uv tool upgrade omnigent"]
|
|
assert "Upgraded to v0.2.0" in result.output
|
|
|
|
|
|
def test_upgrade_force_skips_drain_and_force_stops(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``--force`` skips the drain wait and force-stops the server."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
|
|
def _no_drain() -> None:
|
|
raise AssertionError("--force must not wait for sessions to drain")
|
|
|
|
monkeypatch.setattr("omnigent.cli._wait_for_local_sessions_to_drain", _no_drain)
|
|
|
|
stop_calls: list[bool] = []
|
|
monkeypatch.setattr(
|
|
"omnigent.cli._stop_local_server_and_daemon",
|
|
lambda *, force: stop_calls.append(force) or False,
|
|
)
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 0)
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.2.0", None)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--force"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert stop_calls == [True]
|
|
|
|
|
|
def test_upgrade_install_failure_surfaces(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""A non-zero installer exit → ClickException naming the status, exit non-zero."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 3)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "exited with status 3" in result.output
|
|
|
|
|
|
def test_upgrade_index_unreachable(monkeypatch: pytest.MonkeyPatch, _wheel_install: None) -> None:
|
|
"""Index unreachable → clear error, no upgrade attempted."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: None)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "package index" in result.output
|
|
|
|
|
|
def test_upgrade_rejects_dev_clone(monkeypatch: pytest.MonkeyPatch, _wheel_install: None) -> None:
|
|
"""A source checkout is redirected to ``git pull``, not upgraded."""
|
|
monkeypatch.setattr("omnigent.update_check._find_repo_root", lambda: Path("/repo"))
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "git pull" in result.output
|
|
|
|
|
|
def test_upgrade_rejects_editable(monkeypatch: pytest.MonkeyPatch, _wheel_install: None) -> None:
|
|
"""An editable install is redirected to ``git pull``, not upgraded."""
|
|
editable = _InstalledWheelInfo(
|
|
install_time_epoch=0.0,
|
|
installer="uv",
|
|
vcs_url="file:///Users/me/omnigent",
|
|
commit_sha=None,
|
|
is_editable=True,
|
|
package_version="0.1.0",
|
|
detected_installer="uv",
|
|
)
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", lambda: editable)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0
|
|
assert "git pull" in result.output
|
|
|
|
|
|
def test_upgrade_pre_check_detects_release_candidate(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``--pre --check`` includes pre-releases and reports the rc as available."""
|
|
captured: dict[str, object] = {}
|
|
|
|
def _fetch(include_prereleases: bool = False, **_kw: object) -> str:
|
|
captured["include_prereleases"] = include_prereleases
|
|
return "0.1.1rc1" if include_prereleases else "0.1.0"
|
|
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", _fetch)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--pre", "--check"])
|
|
|
|
assert result.exit_code == 1, result.output
|
|
assert "v0.1.0 → v0.1.1rc1" in result.output
|
|
assert captured["include_prereleases"] is True
|
|
|
|
|
|
def test_upgrade_without_pre_ignores_release_candidate(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""Without ``--pre`` the rc is invisible → reports up to date."""
|
|
|
|
def _fetch(include_prereleases: bool = False, **_kw: object) -> str | None:
|
|
return "0.1.1rc1" if include_prereleases else "0.1.0"
|
|
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", _fetch)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--check"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "up to date" in result.output
|
|
|
|
|
|
def test_count_running_sessions_ignores_idle_connected(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
) -> None:
|
|
"""Only ``status == "running"`` sessions count; idle-connected ones don't."""
|
|
from omnigent.cli import _count_running_sessions, _SessionPagesResult
|
|
|
|
sessions = [
|
|
{"id": "a", "status": "idle"},
|
|
{"id": "b", "status": "running"},
|
|
{"id": "c", "status": "idle"},
|
|
{"id": "d", "status": "running"},
|
|
{"id": "e"}, # missing status → not running
|
|
]
|
|
monkeypatch.setattr(
|
|
"omnigent.cli._fetch_session_pages",
|
|
lambda **_kw: _SessionPagesResult(sessions=sessions, error=None),
|
|
)
|
|
|
|
assert _count_running_sessions("http://127.0.0.1:6767") == 2
|
|
|
|
|
|
def test_drain_returns_immediately_when_only_idle_connected(
|
|
monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
|
|
) -> None:
|
|
"""Regression: 39 idle-but-connected sessions must not block the drain.
|
|
|
|
Previously the drain counted *connected* sessions, so a box with idle
|
|
sessions holding their connection open hung ``omni upgrade`` forever.
|
|
"""
|
|
from omnigent.cli import _SessionPagesResult, _wait_for_local_sessions_to_drain
|
|
|
|
monkeypatch.setattr(
|
|
"omnigent.cli.local_server_status",
|
|
lambda: LocalServerInfo(running=True, pid=1, port=6767, url="http://127.0.0.1:6767"),
|
|
)
|
|
monkeypatch.setattr(
|
|
"omnigent.cli._fetch_session_pages",
|
|
lambda **_kw: _SessionPagesResult(
|
|
sessions=[{"id": f"conv_{i}", "status": "idle"} for i in range(39)], error=None
|
|
),
|
|
)
|
|
|
|
_wait_for_local_sessions_to_drain() # must return, not hang
|
|
|
|
assert "Waiting for" not in capsys.readouterr().out
|
|
|
|
|
|
def test_upgrade_pre_passes_prerelease_flag_to_installer(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``--pre`` upgrade runs the uv command with ``--prerelease allow``."""
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check.fetch_latest_version",
|
|
lambda include_prereleases=False, **_kw: "0.1.1rc1",
|
|
)
|
|
monkeypatch.setattr("omnigent.cli._wait_for_local_sessions_to_drain", lambda: None)
|
|
monkeypatch.setattr("omnigent.cli._stop_local_server_and_daemon", lambda *, force: False)
|
|
ran: list[str] = []
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._run_upgrade_command",
|
|
lambda command, _console: ran.append(command) or 0,
|
|
)
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.1.1rc1", None)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--pre"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert ran == ["uv tool upgrade omnigent --prerelease allow"]
|
|
|
|
|
|
# ── ``omni update`` alias ────────────────────────────────────────────
|
|
|
|
|
|
def test_update_is_alias_for_upgrade_same_callback() -> None:
|
|
"""``update`` and ``upgrade`` resolve to the exact same Click command.
|
|
|
|
The alias is registered by handing the *same* Command object to the
|
|
group under a second name, so its callback, options and help must be
|
|
identical — there is no second implementation to drift from ``upgrade``.
|
|
"""
|
|
update_cmd = cli.commands["update"]
|
|
upgrade_cmd = cli.commands["upgrade"]
|
|
|
|
assert update_cmd is upgrade_cmd
|
|
assert update_cmd.callback is upgrade_cmd.callback
|
|
# Same option surface (--check / --force / --pre).
|
|
assert [p.name for p in update_cmd.params] == [p.name for p in upgrade_cmd.params]
|
|
|
|
|
|
def test_update_up_to_date(monkeypatch: pytest.MonkeyPatch, _wheel_install: None) -> None:
|
|
"""``omni update`` runs the upgrade flow end-to-end (up-to-date path)."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.1.0")
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("upgrade command ran while already up to date")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
result = CliRunner().invoke(cli, ["update"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "up to date" in result.output
|
|
assert "0.1.0" in result.output
|
|
|
|
|
|
def test_update_check_matches_upgrade_check(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``update --check`` behaves identically to ``upgrade --check``."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("--check must not run the upgrade")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
runner = CliRunner()
|
|
update_result = runner.invoke(cli, ["update", "--check"])
|
|
upgrade_result = runner.invoke(cli, ["upgrade", "--check"])
|
|
|
|
assert update_result.exit_code == upgrade_result.exit_code == 1
|
|
assert update_result.output == upgrade_result.output
|
|
assert "v0.1.0 → v0.2.0" in update_result.output
|
|
|
|
|
|
def test_update_suppresses_update_check_like_upgrade() -> None:
|
|
"""``update`` is special-cased alongside ``upgrade`` in the skip set."""
|
|
from omnigent.cli import _should_skip_update_check
|
|
|
|
assert _should_skip_update_check(["update"]) is True
|
|
assert _should_skip_update_check(["upgrade"]) is True
|
|
|
|
|
|
def test_upgrade_noop_install_reports_failure_not_success(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""Regression: a no-op upgrade must NOT claim success.
|
|
|
|
The installer exits 0 but the installed version doesn't move (a pinned
|
|
spec, a cooldown/exclude-newer excluding the release, or a stale index
|
|
cache). The old code printed "✓ Upgraded to v0.2.0" anyway, so the next
|
|
``--check`` kept reporting the same update — the bug this guards against.
|
|
"""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 0)
|
|
# The installer ran (exit 0) but the version is unchanged.
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.1.0", None)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0, result.output
|
|
assert "still v0.1.0" in result.output
|
|
assert "✓ Upgraded" not in result.output
|
|
|
|
|
|
def test_upgrade_unconfirmed_version_is_honest(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""When the new version can't be read back, don't assert a version."""
|
|
monkeypatch.setattr("omnigent.update_check.fetch_latest_version", lambda *_a, **_k: "0.2.0")
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 0)
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: (None, None)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "couldn't confirm" in result.output
|
|
assert "✓ Upgraded" not in result.output
|
|
|
|
|
|
def test_upgrade_git_install_up_to_date(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""A git install whose ref hasn't moved reports up to date by commit."""
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _git_install_info)
|
|
# fetch_latest_version must never be consulted for a git install.
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check.fetch_latest_version",
|
|
lambda *_a, **_k: pytest.fail("git install must not query PyPI"),
|
|
)
|
|
monkeypatch.setattr("omnigent.update_check._remote_git_head", lambda _url: "a" * 40)
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("nothing to re-pull when already at the ref HEAD")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "up to date" in result.output
|
|
|
|
|
|
def test_upgrade_git_check_behind_exits_nonzero(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""``--check`` on a git install behind its ref reports the delta, exits non-zero."""
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _git_install_info)
|
|
monkeypatch.setattr("omnigent.update_check._remote_git_head", lambda _url: "b" * 40)
|
|
|
|
def _must_not_run(*_a: object, **_k: object) -> int:
|
|
raise AssertionError("--check must not re-pull")
|
|
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", _must_not_run)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade", "--check"])
|
|
|
|
assert result.exit_code == 1, result.output
|
|
assert "newer commit is available" in result.output
|
|
|
|
|
|
def test_upgrade_git_install_repulls_and_verifies_commit(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""A git install behind its ref re-pulls and reports the NEW commit."""
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _git_install_info)
|
|
monkeypatch.setattr("omnigent.update_check._remote_git_head", lambda _url: "b" * 40)
|
|
|
|
ran: list[str] = []
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._run_upgrade_command",
|
|
lambda command, _console: ran.append(command) or 0,
|
|
)
|
|
# After re-pull the install is at the new commit.
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.1.0", "b" * 40)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert ran == ["uv tool install --reinstall git+https://github.com/omnigent-ai/omnigent.git"]
|
|
assert "Updated to git bbbbbbbbb" in result.output
|
|
|
|
|
|
def test_upgrade_git_install_noop_does_not_claim_update(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""If the re-pull leaves the commit unchanged, say so — don't claim an update."""
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _git_install_info)
|
|
# Remote unknown (e.g. offline) → re-pull anyway, then verify by commit.
|
|
monkeypatch.setattr("omnigent.update_check._remote_git_head", lambda _url: None)
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 0)
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.1.0", "a" * 40)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code == 0, result.output
|
|
assert "nothing changed" in result.output
|
|
assert "✓ Updated" not in result.output
|
|
|
|
|
|
def test_upgrade_git_confirmed_behind_but_repull_noop_fails(
|
|
monkeypatch: pytest.MonkeyPatch, _wheel_install: None
|
|
) -> None:
|
|
"""Regression: known-behind git install whose re-pull doesn't move the commit
|
|
must FAIL, not silently exit 0 (else it recreates the loop on the git path)."""
|
|
monkeypatch.setattr("omnigent.update_check._read_installed_wheel_info", _git_install_info)
|
|
# Remote HEAD differs from the installed commit ("a"*40) → positively behind.
|
|
monkeypatch.setattr("omnigent.update_check._remote_git_head", lambda _url: "b" * 40)
|
|
monkeypatch.setattr("omnigent.update_check._run_upgrade_command", lambda *_a, **_k: 0)
|
|
# …but the re-pull left the install on the SAME commit (pinned ref / cached).
|
|
monkeypatch.setattr(
|
|
"omnigent.update_check._probe_installed_distribution", lambda: ("0.1.0", "a" * 40)
|
|
)
|
|
|
|
result = CliRunner().invoke(cli, ["upgrade"])
|
|
|
|
assert result.exit_code != 0, result.output
|
|
assert "still at aaaaaaaaa" in result.output
|
|
assert "✓ Updated" not in result.output
|