github.com/databricks/cli@v0.203.0/internal/build/info.go (about) 1 package build 2 3 import ( 4 "fmt" 5 "runtime/debug" 6 "strconv" 7 "sync" 8 "time" 9 10 "golang.org/x/mod/semver" 11 ) 12 13 type Info struct { 14 ProjectName string 15 Version string 16 17 Branch string 18 Tag string 19 ShortCommit string 20 FullCommit string 21 CommitTime time.Time 22 Summary string 23 24 Major int64 25 Minor int64 26 Patch int64 27 Prerelease string 28 IsSnapshot bool 29 BuildTime time.Time 30 } 31 32 var info Info 33 34 var once sync.Once 35 36 // getDefaultBuildVersion uses build information stored by Go itself 37 // to synthesize a build version if one wasn't set. 38 // This is necessary if the binary was not built through goreleaser. 39 func getDefaultBuildVersion() string { 40 bi, ok := debug.ReadBuildInfo() 41 if !ok { 42 panic("unable to read build info") 43 } 44 45 m := make(map[string]string) 46 for _, s := range bi.Settings { 47 m[s.Key] = s.Value 48 } 49 50 out := "0.0.0-dev" 51 52 // Append revision as build metadata. 53 if v, ok := m["vcs.revision"]; ok { 54 // First 12 characters of the commit SHA is plenty to identify one. 55 out = fmt.Sprintf("%s+%s", out, v[0:12]) 56 } 57 58 return out 59 } 60 61 func initialize() { 62 // If buildVersion is empty it means the binary was NOT built through goreleaser. 63 // We try to pull version information from debug.BuildInfo(). 64 if buildVersion == "" { 65 buildVersion = getDefaultBuildVersion() 66 } 67 68 // Confirm that buildVersion is valid semver. 69 // Note that the semver package requires a leading 'v'. 70 if !semver.IsValid("v" + buildVersion) { 71 panic(fmt.Sprintf(`version is not a valid semver string: "%s"`, buildVersion)) 72 } 73 74 info = Info{ 75 ProjectName: buildProjectName, 76 Version: buildVersion, 77 78 Branch: buildBranch, 79 Tag: buildTag, 80 ShortCommit: buildShortCommit, 81 FullCommit: buildFullCommit, 82 CommitTime: parseTime(buildCommitTimestamp), 83 Summary: buildSummary, 84 85 Major: parseInt(buildMajor), 86 Minor: parseInt(buildMinor), 87 Patch: parseInt(buildPatch), 88 Prerelease: buildPrerelease, 89 IsSnapshot: parseBool(buildIsSnapshot), 90 BuildTime: parseTime(buildTimestamp), 91 } 92 } 93 94 func GetInfo() Info { 95 once.Do(initialize) 96 return info 97 } 98 99 func parseInt(s string) int64 { 100 i, err := strconv.ParseInt(s, 10, 64) 101 if err != nil { 102 panic(err) 103 } 104 return i 105 } 106 107 func parseBool(s string) bool { 108 b, err := strconv.ParseBool(s) 109 if err != nil { 110 panic(err) 111 } 112 return b 113 } 114 115 func parseTime(s string) time.Time { 116 return time.Unix(parseInt(s), 0) 117 }