-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate.go
142 lines (123 loc) · 3.85 KB
/
update.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"bytes"
"crypto/sha256"
"encoding/json"
"fmt"
"ftb-server-downloader/util"
semver "github.com/hashicorp/go-version"
"github.com/minio/selfupdate"
"github.com/pterm/pterm"
"io"
"net/http"
"os"
"runtime"
"strings"
)
const (
org = "FTBTeam"
repo = "FTB-Server-Installer"
)
type GHRelease struct {
TagName string `json:"tag_name"`
Name string `json:"name"`
Prerelease bool `json:"prerelease"`
Draft bool `json:"draft"`
}
type VersionInfo struct {
UpdateAvailable bool
CurrentVersion string
LatestVersion string
Name string
isPreReleaseOrDraft bool
}
func checkForUpdate() (VersionInfo, error) {
var versionInfo VersionInfo = VersionInfo{
UpdateAvailable: false,
CurrentVersion: util.ReleaseVersion,
LatestVersion: "",
Name: "",
isPreReleaseOrDraft: false,
}
releaseApi := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", org, repo)
resp, err := http.Get(releaseApi)
if err != nil {
return versionInfo, fmt.Errorf("error checking for update: %s", err.Error())
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return versionInfo, fmt.Errorf("bad status: %s", resp.Status)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return versionInfo, fmt.Errorf("error reading response body: %s", err.Error())
}
var release GHRelease
err = json.Unmarshal(data, &release)
if err != nil {
return versionInfo, fmt.Errorf("error unmarshalling response: %s", err.Error())
}
if release.Prerelease || release.Draft {
versionInfo.isPreReleaseOrDraft = true
return versionInfo, nil
}
versionInfo.LatestVersion = release.TagName
versionInfo.Name = release.Name
currentVersion, err := semver.NewVersion(strings.ReplaceAll(util.ReleaseVersion, "v", ""))
if err != nil {
return versionInfo, fmt.Errorf("error parsing current version: %s", err.Error())
}
latestVersion, err := semver.NewVersion(strings.ReplaceAll(versionInfo.LatestVersion, "v", ""))
if err != nil {
return versionInfo, fmt.Errorf("error parsing latest version: %s", err.Error())
}
if latestVersion.GreaterThan(currentVersion) {
versionInfo.UpdateAvailable = true
}
return versionInfo, nil
}
func doUpdate(versionInfo VersionInfo) error {
filename := fmt.Sprintf("ftb-server-%s-%s", strings.ToLower(runtime.GOOS), strings.ToLower(runtime.GOARCH))
if runtime.GOOS == "windows" {
filename += ".exe"
}
downloadUrl := fmt.Sprintf("https://github.com/%s/%s/releases/download/%s/%s", org, repo, versionInfo.LatestVersion, filename)
hashResp, err := http.Get(fmt.Sprintf("%s.sha256", downloadUrl))
if err != nil {
return fmt.Errorf("error downloading hash: %s", err.Error())
}
defer hashResp.Body.Close()
if hashResp.StatusCode != http.StatusOK {
return fmt.Errorf("error downloading hash: %s", hashResp.Status)
}
hashBytes, err := io.ReadAll(hashResp.Body)
if err != nil {
return fmt.Errorf("error reading hash response: %s", err.Error())
}
updateHash := strings.TrimSpace(string(hashBytes))
pterm.Debug.Println("Update Hash: ", updateHash)
resp, err := http.Get(downloadUrl)
if err != nil {
return fmt.Errorf("error downloading update: %s", err.Error())
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("error downloading update: %s", resp.Status)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("error reading update response: %s", err.Error())
}
binHashByte := sha256.Sum256(data)
binHash := fmt.Sprintf("%x", binHashByte)
if updateHash != binHash {
return fmt.Errorf("update hash does not match")
}
err = selfupdate.Apply(bytes.NewReader(data), selfupdate.Options{})
if err != nil {
return fmt.Errorf("error applying update: %s", err.Error())
}
pterm.Success.Println("Update successful!\nPlease restart the installer to use the new version.")
os.Exit(0)
return nil
}