diff --git a/cmd/root.go b/cmd/root.go index 0dadd711..9719efd0 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -124,6 +124,12 @@ func init() { } func Execute() { + go func() { + err := detectVersion() + if err != nil { + logger.Warnln(err) + } + }() if err := rootCmd.Execute(); err != nil { fmt.Println(err) } diff --git a/cmd/version.go b/cmd/version.go index be98d8fb..909fbd73 100644 --- a/cmd/version.go +++ b/cmd/version.go @@ -1,7 +1,9 @@ package cmd import ( + "context" "fmt" + "kyanos/common" "github.com/spf13/cobra" ) @@ -29,3 +31,21 @@ var ( func init() { rootCmd.AddCommand(versionCmd) } + +func detectVersion() error { + localVersion, err := common.LocalVersion(Version) + if err != nil { + return fmt.Errorf("Failed to detect local version: %v", err) + } + ctx, cancel := context.WithCancel(context.TODO()) + defer cancel() + + remoteVersion, downloadUrl, err := common.RemoteVersion(ctx) + if err != nil { + return fmt.Errorf("Failed to detect remote version: %v", err) + } + if localVersion.LessThan(remoteVersion) { + return fmt.Errorf("Kyanos version %s is available, please download from %s", remoteVersion, downloadUrl) + } + return nil +} diff --git a/common/version.go b/common/version.go new file mode 100644 index 00000000..5929db51 --- /dev/null +++ b/common/version.go @@ -0,0 +1,41 @@ +package common + +import ( + "context" + "fmt" + "strings" + + "github.com/google/go-github/v68/github" + "github.com/hashicorp/go-version" +) + +func RemoteVersion(ctx context.Context) (*version.Version, string, error) { + client := github.NewClient(nil) + releases, _, err := client.Repositories.GetLatestRelease(ctx, "hengyoush", "kyanos") + if err != nil { + return nil, "", err + } + arch, err := UnameMachine() + if err != nil { + return nil, "", err + } + gitReposVer, err := version.NewVersion(*releases.TagName) + if err != nil { + return nil, "", fmt.Errorf("error parsing github Repository version: %v", err) + } + versionInt := strings.TrimPrefix(*releases.TagName, "v") + kyanosAsset := fmt.Sprintf("kyanos_%s_linux_%s.tar.gz", versionInt, arch) + for _, asset := range releases.Assets { + if *asset.Name == kyanosAsset { + return gitReposVer, *asset.BrowserDownloadURL, nil + } + } + return nil, "", fmt.Errorf("no asset found for %s in github release", kyanosAsset) +} + +func LocalVersion(tag string) (*version.Version, error) { + if !strings.HasPrefix(tag, "v") { + tag = "v" + tag + } + return version.NewVersion(tag) +} diff --git a/common/version_test.go b/common/version_test.go new file mode 100644 index 00000000..54510b81 --- /dev/null +++ b/common/version_test.go @@ -0,0 +1,14 @@ +package common + +import "testing" + +func TestLocalVersion(t *testing.T) { + testLocalVersion := "0.0.1" + localVersion, err := LocalVersion(testLocalVersion) + if err != nil { + t.Errorf("LocalVersion(%s) failed: %v", testLocalVersion, err) + } + if localVersion.Original() != "v0.0.1" { + t.Errorf("LocalVersion(%s) failed: %v", testLocalVersion, localVersion) + } +} diff --git a/go.mod b/go.mod index a913d8e6..7398a675 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/docker/docker v27.3.1+incompatible github.com/emirpasic/gods v1.18.1 github.com/go-logr/logr v1.4.2 + github.com/google/go-github/v68 v68.0.0 github.com/google/gops v0.3.28 github.com/hashicorp/go-version v1.7.0 github.com/jefurry/logrus v2.0.6+incompatible @@ -70,6 +71,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect diff --git a/go.sum b/go.sum index 8e9ecdb1..c8d1c63c 100644 --- a/go.sum +++ b/go.sum @@ -127,9 +127,14 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v68 v68.0.0 h1:ZW57zeNZiXTdQ16qrDiZ0k6XucrxZ2CGmoTvcCyQG6s= +github.com/google/go-github/v68 v68.0.0/go.mod h1:K9HAUBovM2sLwM408A18h+wd9vqdLOEqTUCbnRIcx68= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gops v0.3.28 h1:2Xr57tqKAmQYRAfG12E+yLcoa2Y42UJo2lOrUFL9ark= github.com/google/gops v0.3.28/go.mod h1:6f6+Nl8LcHrzJwi8+p0ii+vmBFSlB4f8cOOkTJ7sk4c= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=