summaryrefslogtreecommitdiffstats
path: root/cmd/notices.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/notices.go')
-rw-r--r--cmd/notices.go140
1 files changed, 140 insertions, 0 deletions
diff --git a/cmd/notices.go b/cmd/notices.go
new file mode 100644
index 0000000..a912bd9
--- /dev/null
+++ b/cmd/notices.go
@@ -0,0 +1,140 @@
+package cmd
+
+import (
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "net/url"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ log "github.com/sirupsen/logrus"
+)
+
+type Notice struct {
+ Level string `json:"level"`
+ Message string `json:"message"`
+}
+
+func displayNotices(input *Input) {
+ select {
+ case notices := <-noticesLoaded:
+ if len(notices) > 0 {
+ noticeLogger := log.New()
+ if input.jsonLogger {
+ noticeLogger.SetFormatter(&log.JSONFormatter{})
+ } else {
+ noticeLogger.SetFormatter(&log.TextFormatter{
+ DisableQuote: true,
+ DisableTimestamp: true,
+ PadLevelText: true,
+ })
+ }
+
+ fmt.Printf("\n")
+ for _, notice := range notices {
+ level, err := log.ParseLevel(notice.Level)
+ if err != nil {
+ level = log.InfoLevel
+ }
+ noticeLogger.Log(level, notice.Message)
+ }
+ }
+ case <-time.After(time.Second * 1):
+ log.Debugf("Timeout waiting for notices")
+ }
+}
+
+var noticesLoaded = make(chan []Notice)
+
+func loadVersionNotices(version string) {
+ go func() {
+ noticesLoaded <- getVersionNotices(version)
+ }()
+}
+
+const NoticeURL = "https://api.nektosact.com/notices"
+
+func getVersionNotices(version string) []Notice {
+ if os.Getenv("ACT_DISABLE_VERSION_CHECK") == "1" {
+ return nil
+ }
+
+ noticeURL, err := url.Parse(NoticeURL)
+ if err != nil {
+ log.Error(err)
+ return nil
+ }
+ query := noticeURL.Query()
+ query.Add("os", runtime.GOOS)
+ query.Add("arch", runtime.GOARCH)
+ query.Add("version", version)
+
+ noticeURL.RawQuery = query.Encode()
+
+ client := &http.Client{}
+ req, err := http.NewRequest("GET", noticeURL.String(), nil)
+ if err != nil {
+ log.Debug(err)
+ return nil
+ }
+
+ etag := loadNoticesEtag()
+ if etag != "" {
+ log.Debugf("Conditional GET for notices etag=%s", etag)
+ req.Header.Set("If-None-Match", etag)
+ }
+
+ resp, err := client.Do(req)
+ if err != nil {
+ log.Debug(err)
+ return nil
+ }
+
+ newEtag := resp.Header.Get("Etag")
+ if newEtag != "" {
+ log.Debugf("Saving notices etag=%s", newEtag)
+ saveNoticesEtag(newEtag)
+ }
+
+ defer resp.Body.Close()
+ notices := []Notice{}
+ if resp.StatusCode == 304 {
+ log.Debug("No new notices")
+ return nil
+ }
+ if err := json.NewDecoder(resp.Body).Decode(&notices); err != nil {
+ log.Debug(err)
+ return nil
+ }
+
+ return notices
+}
+
+func loadNoticesEtag() string {
+ p := etagPath()
+ content, err := os.ReadFile(p)
+ if err != nil {
+ log.Debugf("Unable to load etag from %s: %e", p, err)
+ }
+ return strings.TrimSuffix(string(content), "\n")
+}
+
+func saveNoticesEtag(etag string) {
+ p := etagPath()
+ err := os.WriteFile(p, []byte(strings.TrimSuffix(etag, "\n")), 0o600)
+ if err != nil {
+ log.Debugf("Unable to save etag to %s: %e", p, err)
+ }
+}
+
+func etagPath() string {
+ dir := filepath.Join(CacheHomeDir, "act")
+ if err := os.MkdirAll(dir, 0o777); err != nil {
+ log.Fatal(err)
+ }
+ return filepath.Join(dir, ".notices.etag")
+}