فهرست منبع

feat(upgrader): add test commit and restart functionality

Jacky 16 ساعت پیش
والد
کامیت
5c2621aaa6
5فایلهای تغییر یافته به همراه120 افزوده شده و 8 حذف شده
  1. 5 0
      app/src/views/system/Upgrade.vue
  2. 1 1
      go.mod
  3. 2 4
      go.sum
  4. 14 3
      internal/upgrader/binary.go
  5. 98 0
      internal/upgrader/test_commit_restart.go

+ 5 - 0
app/src/views/system/Upgrade.vue

@@ -67,6 +67,10 @@ const dryRun = computed(() => {
   return !!route.query.dry_run
 })
 
+const testCommitAndRestart = computed(() => {
+  return !!route.query.test_commit_and_restart
+})
+
 async function performUpgrade() {
   progressStatus.value = 'active'
   modalClosable.value = false
@@ -84,6 +88,7 @@ async function performUpgrade() {
     ws.send(JSON.stringify({
       dry_run: dryRun.value,
       channel: channel.value,
+      test_commit_and_restart: testCommitAndRestart.value,
     }))
   }
 

+ 1 - 1
go.mod

@@ -313,7 +313,7 @@ require (
 )
 
 replace (
-	code.pfad.fr/risefront => github.com/nginxui/risefront v1.2.0
+	code.pfad.fr/risefront => github.com/nginxui/risefront v1.2.1
 	github.com/tufanbarisyildirim/gonginx => github.com/0xJacky/gonginx v0.0.0-20250420001451-d120448e89a4
 	gorm.io/gorm => gorm.io/gorm v1.25.12
 	gorm.io/plugin/dbresolver => gorm.io/plugin/dbresolver v1.5.3

+ 2 - 4
go.sum

@@ -1520,10 +1520,8 @@ github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1t
 github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
-github.com/nginxui/risefront v1.1.10 h1:8gy6fs89nha3TIZWFSkoMn6KZ6Qn3dFj3Jop3+E1tsc=
-github.com/nginxui/risefront v1.1.10/go.mod h1:QX3OyvazX3Mi/X2NZKl9ylDrFVUeaogwSMKyEsnRCHE=
-github.com/nginxui/risefront v1.2.0 h1:r/C5+mPs1V76EKEQl966Kl0UpbJnnC/a38ZLYtlvnT4=
-github.com/nginxui/risefront v1.2.0/go.mod h1:QX3OyvazX3Mi/X2NZKl9ylDrFVUeaogwSMKyEsnRCHE=
+github.com/nginxui/risefront v1.2.1 h1:CXu4c+bM6iBRVZHXQTUy9ceQa2p3YqIPNEdTPeCjIQ0=
+github.com/nginxui/risefront v1.2.1/go.mod h1:QX3OyvazX3Mi/X2NZKl9ylDrFVUeaogwSMKyEsnRCHE=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/nikoksr/notify v1.3.0 h1:UxzfxzAYGQD9a5JYLBTVx0lFMxeHCke3rPCkfWdPgLs=
 github.com/nikoksr/notify v1.3.0/go.mod h1:Xor2hMmkvrCfkCKvXGbcrESez4brac2zQjhd6U2BbeM=

+ 14 - 3
internal/upgrader/binary.go

@@ -9,8 +9,9 @@ import (
 )
 
 type Control struct {
-	DryRun  bool   `json:"dry_run"`
-	Channel string `json:"channel"`
+	DryRun               bool   `json:"dry_run"`
+	TestCommitAndRestart bool   `json:"test_commit_and_restart"`
+	Channel              string `json:"channel"`
 }
 
 // BinaryUpgrade Upgrade the binary
@@ -48,6 +49,16 @@ func BinaryUpgrade(ws *websocket.Conn, control *Control) {
 		}
 	}()
 
+	if control.TestCommitAndRestart {
+		err = u.TestCommitAndRestart()
+		if err != nil {
+			_ = ws.WriteJSON(CoreUpgradeResp{
+				Status:  UpgradeStatusError,
+				Message: "Test commit and restart error",
+			})
+		}
+	}
+
 	tarName, err := u.DownloadLatestRelease(progressChan)
 	if err != nil {
 		_ = ws.WriteJSON(CoreUpgradeResp{
@@ -71,7 +82,7 @@ func BinaryUpgrade(ws *websocket.Conn, control *Control) {
 		Message: "Performing core upgrade",
 	})
 
-	if settings.NodeSettings.Demo {
+	if control.DryRun || settings.NodeSettings.Demo {
 		return
 	}
 

+ 98 - 0
internal/upgrader/test_commit_restart.go

@@ -0,0 +1,98 @@
+package upgrader
+
+import (
+	"io"
+	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
+	"time"
+
+	"code.pfad.fr/risefront"
+	"github.com/minio/selfupdate"
+	"github.com/pkg/errors"
+)
+
+func (u *Upgrader) TestCommitAndRestart() error {
+	// Get the directory of the current executable
+	exDir := filepath.Dir(u.ExPath)
+	testBinaryPath := filepath.Join(exDir, "nginx-ui.test")
+
+	// Create temporary old file path
+	oldExe := filepath.Join(exDir, ".nginx-ui.old."+strconv.FormatInt(time.Now().Unix(), 10))
+
+	// Setup update options
+	opts := selfupdate.Options{
+		OldSavePath: oldExe,
+	}
+
+	// Check permissions
+	if err := opts.CheckPermissions(); err != nil {
+		return err
+	}
+
+	// Copy current executable to test file
+	srcFile, err := os.Open(u.ExPath)
+	if err != nil {
+		return errors.Wrap(err, "failed to open source executable")
+	}
+	defer srcFile.Close()
+
+	// Create destination file
+	destFile, err := os.Create(testBinaryPath)
+	if err != nil {
+		return errors.Wrap(err, "failed to create test executable")
+	}
+	defer destFile.Close()
+
+	// Copy file content
+	_, err = io.Copy(destFile, srcFile)
+	if err != nil {
+		return errors.Wrap(err, "failed to copy executable content")
+	}
+
+	// Set executable permissions
+	if err = destFile.Chmod(0755); err != nil {
+		return errors.Wrap(err, "failed to set executable permission")
+	}
+
+	// Reopen file for selfupdate
+	srcFile.Close()
+	srcFile, err = os.Open(testBinaryPath)
+	if err != nil {
+		return errors.Wrap(err, "failed to open test executable for update")
+	}
+	defer srcFile.Close()
+
+	// Prepare and check binary
+	if err = selfupdate.PrepareAndCheckBinary(srcFile, opts); err != nil {
+		var pathErr *os.PathError
+		if errors.As(err, &pathErr) {
+			return pathErr.Err
+		}
+		return err
+	}
+
+	// Commit binary update
+	if err = selfupdate.CommitBinary(opts); err != nil {
+		if rerr := selfupdate.RollbackError(err); rerr != nil {
+			return rerr
+		}
+		var pathErr *os.PathError
+		if errors.As(err, &pathErr) {
+			return pathErr.Err
+		}
+		return err
+	}
+
+	if runtime.GOOS != "windows" {
+		_ = os.Remove(oldExe)
+	}
+
+	// Wait for file to be written
+	time.Sleep(1 * time.Second)
+	
+	// Gracefully restart
+	risefront.Restart()
+	return nil
+}