mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-25 18:40:06 -04:00
upgrade: report git branch via --show-current so a stale release tag can't break upgrades
git rev-parse --abbrev-ref HEAD reports "heads/release" when a stale tag named release exists alongside the release branch (tags outrank heads in git ref resolution). check_for_update then looked up the nonexistent origin/heads/release and permanently reported no updates available, and the Controller UI pre-filled "heads/release" as the upgrade branch. Use git branch --show-current everywhere instead; it never disambiguates. A detached HEAD (empty output) now defaults to the release branch for upgrades; a genuine git failure still returns None. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
9e8050bd48
commit
ab5f416b3f
5 changed files with 94 additions and 15 deletions
|
|
@ -78,17 +78,20 @@ def get_current_branch() -> Optional[str]:
|
|||
Get the current git branch of /opt/wrolpi.
|
||||
|
||||
Returns:
|
||||
Branch name, or None if unable to determine
|
||||
Branch name ('release' on a detached HEAD), or None if unable to determine
|
||||
"""
|
||||
try:
|
||||
# Not `rev-parse --abbrev-ref HEAD`: it reports "heads/release" when a stale
|
||||
# `release` tag exists alongside the branch, breaking origin/{branch} lookups.
|
||||
result = subprocess.run(
|
||||
["git", "-C", "/opt/wrolpi", "rev-parse", "--abbrev-ref", "HEAD"],
|
||||
["git", "-C", "/opt/wrolpi", "branch", "--show-current"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=5,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
return result.stdout.strip()
|
||||
# A detached HEAD prints nothing; upgrades come from `release` by default.
|
||||
return result.stdout.strip() or "release"
|
||||
except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
|
||||
pass
|
||||
return None
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from unittest import mock
|
|||
|
||||
from controller.lib.scripts import (
|
||||
AVAILABLE_SCRIPTS,
|
||||
get_current_branch,
|
||||
get_script_output,
|
||||
get_script_status,
|
||||
list_available_scripts,
|
||||
|
|
@ -14,6 +15,44 @@ from controller.lib.scripts import (
|
|||
)
|
||||
|
||||
|
||||
class TestGetCurrentBranch:
|
||||
"""Tests for get_current_branch function."""
|
||||
|
||||
def test_returns_branch_name(self):
|
||||
"""Should return the branch name from `git branch --show-current`.
|
||||
|
||||
`git rev-parse --abbrev-ref HEAD` must not be used: it reports "heads/release" when a
|
||||
stale `release` tag exists alongside the `release` branch.
|
||||
"""
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.returncode = 0
|
||||
mock_result.stdout = "release\n"
|
||||
|
||||
with mock.patch("subprocess.run", return_value=mock_result) as mock_run:
|
||||
assert get_current_branch() == "release"
|
||||
cmd = mock_run.call_args[0][0]
|
||||
assert "--show-current" in cmd
|
||||
assert "--abbrev-ref" not in cmd
|
||||
|
||||
def test_detached_head_defaults_to_release(self):
|
||||
"""A detached HEAD (empty output) should default to 'release'."""
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.returncode = 0
|
||||
mock_result.stdout = "\n"
|
||||
|
||||
with mock.patch("subprocess.run", return_value=mock_result):
|
||||
assert get_current_branch() == "release"
|
||||
|
||||
def test_git_failure_returns_none(self):
|
||||
"""A failing git command should return None."""
|
||||
mock_result = mock.MagicMock()
|
||||
mock_result.returncode = 128
|
||||
mock_result.stdout = ""
|
||||
|
||||
with mock.patch("subprocess.run", return_value=mock_result):
|
||||
assert get_current_branch() is None
|
||||
|
||||
|
||||
class TestAvailableScripts:
|
||||
"""Tests for AVAILABLE_SCRIPTS constant."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue