Files
pzmanager/internal/updater/updater_test.go
T
mrleo1nidandClaude Opus 5 c0797be745
CI / test (push) Successful in 21s
Release / release (push) Successful in 27s
Обновление панели из интерфейса и режим обновления в установщике
Установщик стал идемпотентным: на уже настроенной машине он определяет
установленную версию, останавливает службу, меняет бинарник и поднимает её
обратно, не трогая конфиг, миры и учётные записи. Зависимости при
обновлении не переустанавливаются — это лишние минуты apt.

Кнопки «Обновить» и «Перезапустить панель» появились на вкладке
«Настройки» вместе с текущей версией и описанием нового релиза.

Панель работает от непривилегированного пользователя и не может ни
заменить свой бинарник в /usr/local/bin, ни дёрнуть systemctl. Вместо
того чтобы расширять её права, установщик кладёт root-скрипт
pzmanager-admin и разрешает сервисному пользователю через sudoers ровно
эту одну команду. Скрипт сверяет sha256 скачанного бинарника с
checksums.txt релиза. Если правила sudo нет, кнопки не будет — панель
покажет команду для терминала.

Перед обновлением и перезапуском игровой сервер останавливается штатным
quit: иначе его погасил бы systemd уже в момент рестарта, и ожидание
растянулось бы на таймаут остановки.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 19:37:53 +03:00

60 lines
2.0 KiB
Go

package updater
import "testing"
func TestIsNewer(t *testing.T) {
cases := []struct {
current, latest string
want bool
}{
{"v1.0.0", "v1.0.1", true},
{"v1.0.0", "v1.1.0", true},
{"v1.0.0", "v2.0.0", true},
{"v1.2.3", "v1.2.3", false},
{"v1.2.3", "v1.2.2", false},
{"v2.0.0", "v1.9.9", false},
// Сборка из рабочей копии не знает, что в ней, — предлагаем релиз.
{"dev", "v1.0.0", true},
{"", "v1.0.0", true},
// Без релизов обновляться некуда.
{"v1.0.0", "", false},
// Разное число компонентов.
{"v1.0", "v1.0.1", true},
{"1.0.0", "v1.0.0", false},
// Предрелизные суффиксы в сравнении чисел не участвуют.
{"v1.0.0-rc1", "v1.0.0", false},
{"v1.0.0", "v1.0.1-rc1", true},
}
for _, c := range cases {
if got := IsNewer(c.current, c.latest); got != c.want {
t.Errorf("IsNewer(%q, %q) = %v, ожидалось %v", c.current, c.latest, got, c.want)
}
}
}
func TestAPIBase(t *testing.T) {
cases := map[string]string{
"https://gitea.hsrv.site/mrleo1nid/pzmanager": "https://gitea.hsrv.site/api/v1/repos/mrleo1nid/pzmanager",
"https://gitea.hsrv.site/mrleo1nid/pzmanager.git": "https://gitea.hsrv.site/api/v1/repos/mrleo1nid/pzmanager",
"https://gitea.hsrv.site/mrleo1nid/pzmanager/": "https://gitea.hsrv.site/api/v1/repos/mrleo1nid/pzmanager",
"http://192.168.0.5:3000/team/pzmanager": "http://192.168.0.5:3000/api/v1/repos/team/pzmanager",
}
for repo, want := range cases {
got, err := New(repo, "dev").apiBase()
if err != nil {
t.Errorf("apiBase(%q): %v", repo, err)
continue
}
if got != want {
t.Errorf("apiBase(%q) = %q, ожидалось %q", repo, got, want)
}
}
for _, bad := range []string{"gitea.hsrv.site/owner/repo", "https://gitea.hsrv.site", ""} {
if _, err := New(bad, "dev").apiBase(); err == nil {
t.Errorf("адрес %q принят, ожидалась ошибка", bad)
}
}
}