feat(admin): manage server updates and local configuration
ci / api / api (push) Successful in 52s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m9s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m35s
release / release (версия и заметки) (push) Successful in 5s
release / android (APK в релиз) (push) Successful in 4m6s
ci / db / db (push) Successful in 1m15s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m19s
ci / ts / ts (packages + web) (push) Successful in 2m34s
release / desktop (Linux и Windows в релиз) (push) Successful in 14m27s
release / prune (старые файлы и прогоны) (push) Successful in 6s

This commit is contained in:
mrleo1nid committed 2026-10-22 23:01:36 +03:00
1 parent e33abc948c
commit a29a8b18ad
49 files changed
+3604 -353

No files matched your search

+86 -2
View File
@@ -32,7 +32,10 @@
"recs_confirm": "Reset {{username}}'s recommendations? The wave will start learning their taste from scratch and ask for favourite artists again. Likes and history stay.",
"recs_done": "{{username}}'s recommendations were reset",
"confirm": "Confirm",
"you": "you"
"you": "you",
"manage_updates": "Server updates",
"grant_updates": "Grant update management",
"revoke_updates": "Revoke update management"
},
"create": {
"title": "New user",
@@ -71,7 +74,8 @@
"user.unblock": "User unblocked",
"user.password_reset": "Password reset",
"user.recommendations_reset": "Recommendations reset",
"user.delete": "User deleted"
"user.delete": "User deleted",
"user.manages_updates": "Server update permission changed"
}
},
"sources": {
@@ -378,5 +382,85 @@
"server_settings": {
"title": "Server settings",
"subtitle": "Settings that apply to all users"
},
"management": {
"server": "Server management",
"updates": "Updates",
"config": "Configuration",
"updates_intro": "Choose a source and version. The server will build and report the result.",
"refresh": "Refresh status",
"current": "Installed version",
"manual": "Updates start manually. The latest stable release is resolved when you start the update.",
"update_target": "Next update",
"sources": "Update sources",
"source": "Source",
"channel": "Update target",
"channel_latest": "Latest release",
"channel_version": "Choose version",
"channel_main": "main",
"hint_latest": "Install the latest stable tag, excluding release candidates.",
"hint_version": "Choose a published tag. Downgrading to an older version requires a manual rollback.",
"hint_main": "The current main branch. May include unreleased changes.",
"version": "Version",
"choose_version": "Choose a version",
"source_unavailable": "Could not read the repository. Check its address, server access and SSH keys.",
"install": "Install update",
"confirm_update": "Update the server?",
"confirm_update_text": "Source: {{source}}. Target: {{target}}.",
"update_warning": "The service will be briefly unavailable during restart. Back up the database first. Database migrations are not rolled back.",
"cancel": "Cancel",
"sources_hint": "Git repositories compatible with Pipu. HTTP(S) or SSH; configure private repository keys on the agent host. Do not include tokens in the URL.",
"source_name": "Name",
"repository": "Git repository URL",
"remove_source": "Remove source",
"add_source": "Add source",
"save": "Save",
"job": "Last operation",
"started": "Started",
"finished": "Finished",
"log": "Execution log",
"waiting": "Waiting for command output…",
"running_hint": "The task runs on the server. You can close this page without interrupting it.",
"reconnecting": "Services are restarting. Waiting to reconnect to the server…",
"state": {
"running": "Running",
"succeeded": "Completed",
"failed": "Failed"
},
"config_intro": "API, recommender and deployment settings in deploy/config.local.",
"priority": "Priority order",
"defaults": "defaults",
"priority_hint": ".env values override config.local. Save and apply are separate actions.",
"search": "Search settings",
"group": "Section",
"all": "All sections",
"groups": {
"api": "API",
"deployment": "Deployment",
"shared": "Shared",
"recommender": "Recommender"
},
"config_files_hint": "Supported settings are listed here. “After applying” is the value from .env, config.local or a default. Fixed paths and service parameters are read-only. Secrets can be replaced; their values stay hidden.",
"value_source": {
"env": "From .env",
"local": "From config.local",
"default": "Default"
},
"effective": "After applying",
"readonly": "Service parameter. Change on the host together with its Compose configuration.",
"secret_saved": "Secret saved",
"will_reset": "The local value will be removed when saved.",
"overridden": "A value in .env takes priority. This local change will not take effect yet.",
"secret_hint": "Leave unchanged to keep the stored secret. Enter a new value to replace it.",
"default": "Default",
"reset": "Reset local value",
"no_results": "No settings found",
"saved": "Changes saved to config.local",
"unsaved": "Unsaved settings: {{count}}",
"pending_restart": "Saved changes are waiting to be applied",
"no_changes": "No changes to apply",
"discard": "Discard edits",
"apply": "Apply and restart",
"apply_warning": "Containers will be recreated with the saved configuration. The service will be briefly unavailable; persistent volume data is preserved. Values from .env will keep taking priority."
}
}
+3 -1
View File
@@ -62,7 +62,9 @@
"suggest": "Suggest tracks",
"my_uploads": "My uploads",
"upload_queue": "Queue",
"admin_settings": "Settings"
"admin_settings": "Settings",
"server_updates": "Updates",
"server_config": "Configuration"
},
"profile": {
"menu": "Profile menu",
+16
View File
@@ -101,5 +101,21 @@
"invalid_tracks": "Tracks must be unique and exist in the library",
"too_large": "Maximum 2000 tracks and 2000 description characters",
"conflict": "This playlist changed on another device. Close the editor and try again with the refreshed data."
},
"management": {
"unavailable": "Server management agent is unavailable. Run sudo bash deploy/install-management.sh on the server and check pipu-management.service.",
"timeout": "The agent timed out. Check operation status before retrying.",
"busy": "A server operation is already running. Wait for it to finish.",
"source_invalid": "Check source names and URLs. Embedded passwords and tokens are not supported.",
"source_unavailable": "The repository is unavailable from the server.",
"target_invalid": "The selected version is unavailable or changed. Refresh the list and try again.",
"no_releases": "No stable release tags were found.",
"config_conflict": "Another administrator changed the configuration. Reload the page and repeat your edits.",
"config_invalid": "Invalid value or Compose configuration. Changes were not saved.",
"config_readonly": "This setting cannot be changed in the interface.",
"agent_error": "The agent could not complete the operation. Check journalctl -u pipu-management.",
"request_expired": "The request expired. Check operation status before retrying.",
"request_invalid": "Invalid server management request.",
"operation_invalid": "Unsupported server management operation."
}
}
+86 -2
View File
@@ -32,7 +32,10 @@
"recs_confirm": "Сбросить рекомендации {{username}}? Волна начнёт подбирать музыку с нуля и снова спросит любимых исполнителей. Лайки и история останутся.",
"recs_done": "Рекомендации {{username}} сброшены",
"confirm": "Подтвердить",
"you": "вы"
"you": "вы",
"manage_updates": "Обновление сервера",
"grant_updates": "Дать управление обновлениями",
"revoke_updates": "Забрать управление обновлениями"
},
"create": {
"title": "Новый пользователь",
@@ -71,7 +74,8 @@
"user.unblock": "Пользователь разблокирован",
"user.password_reset": "Сброшен пароль",
"user.recommendations_reset": "Сброшены рекомендации",
"user.delete": "Пользователь удалён"
"user.delete": "Пользователь удалён",
"user.manages_updates": "Изменены права обновления сервера"
}
},
"sources": {
@@ -378,5 +382,85 @@
"server_settings": {
"title": "Настройки сервера",
"subtitle": "Параметры, которые действуют для всех пользователей"
},
"management": {
"server": "Управление сервером",
"updates": "Обновления",
"config": "Конфигурация",
"updates_intro": "Выберите источник и версию. Сервер выполнит сборку и покажет результат.",
"refresh": "Обновить статус",
"current": "Установленная версия",
"manual": "Обновления запускаются вручную. Последний стабильный релиз выбирается в момент запуска.",
"update_target": "Следующее обновление",
"sources": "Источники обновлений",
"source": "Источник",
"channel": "Тип обновления",
"channel_latest": "Последний релиз",
"channel_version": "Выбрать версию",
"channel_main": "main",
"hint_latest": "Будет установлен последний стабильный тег без release candidate.",
"hint_version": "Можно выбрать опубликованный тег. Переход на старую версию требует ручного отката.",
"hint_main": "Текущее состояние ветки main. Может содержать ещё не выпущенные изменения.",
"version": "Версия",
"choose_version": "Выберите версию",
"source_unavailable": "Не удалось прочитать репозиторий. Проверьте адрес, доступ сервера и SSH-ключи.",
"install": "Установить обновление",
"confirm_update": "Обновить сервер?",
"confirm_update_text": "Источник: {{source}}. Цель: {{target}}.",
"update_warning": "Во время перезапуска сервис временно недоступен. Перед обновлением сделайте резервную копию базы. Миграции назад не откатываются.",
"cancel": "Отмена",
"sources_hint": "Git-репозитории с совместимой структурой Pipu. HTTP(S) или SSH; для приватных репозиториев настройте ключи на хосте агента. Не вставляйте токены в адрес.",
"source_name": "Название",
"repository": "URL Git-репозитория",
"remove_source": "Удалить источник",
"add_source": "Добавить источник",
"save": "Сохранить",
"job": "Последняя операция",
"started": "Начало",
"finished": "Завершение",
"log": "Журнал выполнения",
"waiting": "Ожидаем вывод команды…",
"running_hint": "Задача выполняется на сервере. Страницу можно закрыть — выполнение продолжится.",
"reconnecting": "Сервисы перезапускаются. Ждём восстановления связи с сервером…",
"state": {
"running": "Выполняется",
"succeeded": "Готово",
"failed": "Ошибка"
},
"config_intro": "Настройки API, рекомендателя и развёртывания в deploy/config.local.",
"priority": "Порядок приоритета",
"defaults": "по умолчанию",
"priority_hint": "Значения из .env перекрывают config.local. Сохранение и применение — отдельные действия.",
"search": "Поиск по названию настройки",
"group": "Раздел",
"all": "Все разделы",
"groups": {
"api": "API",
"deployment": "Развёртывание",
"shared": "Общие",
"recommender": "Рекомендатель"
},
"config_files_hint": "Показаны поддерживаемые параметры. «После применения» — значение из .env, config.local или значение по умолчанию. Фиксированные пути и служебные параметры доступны для просмотра. Секреты можно заменить, их значения скрыты.",
"value_source": {
"env": "Из .env",
"local": "Из config.local",
"default": "По умолчанию"
},
"effective": "После применения",
"readonly": "Служебный параметр. Меняется на хосте с учётом конфигурации Compose.",
"secret_saved": "Секрет сохранён",
"will_reset": "Локальное значение будет удалено при сохранении.",
"overridden": "В .env есть значение: оно имеет приоритет. Локальное изменение пока не вступит в силу.",
"secret_hint": "Оставьте поле без изменений, чтобы сохранить секрет. Введите новое значение для замены.",
"default": "По умолчанию",
"reset": "Сбросить локальное",
"no_results": "Настройки не найдены",
"saved": "Изменения сохранены в config.local",
"unsaved": "Несохранённых параметров: {{count}}",
"pending_restart": "Сохранённые изменения ожидают применения",
"no_changes": "Нет изменений для применения",
"discard": "Отменить правки",
"apply": "Применить и перезапустить",
"apply_warning": "Контейнеры будут пересозданы с сохранённой конфигурацией. Сервис временно недоступен; данные в постоянных томах сохранятся. Значения из .env продолжат иметь приоритет."
}
}
+3 -1
View File
@@ -62,7 +62,9 @@
"suggest": "Предложить треки",
"my_uploads": "Мои предложения",
"upload_queue": "Очередь",
"admin_settings": "Настройки"
"admin_settings": "Настройки",
"server_updates": "Обновления",
"server_config": "Конфигурация"
},
"profile": {
"menu": "Меню профиля",
+16
View File
@@ -101,5 +101,21 @@
"invalid_tracks": "Треки не должны повторяться и должны существовать в библиотеке",
"too_large": "Максимум 2000 треков и 2000 символов описания",
"conflict": "Плейлист изменён на другом устройстве. Закройте редактор и повторите изменение с обновлёнными данными."
},
"management": {
"unavailable": "Агент управления сервером недоступен. Выполните sudo bash deploy/install-management.sh на сервере и проверьте pipu-management.service.",
"timeout": "Агент не ответил вовремя. Проверьте статус операции перед повторным запуском.",
"busy": "На сервере уже выполняется операция. Дождитесь завершения.",
"source_invalid": "Проверьте названия и адреса источников. Токены и пароли в URL не поддерживаются.",
"source_unavailable": "Репозиторий недоступен с сервера.",
"target_invalid": "Выбранная версия недоступна или изменилась. Обновите список и повторите.",
"no_releases": "В источнике нет стабильных релизных тегов.",
"config_conflict": "Конфигурация изменена другим администратором. Обновите страницу и повторите правки.",
"config_invalid": "Недопустимое значение или конфигурация Compose. Изменения не сохранены.",
"config_readonly": "Этот параметр нельзя менять через интерфейс.",
"agent_error": "Агент не смог выполнить операцию. Проверьте journalctl -u pipu-management.",
"request_expired": "Запрос устарел. Проверьте статус перед повтором.",
"request_invalid": "Недопустимый запрос управления сервером.",
"operation_invalid": "Операция управления сервером не поддерживается."
}
}