version.go RawHistoryFolder
1package common
2
3import (
4 "encoding/json"
5 "fmt"
6 "io"
7 "log"
8 "net/http"
9 "runtime"
10 "time"
11
12 "github.com/bnema/gordon/pkg/docker"
13 "github.com/fatih/color"
14)
15
16type CurrentVersion struct {
17 isContainer bool
18 Version string `json:"version"`
19}
20
21type ArchVersion struct {
22 Name string `json:"name"`
23}
24
25type VersionInfo struct {
26 Name string `json:"name"`
27}
28
29type VersionsResponse struct {
30 Name string `json:"name"`
31 AMD64 VersionInfo `json:"amd64"`
32 ARM64 VersionInfo `json:"arm64"`
33}
34
35func GetCurrentBuildVersionInfo(c *Config) CurrentVersion {
36 return CurrentVersion{
37 isContainer: docker.IsRunningInContainer(),
38 Version: c.GetVersion(),
39 }
40}
41
42func CheckForNewVersion(localVersion, remoteVersion string) string {
43 if localVersion != remoteVersion {
44 return "A new version is available"
45 }
46 return ""
47}
48
49func getArch() string {
50 return runtime.GOARCH
51}
52
53func checkAndUpdateVersion(c *Config) (string, error) {
54 localVersion := GetCurrentBuildVersionInfo(c)
55 remoteVersions, err := getRemoteVersion(c)
56 if err != nil {
57 return "", err
58 }
59
60 var remoteVersion string
61 switch getArch() {
62 case "amd64":
63 remoteVersion = remoteVersions.AMD64.Name
64 case "arm64":
65 remoteVersion = remoteVersions.ARM64.Name
66 default:
67 remoteVersion = remoteVersions.Name
68 }
69
70 remoteVersion = remoteVersion[:len(remoteVersion)-len(getArch())-1]
71 message := CheckForNewVersion(localVersion.Version, remoteVersion)
72
73 // if local version is empty that means dev mode is on so we don't need to check for updates
74 if localVersion.Version == "" {
75 return "", nil
76 }
77
78 if message != "" {
79 // Create a new color attribute
80 green := color.New(color.FgGreen).SprintFunc()
81 // Use the color attribute to format the string with ANSI codes
82 coloredMessage := green(fmt.Sprintf("New version %s is available", remoteVersion))
83 return coloredMessage, nil
84 }
85
86 return "", nil
87
88}
89
90func CheckVersionPeriodically(c *Config) (string, error) {
91 // Perform an immediate check.
92 newVersionMessage, err := checkAndUpdateVersion(c)
93
94 if err != nil {
95 return "", err
96 }
97
98 if newVersionMessage != "" {
99 fmt.Println(newVersionMessage)
100 return "", nil
101 }
102
103 // Set up a ticker to check every 5 minutes.
104 timer := time.NewTicker(5 * time.Minute)
105 defer timer.Stop()
106
107 for range timer.C {
108 newVersionMessage, err = checkAndUpdateVersion(c)
109 if err != nil {
110 log.Printf("Error fetching remote version: %s", err)
111 continue
112 }
113
114 if newVersionMessage != "" {
115 fmt.Println(newVersionMessage)
116 return "", nil //We return so the loop stops in case of a new version
117 }
118 }
119
120 return "", nil
121}
122
123// func getLocalVersion(c *Config) CurrentVersion {
124// // Dummy implementation, replace with your actual logic
125// return CurrentVersion{Version: "0.0.970"} // Example version
126// }
127
128func getRemoteVersion(c *Config) (VersionsResponse, error) {
129 proxyURL := c.Build.ProxyURL
130 if proxyURL == "" {
131 return VersionsResponse{}, fmt.Errorf("proxy URL is empty")
132 }
133
134 checkVersionEndpoint := proxyURL + "/version"
135 resp, err := http.Get(checkVersionEndpoint)
136 if err != nil {
137 return VersionsResponse{}, err
138 }
139
140 defer resp.Body.Close()
141
142 body, err := io.ReadAll(resp.Body)
143 if err != nil {
144 return VersionsResponse{}, err
145 }
146
147 var remoteVersionInfo VersionsResponse
148 err = json.Unmarshal(body, &remoteVersionInfo)
149 if err != nil {
150 return VersionsResponse{}, err
151 }
152
153 return remoteVersionInfo, nil
154
155}