-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
4 changed files
with
45 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,96 @@ | ||
package updatecheck | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
config "github.com/OliveTin/OliveTin/internal/config" | ||
installationinfo "github.com/OliveTin/OliveTin/internal/installationinfo" | ||
"github.com/google/uuid" | ||
"github.com/OliveTin/OliveTin/internal/installationinfo" | ||
"github.com/robfig/cron/v3" | ||
log "github.com/sirupsen/logrus" | ||
"io" | ||
"net/http" | ||
"os" | ||
) | ||
|
||
type updateRequest struct { | ||
CurrentVersion string | ||
CurrentCommit string | ||
OS string | ||
Arch string | ||
InstallationID string | ||
InContainer bool | ||
} | ||
|
||
// AvailableVersion is updated when checking with the update service. | ||
var AvailableVersion = "none" | ||
|
||
// CurrentVersion is set by the main cmd (which is in tern set as a compile constant) | ||
var CurrentVersion = "?" | ||
|
||
func installationID(filename string) string { | ||
var content string | ||
contentBytes, err := os.ReadFile(filename) | ||
|
||
if err != nil { | ||
fileHandle, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) | ||
|
||
if err != nil { | ||
log.Warnf("Could not read + create installation ID file: %v", err) | ||
return "cant-create" | ||
} | ||
|
||
content = uuid.NewString() | ||
fileHandle.WriteString(content) | ||
fileHandle.Close() | ||
} else { | ||
content = string(contentBytes) | ||
|
||
_, err := uuid.Parse(content) | ||
|
||
if err != nil { | ||
log.Errorf("Invalid installation ID, %v", err) | ||
content = "invalid-installation-id" | ||
} | ||
} | ||
|
||
log.WithFields(log.Fields{ | ||
"content": content, | ||
"from": filename, | ||
}).Infof("Installation ID") | ||
|
||
return content | ||
type versionMapType struct { | ||
ApiVersion int | ||
Latest string | ||
History map[string]string | ||
} | ||
|
||
// StartUpdateChecker will start a job that runs periodically, checking | ||
// for updates. | ||
func StartUpdateChecker(currentVersion string, currentCommit string, cfg *config.Config, configDir string) { | ||
CurrentVersion = currentVersion | ||
|
||
func StartUpdateChecker(cfg *config.Config) { | ||
if !cfg.CheckForUpdates { | ||
installationinfo.Runtime.AvailableVersion = "none" | ||
log.Warn("Update checking is disabled") | ||
return | ||
} | ||
|
||
payload := updateRequest{ | ||
CurrentVersion: currentVersion, | ||
CurrentCommit: currentCommit, | ||
OS: installationinfo.Runtime.OS, | ||
Arch: installationinfo.Runtime.Arch, | ||
InstallationID: installationID(configDir + "/installation-id.txt"), | ||
InContainer: installationinfo.Runtime.InContainer, | ||
} | ||
|
||
s := cron.New(cron.WithSeconds()) | ||
s := cron.New() | ||
|
||
// Several values have been tried here. | ||
// 1st: Every 24h - very spammy. | ||
// 2nd: Every 7d - (168 hours - much more reasonable, but it checks in at the same time/day each week. | ||
// Current: Every 100h is not so spammy, and has the advantage that the checkin time "shifts" hours. | ||
s.AddFunc("@every 100h", func() { | ||
actualCheckForUpdate(payload) | ||
actualCheckForUpdate() | ||
}) | ||
|
||
go actualCheckForUpdate(payload) // On startup | ||
go actualCheckForUpdate() // On startup | ||
|
||
go s.Start() | ||
} | ||
|
||
func doRequest(jsonUpdateRequest []byte) string { | ||
req, err := http.NewRequest("POST", "http://update-check.olivetin.app", bytes.NewBuffer(jsonUpdateRequest)) | ||
func parseVersion(input []byte) string { | ||
versionMap := &versionMapType{} | ||
|
||
err := json.Unmarshal(input, &versionMap) | ||
|
||
if err != nil { | ||
log.Warnf("Update check unmarshal failure: %v", err) | ||
return "error-during-check" | ||
} else { | ||
log.Infof("Update check remote version: %+v", versionMap) | ||
|
||
if installationinfo.Build.Version != versionMap.Latest { | ||
return versionMap.Latest | ||
} else { | ||
return "none" | ||
} | ||
} | ||
} | ||
|
||
func doRequest() string { | ||
req, err := http.NewRequest("GET", "http://update-check.olivetin.app/versions.json", nil) | ||
|
||
if err != nil { | ||
log.Errorf("Update check failed %v", err) | ||
return "" | ||
} | ||
|
||
req.Header.Set("Content-Type", "application/json") | ||
|
||
resp, err := http.DefaultClient.Do(req) | ||
|
||
if err != nil { | ||
log.Errorf("Update check failed %v", err) | ||
return "" | ||
} | ||
|
||
newVersion, _ := io.ReadAll(resp.Body) | ||
versionMap, _ := io.ReadAll(resp.Body) | ||
|
||
defer resp.Body.Close() | ||
|
||
return string(newVersion) | ||
return parseVersion(versionMap) | ||
} | ||
|
||
func actualCheckForUpdate(payload updateRequest) { | ||
jsonUpdateRequest, err := json.Marshal(payload) | ||
|
||
log.Debugf("Update request payload: %+v", payload) | ||
|
||
if err != nil { | ||
log.Errorf("Update check failed %v", err) | ||
return | ||
func actualCheckForUpdate() { | ||
if installationinfo.Build.Version == "dev" && os.Getenv("OLIVETIN_FORCE_UPDATE_CHECK") == "" { | ||
installationinfo.Runtime.AvailableVersion = "you-are-using-a-dev-build" | ||
} else { | ||
installationinfo.Runtime.AvailableVersion = doRequest() | ||
} | ||
|
||
AvailableVersion = doRequest(jsonUpdateRequest) | ||
|
||
log.WithFields(log.Fields{ | ||
"NewVersion": AvailableVersion, | ||
"CurrentVersion": installationinfo.Build.Version, | ||
"NewVersion": installationinfo.Runtime.AvailableVersion, | ||
}).Infof("Update check complete") | ||
} |