Add a Django updater view for checking configured Gitea releases, inspecting the installed git checkout, fetching tags, pulling the current branch, and running the configured native systemd update command. Document the updater environment settings and keep the page staff-only so readonly status users cannot trigger deployment actions.
73 lines
3.2 KiB
Python
73 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
from unittest.mock import MagicMock, patch
|
|
|
|
from django.test import SimpleTestCase, override_settings
|
|
|
|
from pobsync_backend import updater
|
|
|
|
|
|
class UpdaterTests(SimpleTestCase):
|
|
@override_settings(
|
|
POBSYNC_UPDATE_RELEASES_URL="https://code.example.test/api/v1/repos/owner/pobsync/releases",
|
|
POBSYNC_UPDATE_RELEASES_TOKEN="secret",
|
|
)
|
|
def test_fetch_latest_release_reads_first_gitea_release(self) -> None:
|
|
response = MagicMock()
|
|
response.__enter__.return_value.read.return_value = json.dumps(
|
|
[
|
|
{
|
|
"tag_name": "v1.2.0",
|
|
"name": "1.2.0",
|
|
"html_url": "https://code.example.test/releases/v1.2.0",
|
|
}
|
|
]
|
|
).encode("utf-8")
|
|
|
|
with patch("pobsync_backend.updater.urlopen", return_value=response) as urlopen:
|
|
release = updater.fetch_latest_release()
|
|
|
|
self.assertEqual(release["tag_name"], "v1.2.0")
|
|
request = urlopen.call_args.args[0]
|
|
self.assertEqual(request.full_url, "https://code.example.test/api/v1/repos/owner/pobsync/releases")
|
|
self.assertEqual(request.headers["Authorization"], "token secret")
|
|
|
|
@override_settings(POBSYNC_UPDATE_RELEASES_URL="")
|
|
def test_collect_update_status_reports_unconfigured_release_check(self) -> None:
|
|
with patch("pobsync_backend.updater._git_status", return_value={"branch": "master"}):
|
|
status = updater.collect_update_status(check_release=True)
|
|
|
|
self.assertFalse(status["release_check_configured"])
|
|
self.assertEqual(status["release_error"], "POBSYNC_UPDATE_RELEASES_URL is not configured.")
|
|
self.assertIsNone(status["update_available"])
|
|
|
|
@override_settings(POBSYNC_UPDATE_GIT_REMOTE="upstream")
|
|
def test_run_git_fetch_uses_configured_remote(self) -> None:
|
|
completed = MagicMock(returncode=0, stdout="ok", stderr="")
|
|
with patch("pobsync_backend.updater.subprocess.run", return_value=completed) as run:
|
|
result = updater.run_git_fetch()
|
|
|
|
self.assertTrue(result.ok)
|
|
self.assertEqual(result.command, ["git", "fetch", "--tags", "--prune", "upstream"])
|
|
run.assert_called_once()
|
|
|
|
@override_settings(POBSYNC_UPDATE_GIT_REMOTE="origin")
|
|
def test_run_git_pull_rejects_detached_checkout(self) -> None:
|
|
with patch("pobsync_backend.updater._git_current_branch", return_value=""):
|
|
result = updater.run_git_pull()
|
|
|
|
self.assertFalse(result.ok)
|
|
self.assertEqual(result.exit_code, 2)
|
|
self.assertIn("not on a branch", result.stderr)
|
|
|
|
@override_settings(POBSYNC_UPDATE_COMMAND="sudo -n scripts/update-systemd --verbose")
|
|
def test_run_native_update_splits_configured_command(self) -> None:
|
|
completed = MagicMock(returncode=1, stdout="", stderr="sudo failed")
|
|
with patch("pobsync_backend.updater.subprocess.run", return_value=completed):
|
|
result = updater.run_native_update()
|
|
|
|
self.assertFalse(result.ok)
|
|
self.assertEqual(result.command, ["sudo", "-n", "scripts/update-systemd", "--verbose"])
|
|
self.assertEqual(result.stderr, "sudo failed")
|