updateCheck.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package updatecheck
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. config "github.com/OliveTin/OliveTin/internal/config"
  6. installationinfo "github.com/OliveTin/OliveTin/internal/installationinfo"
  7. "github.com/google/uuid"
  8. "github.com/robfig/cron/v3"
  9. log "github.com/sirupsen/logrus"
  10. "io/ioutil"
  11. "net/http"
  12. "os"
  13. )
  14. type updateRequest struct {
  15. CurrentVersion string
  16. CurrentCommit string
  17. OS string
  18. Arch string
  19. InstallationID string
  20. InContainer bool
  21. }
  22. // AvailableVersion is updated when checking with the update service.
  23. var AvailableVersion = "none"
  24. // CurrentVersion is set by the main cmd (which is in tern set as a compile constant)
  25. var CurrentVersion = "?"
  26. func installationID(filename string) string {
  27. var content string
  28. contentBytes, err := ioutil.ReadFile(filename)
  29. if err != nil {
  30. fileHandle, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
  31. if err != nil {
  32. log.Warnf("Could not read + create installation ID file: %v", err)
  33. return "cant-create"
  34. }
  35. content = uuid.NewString()
  36. fileHandle.WriteString(content)
  37. fileHandle.Close()
  38. } else {
  39. content = string(contentBytes)
  40. _, err := uuid.Parse(content)
  41. if err != nil {
  42. log.Errorf("Invalid installation ID, %v", err)
  43. content = "invalid-installation-id"
  44. }
  45. }
  46. log.WithFields(log.Fields{
  47. "content": content,
  48. "from": filename,
  49. }).Infof("Installation ID")
  50. return content
  51. }
  52. // StartUpdateChecker will start a job that runs periodically, checking
  53. // for updates.
  54. func StartUpdateChecker(currentVersion string, currentCommit string, cfg *config.Config, configDir string) {
  55. CurrentVersion = currentVersion
  56. if !cfg.CheckForUpdates {
  57. log.Warn("Update checking is disabled")
  58. return
  59. }
  60. payload := updateRequest{
  61. CurrentVersion: currentVersion,
  62. CurrentCommit: currentCommit,
  63. OS: installationinfo.Runtime.OS,
  64. Arch: installationinfo.Runtime.Arch,
  65. InstallationID: installationID(configDir + "/installation-id.txt"),
  66. InContainer: installationinfo.Runtime.InContainer,
  67. }
  68. s := cron.New(cron.WithSeconds())
  69. // Several values have been tried here.
  70. // 1st: Every 24h - very spammy.
  71. // 2nd: Every 7d - (168 hours - much more reasonable, but it checks in at the same time/day each week.
  72. // Current: Every 100h is not so spammy, and has the advantage that the checkin time "shifts" hours.
  73. s.AddFunc("@every 100h", func() {
  74. actualCheckForUpdate(payload)
  75. })
  76. go actualCheckForUpdate(payload) // On startup
  77. go s.Start()
  78. }
  79. func doRequest(jsonUpdateRequest []byte) string {
  80. req, err := http.NewRequest("POST", "http://update-check.olivetin.app", bytes.NewBuffer(jsonUpdateRequest))
  81. if err != nil {
  82. log.Errorf("Update check failed %v", err)
  83. return ""
  84. }
  85. req.Header.Set("Content-Type", "application/json")
  86. resp, err := http.DefaultClient.Do(req)
  87. if err != nil {
  88. log.Errorf("Update check failed %v", err)
  89. return ""
  90. }
  91. newVersion, _ := ioutil.ReadAll(resp.Body)
  92. defer resp.Body.Close()
  93. return string(newVersion)
  94. }
  95. func actualCheckForUpdate(payload updateRequest) {
  96. jsonUpdateRequest, err := json.Marshal(payload)
  97. log.Debugf("Update request payload: %+v", payload)
  98. if err != nil {
  99. log.Errorf("Update check failed %v", err)
  100. return
  101. }
  102. AvailableVersion = doRequest(jsonUpdateRequest)
  103. log.WithFields(log.Fields{
  104. "NewVersion": AvailableVersion,
  105. }).Infof("Update check complete")
  106. }