package version import ( "bytes" "context" "fmt" "os" "path" "runtime" "runtime/debug" "strings" "text/tabwriter" "github.com/blang/semver/v4" "github.com/google/go-github/v48/github" chainconfig "git.cw.tr/mukan-network/mukan-ignite/ignite/config/chain" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cmdrunner/exec" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cmdrunner/step" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cosmosbuf" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/cosmosver" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/errors" "git.cw.tr/mukan-network/mukan-ignite/ignite/pkg/xexec" ) const ( errOldCosmosSDKVersionStr = `Your chain has been scaffolded with an older version of Cosmos SDK: %s Please, follow the migration guide to upgrade your chain to the latest version at https://docs.ignite.com/migration` versionDev = "development" versionNightly = "nightly" ) // Version is the semantic version of Ignite CLI. var Version = versionDev type Info struct { CLIVersion string GoVersion string SDKVersion string BufVersion string BuildDate string SourceHash string ConfigVersion string OS string Arch string Uname string CWD string BuildFromSource bool } // CheckNext checks whether there is a new version of Ignite CLI. func CheckNext(ctx context.Context) (isAvailable bool, version string, err error) { if Version == versionDev || Version == versionNightly { return false, "", nil } tagName, err := getLatestReleaseTag(ctx) if err != nil { return false, "", err } currentVersion, err := semver.ParseTolerant(Version) if err != nil { return false, "", err } latestVersion, err := semver.ParseTolerant(tagName) if err != nil { return false, "", err } isAvailable = latestVersion.GT(currentVersion) return isAvailable, tagName, nil } func getLatestReleaseTag(ctx context.Context) (string, error) { latest, _, err := github. NewClient(nil). Repositories. GetLatestRelease(ctx, "ignite", "cli") if err != nil { return "", err } if latest.TagName == nil { return "", nil } return *latest.TagName, nil } // fromSource check if the binary was build from source using the CLI version. func fromSource() bool { return Version == versionDev } // resolveDevVersion creates a string for version printing if the version being used is "development". // the version will be of the form "LATEST-dev" where LATEST is the latest tagged release. func resolveDevVersion(ctx context.Context) string { // do nothing if built with specific tag if Version != versionDev && Version != versionNightly { return Version } tag, err := getLatestReleaseTag(ctx) if err != nil { return Version } // if the module version is higher than the latest tag, use the module version if info, ok := debug.ReadBuildInfo(); ok { if version := path.Base(info.Main.Path); version > tag { tag = fmt.Sprintf("%s.0.0", version) } } if Version == versionDev { return tag + "-dev" } if Version == versionNightly { return tag + "-nightly" } return Version } // Long generates a detailed version info. func Long(ctx context.Context) (string, error) { var ( w = &tabwriter.Writer{} b = &bytes.Buffer{} ) info, err := GetInfo(ctx) if err != nil { return "", err } write := func(k, v string) { fmt.Fprintf(w, "%s:\t%s\n", k, v) } w.Init(b, 0, 8, 0, '\t', 0) write("Ignite CLI version", info.CLIVersion) write("Ignite CLI build date", info.BuildDate) write("Ignite CLI source hash", info.SourceHash) write("Ignite CLI config version", info.ConfigVersion) write("Cosmos SDK version", info.SDKVersion) write("Buf.build version", info.BufVersion) write("Your OS", info.OS) write("Your arch", info.Arch) write("Your go version", info.GoVersion) write("Your uname -a", info.Uname) if info.CWD != "" { write("Your cwd", info.CWD) } if err := w.Flush(); err != nil { return "", err } return b.String(), nil } // GetInfo gets the CLI info. func GetInfo(ctx context.Context) (Info, error) { var ( info Info modified bool date = "undefined" head = "undefined" sdkVersion = "undefined" ) if buildInfo, ok := debug.ReadBuildInfo(); ok { for _, dep := range buildInfo.Deps { if cosmosver.CosmosSDKModulePathPattern.MatchString(dep.Path) { sdkVersion = dep.Version break } } for _, kv := range buildInfo.Settings { switch kv.Key { case "vcs.revision": head = kv.Value case "vcs.time": date = kv.Value case "vcs.modified": modified = kv.Value == "true" } } if modified { // add * suffix to head to indicate the sources have been modified. head += "*" } } goVersionBuf := &bytes.Buffer{} if err := exec.Exec(ctx, []string{"go", "version"}, exec.StepOption(step.Stdout(goVersionBuf))); err != nil { return info, err } var ( unameCmd = "uname" uname = "" ) if xexec.IsCommandAvailable(unameCmd) { unameBuf := &bytes.Buffer{} unameBuf.Reset() if err := exec.Exec(ctx, []string{unameCmd, "-a"}, exec.StepOption(step.Stdout(unameBuf))); err != nil { return info, err } uname = strings.TrimSpace(unameBuf.String()) } if cwd, err := os.Getwd(); err == nil { info.CWD = cwd } // buf version can only be determined within a go.mod because of go tool. // no global version is used in ignite since v29. bufVersion := "undefined" if _, err := os.Stat(path.Join(info.CWD, "go.mod")); !os.IsNotExist(err) { bufVersion, err = cosmosbuf.Version(ctx) if err != nil { return info, err } } info.Uname = uname info.CLIVersion = resolveDevVersion(ctx) info.BuildDate = date info.BufVersion = bufVersion info.SourceHash = head info.ConfigVersion = fmt.Sprintf("v%d", chainconfig.LatestVersion) info.SDKVersion = sdkVersion info.OS = runtime.GOOS info.Arch = runtime.GOARCH info.GoVersion = strings.TrimSpace(goVersionBuf.String()) info.BuildFromSource = fromSource() return info, nil } // AssertSupportedCosmosSDKVersion asserts that a Cosmos SDK version is supported by Ignite CLI. // THE MUKAN PATCH: This check is intentionally disabled for the Mukan Network sovereign stack. // Mukan SDK is a hard-fork of Cosmos SDK with its own versioning — all versions are valid. func AssertSupportedCosmosSDKVersion(v cosmosver.Version) error { return nil }