diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dbcd4710..c3b16c5b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -142,6 +142,18 @@ jobs: with: go-version: ^1.23.0 + - name: Download app artifacts + uses: actions/download-artifact@v4 + with: + name: app-dist + path: app/dist + + - name: Generate files + env: + GOOS: linux + GOARCH: amd64 + run: go generate + - name: Setup compiler environment id: info run: | @@ -182,12 +194,6 @@ jobs: echo "CXX=${{ env.ARCH_NAME }}-clang++" >> $GITHUB_ENV echo "LD_FLAGS=-w" >> $GITHUB_ENV - - name: Download app artifacts - uses: actions/download-artifact@v4 - with: - name: app-dist - path: app/dist - - name: Build run: | mkdir -p dist diff --git a/.gitignore b/.gitignore index e910352e..ff4cf5b2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ app/.env app/.status_hash .idea/deployment.xml .idea/webServers.xml +*.gen.go .devcontainer/go-path .devcontainer/data .devcontainer/casdoor.pem diff --git a/api/cluster/node.go b/api/cluster/node.go index 7544ed23..399b9807 100644 --- a/api/cluster/node.go +++ b/api/cluster/node.go @@ -1,14 +1,16 @@ package cluster import ( + "net/http" + "github.com/0xJacky/Nginx-UI/api" analytic2 "github.com/0xJacky/Nginx-UI/internal/analytic" "github.com/0xJacky/Nginx-UI/internal/upgrader" + "github.com/0xJacky/Nginx-UI/internal/version" "github.com/dustin/go-humanize" "github.com/gin-gonic/gin" "github.com/shirou/gopsutil/v4/cpu" "github.com/shirou/gopsutil/v4/disk" - "net/http" ) func GetCurrentNode(c *gin.Context) { @@ -26,7 +28,7 @@ func GetCurrentNode(c *gin.Context) { } cpuInfo, _ := cpu.Info() memory, _ := analytic2.GetMemoryStat() - ver, _ := upgrader.GetCurrentVersion() + ver := version.GetVersionInfo() diskUsage, _ := disk.Usage(".") nodeInfo := analytic2.NodeInfo{ diff --git a/api/system/upgrade.go b/api/system/upgrade.go index 3dbd3478..d3c96ce0 100644 --- a/api/system/upgrade.go +++ b/api/system/upgrade.go @@ -1,14 +1,16 @@ package system import ( + "net/http" + "os" + "github.com/0xJacky/Nginx-UI/api" "github.com/0xJacky/Nginx-UI/internal/upgrader" + "github.com/0xJacky/Nginx-UI/internal/version" "github.com/0xJacky/Nginx-UI/settings" "github.com/gin-gonic/gin" "github.com/gorilla/websocket" "github.com/uozi-tech/cosy/logger" - "net/http" - "os" ) func GetRelease(c *gin.Context) { @@ -32,13 +34,7 @@ func GetRelease(c *gin.Context) { } func GetCurrentVersion(c *gin.Context) { - curVer, err := upgrader.GetCurrentVersion() - if err != nil { - api.ErrHandler(c, err) - return - } - - c.JSON(http.StatusOK, curVer) + c.JSON(http.StatusOK, version.GetVersionInfo()) } const ( diff --git a/app/app.go b/app/app.go index f00ad958..0079d34d 100644 --- a/app/app.go +++ b/app/app.go @@ -8,5 +8,3 @@ import ( //go:embed i18n.json dist/* dist/*/* src/language/* src/language/*/* var DistFS embed.FS - -var VersionPath = "dist/version.json" diff --git a/app/app_unembed.go b/app/app_unembed.go index 43733be7..db848603 100644 --- a/app/app_unembed.go +++ b/app/app_unembed.go @@ -4,7 +4,5 @@ package app import "embed" -//go:embed i18n.json src/language/* src/language/*/* src/version.json +//go:embed i18n.json src/language/* src/language/*/* var DistFS embed.FS - -var VersionPath = "src/version.json" diff --git a/cmd/version/generate.go b/cmd/version/generate.go new file mode 100644 index 00000000..304f16f8 --- /dev/null +++ b/cmd/version/generate.go @@ -0,0 +1,81 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "io/fs" + "log" + "os" + "path" + "runtime" +) + +type VersionInfo struct { + Version string `json:"version"` + BuildId int `json:"build_id"` + TotalBuild int `json:"total_build"` +} + +func main() { + _, file, _, ok := runtime.Caller(0) + if !ok { + log.Print("Unable to get the current file") + return + } + basePath := path.Join(path.Dir(file), "../../") + + versionFile, err := os.Open(path.Join(basePath, "app/dist/version.json")) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + log.Print("\"dist/version.json\" not found, load from src instead") + versionFile, err = os.Open(path.Join(basePath, "app/src/version.json")) + } + + if err != nil { + log.Fatal(err) + return + } + } + + defer func(versionFile fs.File) { + err := versionFile.Close() + if err != nil { + log.Fatal(err) + } + }(versionFile) + + // Read the version.json file + data, err := io.ReadAll(versionFile) + if err != nil { + log.Fatalf("Failed to read version.json: %v", err) + } + + // Parse the JSON data + var versionInfo VersionInfo + err = json.Unmarshal(data, &versionInfo) + if err != nil { + log.Fatalf("Failed to parse JSON: %v", err) + } + + // Generate the version.gen.go file content + genContent := fmt.Sprintf(`// Code generated by cmd/version/generate.go; DO NOT EDIT. + +package version + +func init() { + Version = "%s" + BuildId = %d + TotalBuild = %d +} +`, versionInfo.Version, versionInfo.BuildId, versionInfo.TotalBuild) + + genPath := path.Join(basePath, "internal/version/version.gen.go") + err = os.WriteFile(genPath, []byte(genContent), 0644) + if err != nil { + log.Fatalf("Failed to write version.gen.go: %v", err) + } + + fmt.Println("version.gen.go has been generated successfully.") +} diff --git a/go.mod b/go.mod index 3527ff95..87b1b5a8 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,6 @@ require ( github.com/dgraph-io/ristretto/v2 v2.1.0 github.com/dustin/go-humanize v1.0.1 github.com/elliotchance/orderedmap/v3 v3.1.0 - github.com/fatih/color v1.18.0 github.com/gin-contrib/static v1.1.3 github.com/gin-gonic/gin v1.10.0 github.com/go-acme/lego/v4 v4.21.0 @@ -31,13 +30,13 @@ require ( github.com/pretty66/websocketproxy v0.0.0-20220507015215-930b3a686308 github.com/samber/lo v1.49.1 github.com/sashabaranov/go-openai v1.36.1 - github.com/shirou/gopsutil/v4 v4.25.1 + github.com/shirou/gopsutil/v4 v4.24.12 github.com/spf13/cast v1.7.1 github.com/stretchr/testify v1.10.0 github.com/tufanbarisyildirim/gonginx v0.0.0-20250120210832-12a9c7ae0c8a github.com/uozi-tech/cosy v1.14.3 - github.com/uozi-tech/cosy-driver-sqlite v0.2.1 - go.uber.org/zap v1.27.0 + github.com/uozi-tech/cosy-driver-sqlite v0.2.0 + github.com/urfave/cli/v3 v3.0.0-beta1 golang.org/x/crypto v0.32.0 golang.org/x/net v0.34.0 gopkg.in/ini.v1 v1.67.0 @@ -107,6 +106,7 @@ require ( github.com/dnsimple/dnsimple-go v1.7.0 // indirect github.com/ebitengine/purego v0.8.2 // indirect github.com/exoscale/egoscale/v3 v3.1.9 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.8.0 // indirect @@ -253,6 +253,7 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.13.0 // indirect golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c // indirect golang.org/x/mod v0.22.0 // indirect diff --git a/go.sum b/go.sum index aca9221a..da38b3c2 100644 --- a/go.sum +++ b/go.sum @@ -1658,8 +1658,6 @@ github.com/selectel/go-selvpcclient/v3 v3.2.1 h1:ny6WIAMiHzKxOgOEnwcWE79wIQij1AH github.com/selectel/go-selvpcclient/v3 v3.2.1/go.mod h1:3EfSf8aEWyhspOGbvZ6mvnFg7JN5uckxNyBFPGWsXNQ= github.com/shirou/gopsutil/v4 v4.24.12 h1:qvePBOk20e0IKA1QXrIIU+jmk+zEiYVVx06WjBRlZo4= github.com/shirou/gopsutil/v4 v4.24.12/go.mod h1:DCtMPAad2XceTeIAbGyVfycbYQNBGk2P8cvDi7/VN9o= -github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= -github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= @@ -1783,9 +1781,9 @@ github.com/uozi-tech/cosy-driver-postgres v0.2.1 h1:OICakGuT+omva6QOJCxTJ5Lfr7CG github.com/uozi-tech/cosy-driver-postgres v0.2.1/go.mod h1:eAy1A89yHbAEfjkhNAifaJQk172NqrNoRyRtFcZc9Go= github.com/uozi-tech/cosy-driver-sqlite v0.2.0 h1:eTpIMyGoFUK4JcaiKfJHD5AyiM6vtCwN98c7Bz5n25o= github.com/uozi-tech/cosy-driver-sqlite v0.2.0/go.mod h1:87a6mzn5IuEtIR4z7U4Ey8eKLGfNEOSkv7kPQlbNQgM= -github.com/uozi-tech/cosy-driver-sqlite v0.2.1 h1:W+Z4pY25PSJCeReqroG7LIBeffsqotbpHzgqSMqZDIM= -github.com/uozi-tech/cosy-driver-sqlite v0.2.1/go.mod h1:2ya7Z5P3HzFi1ktfL8gvwaAGx0DDV0bmWxNSNpaLlwo= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/urfave/cli/v3 v3.0.0-beta1 h1:6DTaaUarcM0wX7qj5Hcvs+5Dm3dyUTBbEwIWAjcw9Zg= +github.com/urfave/cli/v3 v3.0.0-beta1/go.mod h1:FnIeEMYu+ko8zP1F9Ypr3xkZMIDqW3DR92yUtY39q1Y= github.com/vinyldns/go-vinyldns v0.9.16 h1:GZJStDkcCk1F1AcRc64LuuMh+ENL8pHA0CVd4ulRMcQ= github.com/vinyldns/go-vinyldns v0.9.16/go.mod h1:5qIJOdmzAnatKjurI+Tl4uTus7GJKJxb+zitufjHs3Q= github.com/volcengine/volc-sdk-golang v1.0.194 h1:3o0INQzdtYJWvdGrtX02booCqPL5TsWSq2W1Ur7Bzlo= diff --git a/internal/cmd/main.go b/internal/cmd/main.go new file mode 100644 index 00000000..68476e13 --- /dev/null +++ b/internal/cmd/main.go @@ -0,0 +1,50 @@ +package cmd + +import ( + "context" + "fmt" + "log" + "os" + + "github.com/0xJacky/Nginx-UI/internal/version" + "github.com/urfave/cli/v3" +) + +func NewAppCmd() *cli.Command { + serve := false + + cmd := &cli.Command{ + Name: "nginx-ui", + Usage: "Yet another Nginx Web UI", + Commands: []*cli.Command{ + { + Name: "serve", + Usage: "Start the Nginx-UI server", + Action: func(ctx context.Context, command *cli.Command) error { + serve = true + return nil + }, + }, + }, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "config", + Value: "app.ini", + Usage: "configuration file path", + }, + }, + DefaultCommand: "serve", + Version: version.Version, + } + + cli.VersionPrinter = func(cmd *cli.Command) { + fmt.Printf("%s (%d)\n", cmd.Root().Version, version.BuildId) + } + + if err := cmd.Run(context.Background(), os.Args); err != nil { + log.Fatal(err) + } else if !serve { + os.Exit(0) + } + return cmd +} diff --git a/internal/upgrader/info.go b/internal/upgrader/info.go index 3bede803..96252120 100644 --- a/internal/upgrader/info.go +++ b/internal/upgrader/info.go @@ -1,12 +1,10 @@ package upgrader import ( - "encoding/json" "os" "path/filepath" "runtime" - "github.com/0xJacky/Nginx-UI/app" "github.com/pkg/errors" ) @@ -42,19 +40,3 @@ func GetRuntimeInfo() (r RuntimeInfo, err error) { return } - -func GetCurrentVersion() (c CurVersion, err error) { - verJson, err := app.DistFS.ReadFile(app.VersionPath) - if err != nil { - err = errors.Wrap(err, "service.GetCurrentVersion ReadFile err") - return - } - - err = json.Unmarshal(verJson, &c) - if err != nil { - err = errors.Wrap(err, "service.GetCurrentVersion json.Unmarshal err") - return - } - - return -} diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 00000000..4eecdad1 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,26 @@ +package version + +var ( + Version = "" + BuildId = 0 + TotalBuild = 0 +) + +type Info struct { + Version string `json:"version"` + BuildId int `json:"build_id"` + TotalBuild int `json:"total_build"` +} + +var versionInfo *Info + +func GetVersionInfo() *Info { + if versionInfo == nil { + versionInfo = &Info{ + Version: Version, + BuildId: BuildId, + TotalBuild: TotalBuild, + } + } + return versionInfo +} diff --git a/main.go b/main.go index 838f9281..db97a73e 100644 --- a/main.go +++ b/main.go @@ -2,11 +2,11 @@ package main import ( "errors" - "flag" "fmt" "net/http" "time" + "github.com/0xJacky/Nginx-UI/internal/cmd" "github.com/0xJacky/Nginx-UI/internal/kernel" "github.com/0xJacky/Nginx-UI/model" "github.com/0xJacky/Nginx-UI/router" @@ -20,6 +20,8 @@ import ( cSettings "github.com/uozi-tech/cosy/settings" ) +//go:generate go run cmd/version/generate.go + func Program(confPath string) func(state overseer.State) { return func(state overseer.State) { defer logger.Sync() @@ -59,12 +61,10 @@ func Program(confPath string) func(state overseer.State) { } func main() { - var confPath string - flag.StringVar(&confPath, "config", "app.ini", "Specify the configuration file") - flag.Parse() + appCmd := cmd.NewAppCmd() + confPath := appCmd.String("config") settings.Init(confPath) - overseer.Run(overseer.Config{ Program: Program(confPath), Address: fmt.Sprintf("%s:%d", cSettings.ServerSettings.Host, cSettings.ServerSettings.Port),