l4d2host: LEFT4ME_STEAMCMD env var for steamcmd path

SteamInstaller defaults to steamcmd="steamcmd" (bare name), which relies
on PATH lookup. Deployments that don't have steamcmd on PATH — or where
steamcmd.sh's `cd "$(dirname "$0")"` breaks under PATH-symlink invocation
(observed with the Valve-shipped script) — can now pin an absolute path
via LEFT4ME_STEAMCMD. Default keeps bare-name lookup for dev/tests.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-10 22:46:21 +02:00
parent c594d4b5e8
commit 363f429c7a
No known key found for this signature in database
2 changed files with 45 additions and 1 deletions

View file

@ -1,5 +1,6 @@
from pathlib import Path from pathlib import Path
import json import json
import os
import subprocess import subprocess
import typer import typer
@ -21,8 +22,13 @@ def _exit_from_subprocess_error(exc: subprocess.CalledProcessError) -> None:
@app.command() @app.command()
def install() -> None: def install() -> None:
# LEFT4ME_STEAMCMD lets deployment pin an absolute path (e.g. when the
# binary lives outside PATH or its steamcmd.sh resolves $0 via dirname,
# which breaks under PATH-symlink invocation). Default keeps PATH lookup
# for dev/tests.
steamcmd = os.environ.get("LEFT4ME_STEAMCMD", "steamcmd")
try: try:
SteamInstaller().install_or_update(passthrough=True) SteamInstaller(steamcmd=steamcmd).install_or_update(passthrough=True)
except subprocess.CalledProcessError as exc: except subprocess.CalledProcessError as exc:
_exit_from_subprocess_error(exc) _exit_from_subprocess_error(exc)

View file

@ -14,6 +14,44 @@ def test_help_lists_v1_commands() -> None:
assert command in result.output assert command in result.output
def test_install_uses_left4me_steamcmd_env_var(monkeypatch) -> None:
captured: dict[str, str] = {}
class FakeInstaller:
def __init__(self, *, steamcmd):
captured["steamcmd"] = steamcmd
def install_or_update(self, **kwargs):
del kwargs
monkeypatch.setattr("l4d2host.cli.SteamInstaller", FakeInstaller)
monkeypatch.setenv("LEFT4ME_STEAMCMD", "/opt/left4me/steam/steamcmd.sh")
result = CliRunner().invoke(app, ["install"])
assert result.exit_code == 0
assert captured["steamcmd"] == "/opt/left4me/steam/steamcmd.sh"
def test_install_defaults_to_bare_steamcmd_when_env_unset(monkeypatch) -> None:
captured: dict[str, str] = {}
class FakeInstaller:
def __init__(self, *, steamcmd):
captured["steamcmd"] = steamcmd
def install_or_update(self, **kwargs):
del kwargs
monkeypatch.setattr("l4d2host.cli.SteamInstaller", FakeInstaller)
monkeypatch.delenv("LEFT4ME_STEAMCMD", raising=False)
result = CliRunner().invoke(app, ["install"])
assert result.exit_code == 0
assert captured["steamcmd"] == "steamcmd"
def test_cli_propagates_subprocess_return_code(monkeypatch) -> None: def test_cli_propagates_subprocess_return_code(monkeypatch) -> None:
def fail(*args, **kwargs): def fail(*args, **kwargs):
del args del args