Starting a Controller script writes its env file every time and rejects unknown parameters

The upgrade service reads BRANCH from /tmp/wrolpi-upgrade.env, which upgrade.sh removes when it finishes.  The
Controller wrote that file only when a request had parameters, so starting an upgrade without a branch (the simple UI
sends no body when the field is empty) left the service unable to start, while the API answered success.  A request
like {"branch": "master"} was accepted with the key ignored, the same way.

Now the env file is always written, and a missing branch is the current one, as upgrade.sh chooses; a file left by an
interrupted run no longer chooses it.  Unknown parameters and unknown request keys are errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Roland 2026-10-25 20:11:19 -06:00
parent eb82489426
commit 3e54731534
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
4 changed files with 74 additions and 8 deletions

View file

@ -240,6 +240,46 @@ class TestStartScript:
assert "wrolpi-repair.service" in call_args
def _start_upgrade(self, tmp_path, params, current_branch="master"):
"""Start the upgrade script with its env file in `tmp_path`. Returns (result, env file, Popen mock)."""
env_file = tmp_path / "wrolpi-upgrade.env"
with mock.patch.dict(AVAILABLE_SCRIPTS["upgrade"], {"env_file": str(env_file)}), \
mock.patch("controller.lib.scripts.is_docker_mode", return_value=False), \
mock.patch("controller.lib.scripts.get_script_status", return_value={"running": False}), \
mock.patch("controller.lib.scripts.get_current_branch", return_value=current_branch), \
mock.patch("subprocess.Popen") as popen:
result = start_script("upgrade", params=params)
return result, env_file, popen
def test_upgrade_without_branch_writes_current_branch(self, tmp_path):
"""The upgrade service reads BRANCH from its env file, and fails to start without the file; upgrade.sh
removes it when it finishes. With no branch, upgrade the current one, as upgrade.sh does."""
for params in (None, {}, {"branch": ""}):
result, env_file, popen = self._start_upgrade(tmp_path, params)
assert result["success"] is True, params
assert env_file.read_text() == "BRANCH=master\n", params
popen.assert_called_once()
env_file.unlink()
def test_upgrade_replaces_stale_env_file(self, tmp_path):
"""A file left by an interrupted upgrade does not choose the branch."""
(tmp_path / "wrolpi-upgrade.env").write_text("BRANCH=old\n")
result, env_file, _ = self._start_upgrade(tmp_path, None, current_branch="release")
assert result["success"] is True
assert env_file.read_text() == "BRANCH=release\n"
result, env_file, _ = self._start_upgrade(tmp_path, {"branch": "master"}, current_branch="release")
assert env_file.read_text() == "BRANCH=master\n"
def test_unknown_param_is_rejected(self, tmp_path):
"""A misspelled parameter is an error, not silently ignored."""
result, env_file, popen = self._start_upgrade(tmp_path, {"brnch": "master"})
assert result["success"] is False
assert "brnch" in result["error"]
assert not env_file.exists()
popen.assert_not_called()
class TestGetScriptOutput:
"""Tests for get_script_output function."""