feat: show new updates in dashboard (#690)

* feat: show new update banner

* feat(http): add request logger

* refactor: updates checker

* feat: make update check optional

* fix: empty releases

* add toggle switch for update checks

* feat: toggle updates check from settings

* feat: toggle updates check from settings

* feat: check on toggle enabled

---------

Co-authored-by: soup <soup@r4tio.dev>
This commit is contained in:
ze0s 2023-02-05 18:44:11 +01:00 committed by GitHub
parent 3fdd7cf5e4
commit 2917a7d42d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 687 additions and 121 deletions

View file

@ -5,6 +5,8 @@ import (
"encoding/json"
"fmt"
"net/http"
"runtime"
"time"
"github.com/autobrr/autobrr/pkg/errors"
@ -13,16 +15,50 @@ import (
// Release is a GitHub release
type Release struct {
TagName string `json:"tag_name,omitempty"`
TargetCommitish *string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Draft *bool `json:"draft,omitempty"`
Prerelease *bool `json:"prerelease,omitempty"`
ID int64 `json:"id,omitempty"`
NodeID string `json:"node_id,omitempty"`
URL string `json:"url,omitempty"`
HtmlURL string `json:"html_url,omitempty"`
TagName string `json:"tag_name,omitempty"`
TargetCommitish string `json:"target_commitish,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Draft bool `json:"draft,omitempty"`
Prerelease bool `json:"prerelease,omitempty"`
CreatedAt time.Time `json:"created_at"`
PublishedAt time.Time `json:"published_at"`
Author Author `json:"author"`
Assets []Asset `json:"assets"`
}
type Author struct {
Login string `json:"login"`
Id int64 `json:"id"`
NodeId string `json:"node_id"`
AvatarUrl string `json:"avatar_url"`
GravatarId string `json:"gravatar_id"`
Url string `json:"url"`
HtmlUrl string `json:"html_url"`
Type string `json:"type"`
}
type Asset struct {
Url string `json:"url"`
Id int64 `json:"id"`
NodeId string `json:"node_id"`
Name string `json:"name"`
Label string `json:"label"`
Uploader Author `json:"uploader"`
ContentType string `json:"content_type"`
State string `json:"state"`
Size int64 `json:"size"`
DownloadCount int64 `json:"download_count"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
BrowserDownloadUrl string `json:"browser_download_url"`
}
func (r *Release) IsPreOrDraft() bool {
if *r.Draft || *r.Prerelease {
if r.Draft || r.Prerelease {
return true
}
return false
@ -30,12 +66,21 @@ func (r *Release) IsPreOrDraft() bool {
type Checker struct {
// user/repo-name or org/repo-name
Owner string
Repo string
Owner string
Repo string
CurrentVersion string
}
func NewChecker(owner, repo, currentVersion string) *Checker {
return &Checker{
Owner: owner,
Repo: repo,
CurrentVersion: currentVersion,
}
}
func (c *Checker) get(ctx context.Context) (*Release, error) {
url := fmt.Sprintf("https://api.github.com/repos/%v/%v/releases/latest", c.Owner, c.Repo)
url := fmt.Sprintf("https://api.autobrr.com/repos/%s/%s/releases/latest", c.Owner, c.Repo)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
@ -43,6 +88,8 @@ func (c *Checker) get(ctx context.Context) (*Release, error) {
}
req.Header.Set("Accept", "application/vnd.github.v3+json")
req.Header.Set("User-Agent", c.buildUserAgent())
client := http.DefaultClient
resp, err := client.Do(req)
@ -64,17 +111,26 @@ func (c *Checker) get(ctx context.Context) (*Release, error) {
return &release, nil
}
func (c *Checker) CheckNewVersion(ctx context.Context, version string) (bool, string, error) {
func (c *Checker) CheckNewVersion(ctx context.Context, version string) (bool, *Release, error) {
if isDevelop(version) {
return false, "", nil
return false, nil, nil
}
release, err := c.get(ctx)
if err != nil {
return false, "", err
return false, nil, err
}
return c.checkNewVersion(version, release)
newAvailable, _, err := c.checkNewVersion(version, release)
if err != nil {
return false, nil, err
}
if !newAvailable {
return false, nil, nil
}
return true, release, nil
}
func (c *Checker) checkNewVersion(version string, release *Release) (bool, string, error) {
@ -100,8 +156,12 @@ func (c *Checker) checkNewVersion(version string, release *Release) (bool, strin
return false, "", nil
}
func (c *Checker) buildUserAgent() string {
return fmt.Sprintf("autobrr/%s (%s %s)", c.CurrentVersion, runtime.GOOS, runtime.GOARCH)
}
func isDevelop(version string) bool {
tags := []string{"dev", "develop", "master", "latest"}
tags := []string{"dev", "develop", "master", "latest", ""}
for _, tag := range tags {
if version == tag {

View file

@ -29,7 +29,7 @@ func TestGitHubReleaseChecker_checkNewVersion(t *testing.T) {
version: "v0.2.0",
release: &Release{
TagName: "v0.3.0",
TargetCommitish: nil,
TargetCommitish: "",
},
},
wantNew: true,
@ -43,7 +43,7 @@ func TestGitHubReleaseChecker_checkNewVersion(t *testing.T) {
version: "v0.2.0",
release: &Release{
TagName: "v0.2.0",
TargetCommitish: nil,
TargetCommitish: "",
},
},
wantNew: false,
@ -57,7 +57,7 @@ func TestGitHubReleaseChecker_checkNewVersion(t *testing.T) {
version: "v0.3.0",
release: &Release{
TagName: "v0.2.0",
TargetCommitish: nil,
TargetCommitish: "",
},
},
wantNew: false,
@ -71,7 +71,7 @@ func TestGitHubReleaseChecker_checkNewVersion(t *testing.T) {
version: "v0.3.0",
release: &Release{
TagName: "v0.3.0-rc1",
TargetCommitish: nil,
TargetCommitish: "",
},
},
wantNew: false,
@ -85,7 +85,7 @@ func TestGitHubReleaseChecker_checkNewVersion(t *testing.T) {
version: "v0.3.0-RC1",
release: &Release{
TagName: "v0.3.0-RC2",
TargetCommitish: nil,
TargetCommitish: "",
},
},
wantNew: true,