version.go

 1package version
 2
 3import (
 4	"encoding/json"
 5	"io/fs"
 6	"os"
 7	"runtime/debug"
 8
 9	"shelley.exe.dev/ui"
10)
11
12// Version and Tag are set at build time via ldflags
13var (
14	Version = "dev"
15	Tag     = ""
16)
17
18// Info holds build information from runtime/debug.ReadBuildInfo
19type Info struct {
20	Version    string `json:"version,omitempty"`
21	Tag        string `json:"tag,omitempty"`
22	Commit     string `json:"commit,omitempty"`
23	CommitTime string `json:"commit_time,omitempty"`
24	Modified   bool   `json:"modified,omitempty"`
25}
26
27// GetInfo returns build information using runtime/debug.ReadBuildInfo,
28// falling back to the embedded build-info.json from the UI build.
29// The SHELLEY_VERSION_OVERRIDE environment variable can override the tag for testing.
30func GetInfo() Info {
31	tag := Tag
32	if override := os.Getenv("SHELLEY_VERSION_OVERRIDE"); override != "" {
33		tag = override
34	}
35
36	info := Info{
37		Version: Version,
38		Tag:     tag,
39	}
40
41	buildInfo, ok := debug.ReadBuildInfo()
42	if ok {
43		for _, setting := range buildInfo.Settings {
44			switch setting.Key {
45			case "vcs.revision":
46				info.Commit = setting.Value
47			case "vcs.time":
48				info.CommitTime = setting.Value
49			case "vcs.modified":
50				info.Modified = setting.Value == "true"
51			}
52		}
53	}
54
55	// If we didn't get vcs info from debug.ReadBuildInfo, try the embedded build-info.json
56	if info.Commit == "" {
57		if data, err := fs.ReadFile(ui.Dist, "dist/build-info.json"); err == nil {
58			var buildJSON struct {
59				Commit     string `json:"commit"`
60				CommitTime string `json:"commitTime"`
61				Modified   bool   `json:"modified"`
62			}
63			if json.Unmarshal(data, &buildJSON) == nil {
64				info.Commit = buildJSON.Commit
65				info.CommitTime = buildJSON.CommitTime
66				info.Modified = buildJSON.Modified
67			}
68		}
69	}
70
71	return info
72}