mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-28 00:24:19 +00:00
feat(nodes): add Dev channel option to node panel updates
The node update confirm dialog now offers a 'Dev channel (latest commit)' choice. The dev flag threads master -> nodes/updatePanel -> UpdatePanels -> remote.UpdatePanel -> the node's updatePanel endpoint, which calls StartUpdateChannel(dev) to install the rolling dev-latest build. With no dev flag the node keeps following its own channel setting.
This commit is contained in:
@@ -318,6 +318,7 @@ func (a *NodeController) probe(c *gin.Context) {
|
||||
func (a *NodeController) updatePanel(c *gin.Context) {
|
||||
var req struct {
|
||||
Ids []int `json:"ids"`
|
||||
Dev bool `json:"dev"`
|
||||
}
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), err)
|
||||
@@ -327,7 +328,7 @@ func (a *NodeController) updatePanel(c *gin.Context) {
|
||||
jsonMsg(c, I18nWeb(c, "somethingWentWrong"), fmt.Errorf("no nodes selected"))
|
||||
return
|
||||
}
|
||||
results, err := a.nodeService.UpdatePanels(req.Ids)
|
||||
results, err := a.nodeService.UpdatePanels(req.Ids, req.Dev)
|
||||
jsonMsgObj(c, I18nWeb(c, "pages.nodes.toasts.updateStarted"), results, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -206,9 +206,22 @@ func (a *ServerController) installXray(c *gin.Context) {
|
||||
jsonMsg(c, I18nWeb(c, "pages.index.xraySwitchVersionPopover"), err)
|
||||
}
|
||||
|
||||
// updatePanel starts a panel self-update to the latest release.
|
||||
// updatePanel starts a panel self-update. With no "dev" form value it follows
|
||||
// this panel's own channel setting; an explicit "dev" (sent by the master node
|
||||
// updater) overrides it for this run.
|
||||
func (a *ServerController) updatePanel(c *gin.Context) {
|
||||
err := a.panelService.StartUpdate()
|
||||
devParam := c.PostForm("dev")
|
||||
var err error
|
||||
if devParam == "" {
|
||||
err = a.panelService.StartUpdate()
|
||||
} else {
|
||||
dev, perr := strconv.ParseBool(devParam)
|
||||
if perr != nil {
|
||||
jsonMsg(c, "invalid data", perr)
|
||||
return
|
||||
}
|
||||
err = a.panelService.StartUpdateChannel(dev)
|
||||
}
|
||||
jsonMsg(c, I18nWeb(c, "pages.index.panelUpdateStartedPopover"), err)
|
||||
}
|
||||
|
||||
|
||||
@@ -538,9 +538,14 @@ func (r *Remote) RestartXray(ctx context.Context) error {
|
||||
|
||||
// UpdatePanel asks the node to run its own official self-updater (update.sh)
|
||||
// and restart onto the latest release. The node returns as soon as the job is
|
||||
// launched; the new version surfaces on the next heartbeat.
|
||||
func (r *Remote) UpdatePanel(ctx context.Context) error {
|
||||
_, err := r.do(ctx, http.MethodPost, "panel/api/server/updatePanel", nil)
|
||||
// launched; the new version surfaces on the next heartbeat. When dev is true the
|
||||
// node is moved to the rolling dev channel instead of the latest stable release.
|
||||
func (r *Remote) UpdatePanel(ctx context.Context, dev bool) error {
|
||||
var body any
|
||||
if dev {
|
||||
body = url.Values{"dev": {"true"}}
|
||||
}
|
||||
_, err := r.do(ctx, http.MethodPost, "panel/api/server/updatePanel", body)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -637,7 +637,7 @@ type NodeUpdateResult struct {
|
||||
// UpdatePanels triggers the official self-updater on each given node. Only
|
||||
// enabled, online nodes are eligible — an offline node can't be reached, so it
|
||||
// is reported as skipped rather than silently dropped.
|
||||
func (s *NodeService) UpdatePanels(ids []int) ([]NodeUpdateResult, error) {
|
||||
func (s *NodeService) UpdatePanels(ids []int, dev bool) ([]NodeUpdateResult, error) {
|
||||
mgr := runtime.GetManager()
|
||||
if mgr == nil {
|
||||
return nil, fmt.Errorf("runtime manager unavailable")
|
||||
@@ -662,7 +662,7 @@ func (s *NodeService) UpdatePanels(ids []int) ([]NodeUpdateResult, error) {
|
||||
break
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
|
||||
updErr := remote.UpdatePanel(ctx)
|
||||
updErr := remote.UpdatePanel(ctx, dev)
|
||||
cancel()
|
||||
if updErr != nil {
|
||||
res.Error = updErr.Error()
|
||||
|
||||
@@ -122,8 +122,19 @@ func getDevUpdateInfo() (*PanelUpdateInfo, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// StartUpdate starts the official updater outside of the current web request.
|
||||
// StartUpdate starts the official updater using this panel's own channel setting.
|
||||
func (s *PanelService) StartUpdate() error {
|
||||
return s.startUpdate(devChannelActive())
|
||||
}
|
||||
|
||||
// StartUpdateChannel runs the updater against an explicitly chosen channel,
|
||||
// overriding the local dev-channel setting. Used by the master node updater so
|
||||
// a node can be moved to the dev channel from the central panel.
|
||||
func (s *PanelService) StartUpdateChannel(dev bool) error {
|
||||
return s.startUpdate(dev)
|
||||
}
|
||||
|
||||
func (s *PanelService) startUpdate(useDev bool) error {
|
||||
if runtime.GOOS != "linux" {
|
||||
return fmt.Errorf("panel web update is supported only on Linux installations")
|
||||
}
|
||||
@@ -140,7 +151,7 @@ func (s *PanelService) StartUpdate() error {
|
||||
|
||||
mainFolder, serviceFolder := resolveUpdateFolders()
|
||||
updateTag := ""
|
||||
if devChannelActive() {
|
||||
if useDev {
|
||||
updateTag = devReleaseTag
|
||||
}
|
||||
updateScript := fmt.Sprintf("set -e; trap 'rm -f %s' EXIT; %s %s", shellQuote(scriptPath), shellQuote(bash), shellQuote(scriptPath))
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "محدّث",
|
||||
"updateConfirmTitle": "تحديث {count} عقدة إلى أحدث إصدار؟",
|
||||
"updateConfirmContent": "كل عقدة محددة ستنزّل أحدث إصدار وتعيد التشغيل عليه. يتم تحديث العقد المفعّلة والمتصلة فقط.",
|
||||
"updateDevChannel": "التحديث إلى قناة التطوير (أحدث كومِت)",
|
||||
"testConnection": "اختبار الاتصال",
|
||||
"connectionOk": "الاتصال شغال ({ms} ms)",
|
||||
"connectionFailed": "فشل الاتصال",
|
||||
|
||||
@@ -1098,6 +1098,7 @@
|
||||
"upToDate": "Up to date",
|
||||
"updateConfirmTitle": "Update {count} node(s) to the latest version?",
|
||||
"updateConfirmContent": "Each selected node downloads the latest release and restarts onto it. Only enabled, online nodes are updated.",
|
||||
"updateDevChannel": "Update to Dev channel (latest commit)",
|
||||
"testConnection": "Test Connection",
|
||||
"connectionOk": "Connection OK ({ms} ms)",
|
||||
"connectionFailed": "Connection failed",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Actualizado",
|
||||
"updateConfirmTitle": "¿Actualizar {count} nodo(s) a la última versión?",
|
||||
"updateConfirmContent": "Cada nodo seleccionado descarga la última versión y se reinicia con ella. Solo se actualizan los nodos habilitados y en línea.",
|
||||
"updateDevChannel": "Actualizar al canal de desarrollo (último commit)",
|
||||
"testConnection": "Probar conexión",
|
||||
"connectionOk": "Conexión correcta ({ms} ms)",
|
||||
"connectionFailed": "Conexión fallida",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "بهروز",
|
||||
"updateConfirmTitle": "{count} نود به آخرین نسخه بهروزرسانی شوند؟",
|
||||
"updateConfirmContent": "هر نود انتخابشده آخرین نسخه را دانلود و روی آن ریاستارت میشود. فقط نودهای فعال و آنلاین بهروزرسانی میشوند.",
|
||||
"updateDevChannel": "بهروزرسانی به کانال دِو (آخرین کامیت)",
|
||||
"testConnection": "تست اتصال",
|
||||
"connectionOk": "اتصال موفق ({ms} میلیثانیه)",
|
||||
"connectionFailed": "اتصال ناموفق",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Terbaru",
|
||||
"updateConfirmTitle": "Perbarui {count} node ke versi terbaru?",
|
||||
"updateConfirmContent": "Setiap node terpilih mengunduh rilis terbaru dan memulai ulang. Hanya node aktif dan online yang diperbarui.",
|
||||
"updateDevChannel": "Perbarui ke kanal dev (commit terbaru)",
|
||||
"testConnection": "Tes Koneksi",
|
||||
"connectionOk": "Koneksi OK ({ms} ms)",
|
||||
"connectionFailed": "Koneksi gagal",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "最新",
|
||||
"updateConfirmTitle": "{count} 個のノードを最新バージョンに更新しますか?",
|
||||
"updateConfirmContent": "選択した各ノードは最新リリースをダウンロードして再起動します。有効かつオンラインのノードのみが更新されます。",
|
||||
"updateDevChannel": "開発チャンネルに更新(最新コミット)",
|
||||
"testConnection": "接続テスト",
|
||||
"connectionOk": "接続OK ({ms} ms)",
|
||||
"connectionFailed": "接続に失敗しました",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Atualizado",
|
||||
"updateConfirmTitle": "Atualizar {count} nó(s) para a versão mais recente?",
|
||||
"updateConfirmContent": "Cada nó selecionado baixa a versão mais recente e reinicia nela. Apenas nós ativos e online são atualizados.",
|
||||
"updateDevChannel": "Atualizar para o canal de desenvolvimento (último commit)",
|
||||
"testConnection": "Testar conexão",
|
||||
"connectionOk": "Conexão OK ({ms} ms)",
|
||||
"connectionFailed": "Falha na conexão",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Актуально",
|
||||
"updateConfirmTitle": "Обновить {count} узлов до последней версии?",
|
||||
"updateConfirmContent": "Каждый выбранный узел загрузит последний релиз и перезапустится. Обновляются только включённые узлы в сети.",
|
||||
"updateDevChannel": "Обновить до канала разработки (последний коммит)",
|
||||
"testConnection": "Проверить соединение",
|
||||
"connectionOk": "Соединение в порядке ({ms} мс)",
|
||||
"connectionFailed": "Не удалось подключиться",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Güncel",
|
||||
"updateConfirmTitle": "{count} düğüm en son sürüme güncellensin mi?",
|
||||
"updateConfirmContent": "Seçilen her düğüm en son sürümü indirir ve yeniden başlatılır. Yalnızca etkin ve çevrimiçi düğümler güncellenir.",
|
||||
"updateDevChannel": "Dev kanalına güncelle (son commit)",
|
||||
"testConnection": "Bağlantıyı Test Et",
|
||||
"connectionOk": "Bağlantı tamam ({ms} ms)",
|
||||
"connectionFailed": "Bağlantı başarısız",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Актуально",
|
||||
"updateConfirmTitle": "Оновити {count} вузлів до останньої версії?",
|
||||
"updateConfirmContent": "Кожен вибраний вузол завантажить останній реліз і перезапуститься. Оновлюються лише увімкнені вузли в мережі.",
|
||||
"updateDevChannel": "Оновити до каналу розробки (останній коміт)",
|
||||
"testConnection": "Перевірити з'єднання",
|
||||
"connectionOk": "З'єднання в порядку ({ms} мс)",
|
||||
"connectionFailed": "Помилка з'єднання",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "Mới nhất",
|
||||
"updateConfirmTitle": "Cập nhật {count} node lên phiên bản mới nhất?",
|
||||
"updateConfirmContent": "Mỗi node đã chọn sẽ tải bản phát hành mới nhất và khởi động lại. Chỉ các node đang bật và trực tuyến được cập nhật.",
|
||||
"updateDevChannel": "Cập nhật lên kênh phát triển (commit mới nhất)",
|
||||
"testConnection": "Kiểm tra kết nối",
|
||||
"connectionOk": "Kết nối OK ({ms} ms)",
|
||||
"connectionFailed": "Kết nối thất bại",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "已是最新",
|
||||
"updateConfirmTitle": "将 {count} 个节点更新到最新版本?",
|
||||
"updateConfirmContent": "每个所选节点会下载最新版本并重启。仅更新已启用且在线的节点。",
|
||||
"updateDevChannel": "更新到开发通道(最新提交)",
|
||||
"testConnection": "测试连接",
|
||||
"connectionOk": "连接正常 ({ms} ms)",
|
||||
"connectionFailed": "连接失败",
|
||||
|
||||
@@ -979,6 +979,7 @@
|
||||
"upToDate": "已是最新",
|
||||
"updateConfirmTitle": "將 {count} 個節點更新到最新版本?",
|
||||
"updateConfirmContent": "每個所選節點會下載最新版本並重新啟動。僅更新已啟用且在線的節點。",
|
||||
"updateDevChannel": "更新到開發通道(最新提交)",
|
||||
"testConnection": "測試連線",
|
||||
"connectionOk": "連線正常 ({ms} ms)",
|
||||
"connectionFailed": "連線失敗",
|
||||
|
||||
Reference in New Issue
Block a user