(feature) Add staff updater page
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.
This commit is contained in:
@@ -62,6 +62,7 @@ class ViewTests(TestCase):
|
||||
self.assertContains(response, reverse("ssh_credentials"))
|
||||
self.assertContains(response, reverse("notification_targets"))
|
||||
self.assertContains(response, reverse("logs"))
|
||||
self.assertContains(response, reverse("updater"))
|
||||
self.assertContains(response, reverse("purged_snapshots"))
|
||||
self.assertContains(response, reverse("self_check"))
|
||||
self.assertContains(response, reverse("changelog"))
|
||||
@@ -82,6 +83,7 @@ class ViewTests(TestCase):
|
||||
self.assertNotContains(response, reverse("ssh_credentials"))
|
||||
self.assertNotContains(response, reverse("notification_targets"))
|
||||
self.assertNotContains(response, reverse("logs"))
|
||||
self.assertNotContains(response, reverse("updater"))
|
||||
self.assertNotContains(response, reverse("self_check"))
|
||||
self.assertNotContains(response, reverse("admin:index"))
|
||||
|
||||
@@ -135,6 +137,7 @@ class ViewTests(TestCase):
|
||||
blocked_urls = [
|
||||
reverse("ssh_credentials"),
|
||||
reverse("logs"),
|
||||
reverse("updater"),
|
||||
reverse("self_check"),
|
||||
reverse("edit_global_config"),
|
||||
reverse("create_host_config"),
|
||||
@@ -147,6 +150,90 @@ class ViewTests(TestCase):
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
def test_updater_view_renders_status(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
with patch("pobsync_backend.views.collect_update_status") as collect_update_status:
|
||||
collect_update_status.return_value = {
|
||||
"app_dir": "/opt/pobsync/app",
|
||||
"installed_version": "1.1.0",
|
||||
"release_check_configured": True,
|
||||
"update_command": "sudo -n scripts/update-systemd",
|
||||
"git_remote": "origin",
|
||||
"git": {"branch": "master", "commit": "abc1234", "describe": "v1.1.0"},
|
||||
"latest_release": None,
|
||||
"release_error": "",
|
||||
"update_available": None,
|
||||
}
|
||||
|
||||
response = self.client.get(reverse("updater"))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Updater")
|
||||
self.assertContains(response, "1.1.0")
|
||||
self.assertContains(response, "master")
|
||||
collect_update_status.assert_called_once_with(check_release=False)
|
||||
|
||||
def test_updater_check_release_requests_release_status(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
with patch("pobsync_backend.views.collect_update_status") as collect_update_status:
|
||||
collect_update_status.return_value = {
|
||||
"app_dir": "/opt/pobsync/app",
|
||||
"installed_version": "1.1.0",
|
||||
"release_check_configured": True,
|
||||
"update_command": "sudo -n scripts/update-systemd",
|
||||
"git_remote": "origin",
|
||||
"git": {"branch": "master", "commit": "abc1234", "describe": "v1.1.0"},
|
||||
"latest_release": {"tag_name": "v1.2.0", "html_url": "https://code.example.test/releases/v1.2.0"},
|
||||
"release_error": "",
|
||||
"update_available": True,
|
||||
}
|
||||
|
||||
response = self.client.post(reverse("updater"), {"action": "check_release"})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "update available")
|
||||
self.assertContains(response, "v1.2.0")
|
||||
collect_update_status.assert_called_once_with(check_release=True)
|
||||
|
||||
def test_updater_git_fetch_runs_action_and_renders_output(self) -> None:
|
||||
self.client.force_login(self.staff_user)
|
||||
|
||||
result = type(
|
||||
"Result",
|
||||
(),
|
||||
{
|
||||
"ok": True,
|
||||
"exit_code": 0,
|
||||
"command": ["git", "fetch", "--tags", "--prune", "origin"],
|
||||
"stdout": "fetched",
|
||||
"stderr": "",
|
||||
},
|
||||
)()
|
||||
with patch("pobsync_backend.views.run_git_fetch", return_value=result) as run_git_fetch, patch(
|
||||
"pobsync_backend.views.collect_update_status"
|
||||
) as collect_update_status:
|
||||
collect_update_status.return_value = {
|
||||
"app_dir": "/opt/pobsync/app",
|
||||
"installed_version": "1.1.0",
|
||||
"release_check_configured": False,
|
||||
"update_command": "sudo -n scripts/update-systemd",
|
||||
"git_remote": "origin",
|
||||
"git": {"branch": "master", "commit": "abc1234", "describe": "v1.1.0"},
|
||||
"latest_release": None,
|
||||
"release_error": "",
|
||||
"update_available": None,
|
||||
}
|
||||
|
||||
response = self.client.post(reverse("updater"), {"action": "git_fetch"})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "fetched")
|
||||
self.assertContains(response, "Updater action completed successfully.")
|
||||
run_git_fetch.assert_called_once_with()
|
||||
collect_update_status.assert_called_once_with(check_release=True)
|
||||
|
||||
def test_readonly_host_detail_hides_backup_controls_and_sensitive_config(self) -> None:
|
||||
self.client.force_login(self.readonly_user)
|
||||
GlobalConfig.objects.create(name="default", backup_root="/backups")
|
||||
|
||||
Reference in New Issue
Block a user