mirror of
https://github.com/glanceapp/glance.git
synced 2024-11-24 09:24:13 +01:00
Merge pull request #165 from Fumesover/release/v0.6.0
releases: Add support for gitlab
This commit is contained in:
commit
303438834b
@ -1105,11 +1105,13 @@ Example:
|
||||
|
||||
```yaml
|
||||
- type: releases
|
||||
show-source-icon: true
|
||||
repositories:
|
||||
- immich-app/immich
|
||||
- go-gitea/gitea
|
||||
- dani-garcia/vaultwarden
|
||||
- jellyfin/jellyfin
|
||||
- glanceapp/glance
|
||||
- gitlab:fdroid/fdroidclient
|
||||
- dockerhub:gotify/server
|
||||
```
|
||||
|
||||
Preview:
|
||||
@ -1121,12 +1123,23 @@ Preview:
|
||||
| Name | Type | Required | Default |
|
||||
| ---- | ---- | -------- | ------- |
|
||||
| repositories | array | yes | |
|
||||
| show-source-icon | boolean | no | false | |
|
||||
| token | string | no | |
|
||||
| gitlab-token | string | no | |
|
||||
| limit | integer | no | 10 |
|
||||
| collapse-after | integer | no | 5 |
|
||||
|
||||
##### `repositories`
|
||||
A list of repositores for which to fetch the latest release for. Only the name/repo is required, not the full URL.
|
||||
A list of repositores to fetch the latest release for. Only the name/repo is required, not the full URL. A prefix can be specified for repositories hosted elsewhere such as GitLab and Docker Hub. Example:
|
||||
|
||||
```yaml
|
||||
repositories:
|
||||
- gitlab:inkscape/inkscape
|
||||
- dockerhub:glanceapp/glance
|
||||
```
|
||||
|
||||
##### `show-source-icon`
|
||||
Shows an icon of the source (GitHub/GitLab/Docker Hub) next to the repository name when set to `true`.
|
||||
|
||||
##### `token`
|
||||
Without authentication Github allows for up to 60 requests per hour. You can easily exceed this limit and start seeing errors if you're tracking lots of repositories or your cache time is low. To circumvent this you can [create a read only token from your Github account](https://github.com/settings/personal-access-tokens/new) and provide it here.
|
||||
@ -1151,6 +1164,9 @@ and then use it in your `glance.yml` like this:
|
||||
|
||||
This way you can safely check your `glance.yml` in version control without exposing the token.
|
||||
|
||||
##### `gitlab-token`
|
||||
Same as the above but used when fetching GitLab releases.
|
||||
|
||||
##### `limit`
|
||||
The maximum number of releases to show.
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 19 KiB |
@ -543,8 +543,6 @@ kbd:active {
|
||||
@container widget (max-width: 750px) { .cards-grid { --cards-per-row: 3; } }
|
||||
@container widget (max-width: 650px) { .cards-grid { --cards-per-row: 2; } }
|
||||
|
||||
|
||||
|
||||
.widget-error-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -707,6 +705,12 @@ kbd:active {
|
||||
color: var(--color-text-highlight);
|
||||
}
|
||||
|
||||
.release-source-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.market-chart {
|
||||
margin-left: auto;
|
||||
width: 6.5rem;
|
||||
|
@ -2,14 +2,28 @@
|
||||
|
||||
{{ define "widget-content" }}
|
||||
<ul class="list list-gap-10 collapsible-container" data-collapse-after="{{ .CollapseAfter }}">
|
||||
{{ range $i, $release := .Releases }}
|
||||
{{ range .Releases }}
|
||||
<li>
|
||||
<a class="size-h4 block text-truncate color-primary-if-not-visited" href="{{ $release.NotesUrl }}" target="_blank" rel="noreferrer">{{ .Name }}</a>
|
||||
<div class="flex items-center gap-10">
|
||||
<a class="size-h4 block text-truncate color-primary-if-not-visited" href="{{ .NotesUrl }}" target="_blank" rel="noreferrer">{{ .Name }}</a>
|
||||
{{ if $.ShowSourceIcon }}
|
||||
{{/* TODO: add the icons as assets and link to them here instead of hardcoding */}}
|
||||
<svg class="release-source-icon" fill="var(--color-text-subdue)" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
{{ if eq .Source "github" }}
|
||||
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||||
{{ else if eq .Source "gitlab" }}
|
||||
<path d="m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z"/>
|
||||
{{ else if eq .Source "dockerhub" }}
|
||||
<path d="M13.983 11.078h2.119a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.119a.185.185 0 00-.185.185v1.888c0 .102.083.185.185.185m-2.954-5.43h2.118a.186.186 0 00.186-.186V3.574a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m0 2.716h2.118a.187.187 0 00.186-.186V6.29a.186.186 0 00-.186-.185h-2.118a.185.185 0 00-.185.185v1.887c0 .102.082.185.185.186m-2.93 0h2.12a.186.186 0 00.184-.186V6.29a.185.185 0 00-.185-.185H8.1a.185.185 0 00-.185.185v1.887c0 .102.083.185.185.186m-2.964 0h2.119a.186.186 0 00.185-.186V6.29a.185.185 0 00-.185-.185H5.136a.186.186 0 00-.186.185v1.887c0 .102.084.185.186.186m5.893 2.715h2.118a.186.186 0 00.186-.185V9.006a.186.186 0 00-.186-.186h-2.118a.185.185 0 00-.185.185v1.888c0 .102.082.185.185.185m-2.93 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.083.185.185.185m-2.964 0h2.119a.185.185 0 00.185-.185V9.006a.185.185 0 00-.184-.186h-2.12a.186.186 0 00-.186.186v1.887c0 .102.084.185.186.185m-2.92 0h2.12a.185.185 0 00.184-.185V9.006a.185.185 0 00-.184-.186h-2.12a.185.185 0 00-.184.185v1.888c0 .102.082.185.185.185M23.763 9.89c-.065-.051-.672-.51-1.954-.51-.338.001-.676.03-1.01.087-.248-1.7-1.653-2.53-1.716-2.566l-.344-.199-.226.327c-.284.438-.49.922-.612 1.43-.23.97-.09 1.882.403 2.661-.595.332-1.55.413-1.744.42H.751a.751.751 0 00-.75.748 11.376 11.376 0 00.692 4.062c.545 1.428 1.355 2.48 2.41 3.124 1.18.723 3.1 1.137 5.275 1.137.983.003 1.963-.086 2.93-.266a12.248 12.248 0 003.823-1.389c.98-.567 1.86-1.288 2.61-2.136 1.252-1.418 1.998-2.997 2.553-4.4h.221c1.372 0 2.215-.549 2.68-1.009.309-.293.55-.65.707-1.046l.098-.288Z"/>
|
||||
{{ end }}
|
||||
</svg>
|
||||
{{ end }}
|
||||
</div>
|
||||
<ul class="list-horizontal-text">
|
||||
<li {{ dynamicRelativeTimeAttrs $release.TimeReleased }}></li>
|
||||
<li>{{ $release.Version }}</li>
|
||||
{{ if gt $release.Downvotes 3 }}
|
||||
<li>{{ $release.Downvotes | formatNumber }} ⚠</li>
|
||||
<li {{ dynamicRelativeTimeAttrs .TimeReleased }}></li>
|
||||
<li>{{ .Version }}</li>
|
||||
{{ if gt .Downvotes 3 }}
|
||||
<li>{{ .Downvotes | formatNumber }} ⚠</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</li>
|
||||
|
58
internal/feed/dockerhub.go
Normal file
58
internal/feed/dockerhub.go
Normal file
@ -0,0 +1,58 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type dockerHubRepositoryTagsResponse struct {
|
||||
Results []struct {
|
||||
Name string `json:"name"`
|
||||
LastPushed string `json:"tag_last_pushed"`
|
||||
} `json:"results"`
|
||||
}
|
||||
|
||||
const dockerHubReleaseNotesURLFormat = "https://hub.docker.com/r/%s/tags?name=%s"
|
||||
|
||||
func fetchLatestDockerHubRelease(request *ReleaseRequest) (*AppRelease, error) {
|
||||
parts := strings.Split(request.Repository, "/")
|
||||
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid repository name: %s", request.Repository)
|
||||
}
|
||||
|
||||
httpRequest, err := http.NewRequest(
|
||||
"GET",
|
||||
fmt.Sprintf("https://hub.docker.com/v2/namespaces/%s/repositories/%s/tags", parts[0], parts[1]),
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.Token != nil {
|
||||
httpRequest.Header.Add("Authorization", "Bearer "+(*request.Token))
|
||||
}
|
||||
|
||||
response, err := decodeJsonFromRequest[dockerHubRepositoryTagsResponse](defaultClient, httpRequest)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(response.Results) == 0 {
|
||||
return nil, fmt.Errorf("no tags found for repository: %s", request.Repository)
|
||||
}
|
||||
|
||||
tag := response.Results[0]
|
||||
|
||||
return &AppRelease{
|
||||
Source: ReleaseSourceDockerHub,
|
||||
NotesUrl: fmt.Sprintf(dockerHubReleaseNotesURLFormat, request.Repository, tag.Name),
|
||||
Name: request.Repository,
|
||||
Version: tag.Name,
|
||||
TimeReleased: parseRFC3339Time(tag.LastPushed),
|
||||
}, nil
|
||||
}
|
@ -2,7 +2,6 @@ package feed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
@ -17,85 +16,41 @@ type githubReleaseLatestResponseJson struct {
|
||||
} `json:"reactions"`
|
||||
}
|
||||
|
||||
func parseGithubTime(t string) time.Time {
|
||||
parsedTime, err := time.Parse("2006-01-02T15:04:05Z", t)
|
||||
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
return parsedTime
|
||||
}
|
||||
|
||||
func FetchLatestReleasesFromGithub(repositories []string, token string) (AppReleases, error) {
|
||||
appReleases := make(AppReleases, 0, len(repositories))
|
||||
|
||||
if len(repositories) == 0 {
|
||||
return appReleases, nil
|
||||
}
|
||||
|
||||
requests := make([]*http.Request, len(repositories))
|
||||
|
||||
for i, repository := range repositories {
|
||||
request, _ := http.NewRequest("GET", fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", repository), nil)
|
||||
|
||||
if token != "" {
|
||||
request.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
|
||||
}
|
||||
|
||||
requests[i] = request
|
||||
}
|
||||
|
||||
task := decodeJsonFromRequestTask[githubReleaseLatestResponseJson](defaultClient)
|
||||
job := newJob(task, requests).withWorkers(15)
|
||||
responses, errs, err := workerPoolDo(job)
|
||||
func fetchLatestGithubRelease(request *ReleaseRequest) (*AppRelease, error) {
|
||||
httpRequest, err := http.NewRequest(
|
||||
"GET",
|
||||
fmt.Sprintf("https://api.github.com/repos/%s/releases/latest", request.Repository),
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var failed int
|
||||
|
||||
for i := range responses {
|
||||
if errs[i] != nil {
|
||||
failed++
|
||||
slog.Error("Failed to fetch or parse github release", "error", errs[i], "url", requests[i].URL)
|
||||
continue
|
||||
}
|
||||
|
||||
liveRelease := &responses[i]
|
||||
|
||||
if liveRelease == nil {
|
||||
slog.Error("No live release found", "repository", repositories[i], "url", requests[i].URL)
|
||||
continue
|
||||
}
|
||||
|
||||
version := liveRelease.TagName
|
||||
|
||||
if version[0] != 'v' {
|
||||
version = "v" + version
|
||||
}
|
||||
|
||||
appReleases = append(appReleases, AppRelease{
|
||||
Name: repositories[i],
|
||||
Version: version,
|
||||
NotesUrl: liveRelease.HtmlUrl,
|
||||
TimeReleased: parseGithubTime(liveRelease.PublishedAt),
|
||||
Downvotes: liveRelease.Reactions.Downvotes,
|
||||
})
|
||||
if request.Token != nil {
|
||||
httpRequest.Header.Add("Authorization", "Bearer "+(*request.Token))
|
||||
}
|
||||
|
||||
if len(appReleases) == 0 {
|
||||
return nil, ErrNoContent
|
||||
response, err := decodeJsonFromRequest[githubReleaseLatestResponseJson](defaultClient, httpRequest)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appReleases.SortByNewest()
|
||||
version := response.TagName
|
||||
|
||||
if failed > 0 {
|
||||
return appReleases, fmt.Errorf("%w: could not get %d releases", ErrPartialContent, failed)
|
||||
if len(version) > 0 && version[0] != 'v' {
|
||||
version = "v" + version
|
||||
}
|
||||
|
||||
return appReleases, nil
|
||||
return &AppRelease{
|
||||
Source: ReleaseSourceGithub,
|
||||
Name: request.Repository,
|
||||
Version: version,
|
||||
NotesUrl: response.HtmlUrl,
|
||||
TimeReleased: parseRFC3339Time(response.PublishedAt),
|
||||
Downvotes: response.Reactions.Downvotes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type GithubTicket struct {
|
||||
@ -201,7 +156,7 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in
|
||||
for i := range PRsResponse.Tickets {
|
||||
details.PullRequests = append(details.PullRequests, GithubTicket{
|
||||
Number: PRsResponse.Tickets[i].Number,
|
||||
CreatedAt: parseGithubTime(PRsResponse.Tickets[i].CreatedAt),
|
||||
CreatedAt: parseRFC3339Time(PRsResponse.Tickets[i].CreatedAt),
|
||||
Title: PRsResponse.Tickets[i].Title,
|
||||
})
|
||||
}
|
||||
@ -218,7 +173,7 @@ func FetchRepositoryDetailsFromGithub(repository string, token string, maxPRs in
|
||||
for i := range issuesResponse.Tickets {
|
||||
details.Issues = append(details.Issues, GithubTicket{
|
||||
Number: issuesResponse.Tickets[i].Number,
|
||||
CreatedAt: parseGithubTime(issuesResponse.Tickets[i].CreatedAt),
|
||||
CreatedAt: parseRFC3339Time(issuesResponse.Tickets[i].CreatedAt),
|
||||
Title: issuesResponse.Tickets[i].Title,
|
||||
})
|
||||
}
|
||||
|
54
internal/feed/gitlab.go
Normal file
54
internal/feed/gitlab.go
Normal file
@ -0,0 +1,54 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type gitlabReleaseResponseJson struct {
|
||||
TagName string `json:"tag_name"`
|
||||
ReleasedAt string `json:"released_at"`
|
||||
Links struct {
|
||||
Self string `json:"self"`
|
||||
} `json:"_links"`
|
||||
}
|
||||
|
||||
func fetchLatestGitLabRelease(request *ReleaseRequest) (*AppRelease, error) {
|
||||
httpRequest, err := http.NewRequest(
|
||||
"GET",
|
||||
fmt.Sprintf(
|
||||
"https://gitlab.com/api/v4/projects/%s/releases/permalink/latest",
|
||||
url.QueryEscape(request.Repository),
|
||||
),
|
||||
nil,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if request.Token != nil {
|
||||
httpRequest.Header.Add("PRIVATE-TOKEN", *request.Token)
|
||||
}
|
||||
|
||||
response, err := decodeJsonFromRequest[gitlabReleaseResponseJson](defaultClient, httpRequest)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
version := response.TagName
|
||||
|
||||
if len(version) > 0 && version[0] != 'v' {
|
||||
version = "v" + version
|
||||
}
|
||||
|
||||
return &AppRelease{
|
||||
Source: ReleaseSourceGitlab,
|
||||
Name: request.Repository,
|
||||
Version: version,
|
||||
NotesUrl: response.Links.Self,
|
||||
TimeReleased: parseRFC3339Time(response.ReleasedAt),
|
||||
}, nil
|
||||
}
|
@ -41,6 +41,7 @@ type Weather struct {
|
||||
}
|
||||
|
||||
type AppRelease struct {
|
||||
Source ReleaseSource
|
||||
Name string
|
||||
Version string
|
||||
NotesUrl string
|
||||
|
69
internal/feed/releases.go
Normal file
69
internal/feed/releases.go
Normal file
@ -0,0 +1,69 @@
|
||||
package feed
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type ReleaseSource string
|
||||
|
||||
const (
|
||||
ReleaseSourceGithub ReleaseSource = "github"
|
||||
ReleaseSourceGitlab ReleaseSource = "gitlab"
|
||||
ReleaseSourceDockerHub ReleaseSource = "dockerhub"
|
||||
)
|
||||
|
||||
type ReleaseRequest struct {
|
||||
Source ReleaseSource
|
||||
Repository string
|
||||
Token *string
|
||||
}
|
||||
|
||||
func FetchLatestReleases(requests []*ReleaseRequest) (AppReleases, error) {
|
||||
job := newJob(fetchLatestReleaseTask, requests).withWorkers(20)
|
||||
results, errs, err := workerPoolDo(job)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var failed int
|
||||
|
||||
releases := make(AppReleases, 0, len(requests))
|
||||
|
||||
for i := range results {
|
||||
if errs[i] != nil {
|
||||
failed++
|
||||
slog.Error("Failed to fetch release", "source", requests[i].Source, "repository", requests[i].Repository, "error", errs[i])
|
||||
continue
|
||||
}
|
||||
|
||||
releases = append(releases, *results[i])
|
||||
}
|
||||
|
||||
if failed == len(requests) {
|
||||
return nil, ErrNoContent
|
||||
}
|
||||
|
||||
releases.SortByNewest()
|
||||
|
||||
if failed > 0 {
|
||||
return releases, fmt.Errorf("%w: could not get %d releases", ErrPartialContent, failed)
|
||||
}
|
||||
|
||||
return releases, nil
|
||||
}
|
||||
|
||||
func fetchLatestReleaseTask(request *ReleaseRequest) (*AppRelease, error) {
|
||||
switch request.Source {
|
||||
case ReleaseSourceGithub:
|
||||
return fetchLatestGithubRelease(request)
|
||||
case ReleaseSourceGitlab:
|
||||
return fetchLatestGitLabRelease(request)
|
||||
case ReleaseSourceDockerHub:
|
||||
return fetchLatestDockerHubRelease(request)
|
||||
}
|
||||
|
||||
return nil, errors.New("unsupported source")
|
||||
}
|
@ -7,6 +7,7 @@ import (
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -79,7 +80,6 @@ func maybeCopySliceWithoutZeroValues[T int | float64](values []T) []T {
|
||||
return values
|
||||
}
|
||||
|
||||
|
||||
var urlSchemePattern = regexp.MustCompile(`^[a-z]+:\/\/`)
|
||||
|
||||
func stripURLScheme(url string) string {
|
||||
@ -95,3 +95,13 @@ func limitStringLength(s string, max int) (string, bool) {
|
||||
|
||||
return s, false
|
||||
}
|
||||
|
||||
func parseRFC3339Time(t string) time.Time {
|
||||
parsed, err := time.Parse(time.RFC3339, t)
|
||||
|
||||
if err != nil {
|
||||
return time.Now()
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
|
@ -152,6 +152,10 @@ func (f *OptionalEnvString) UnmarshalYAML(node *yaml.Node) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *OptionalEnvString) String() string {
|
||||
return string(*f)
|
||||
}
|
||||
|
||||
func toSimpleIconIfPrefixed(icon string) (string, bool) {
|
||||
if !strings.HasPrefix(icon, "si:") {
|
||||
return icon, false
|
||||
|
@ -2,7 +2,9 @@ package widget
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"html/template"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/glanceapp/glance/internal/assets"
|
||||
@ -10,12 +12,15 @@ import (
|
||||
)
|
||||
|
||||
type Releases struct {
|
||||
widgetBase `yaml:",inline"`
|
||||
Releases feed.AppReleases `yaml:"-"`
|
||||
Repositories []string `yaml:"repositories"`
|
||||
Token OptionalEnvString `yaml:"token"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
widgetBase `yaml:",inline"`
|
||||
Releases feed.AppReleases `yaml:"-"`
|
||||
releaseRequests []*feed.ReleaseRequest `yaml:"-"`
|
||||
Repositories []string `yaml:"repositories"`
|
||||
Token OptionalEnvString `yaml:"token"`
|
||||
GitLabToken OptionalEnvString `yaml:"gitlab-token"`
|
||||
Limit int `yaml:"limit"`
|
||||
CollapseAfter int `yaml:"collapse-after"`
|
||||
ShowSourceIcon bool `yaml:"show-source-icon"`
|
||||
}
|
||||
|
||||
func (widget *Releases) Initialize() error {
|
||||
@ -29,11 +34,50 @@ func (widget *Releases) Initialize() error {
|
||||
widget.CollapseAfter = 5
|
||||
}
|
||||
|
||||
var tokenAsString = widget.Token.String()
|
||||
var gitLabTokenAsString = widget.GitLabToken.String()
|
||||
|
||||
for _, repository := range widget.Repositories {
|
||||
parts := strings.Split(repository, ":")
|
||||
var request *feed.ReleaseRequest
|
||||
|
||||
if len(parts) == 1 {
|
||||
request = &feed.ReleaseRequest{
|
||||
Source: feed.ReleaseSourceGithub,
|
||||
Repository: repository,
|
||||
}
|
||||
|
||||
if widget.Token != "" {
|
||||
request.Token = &tokenAsString
|
||||
}
|
||||
} else if len(parts) == 2 {
|
||||
if parts[0] == string(feed.ReleaseSourceGitlab) {
|
||||
request = &feed.ReleaseRequest{
|
||||
Source: feed.ReleaseSourceGitlab,
|
||||
Repository: parts[1],
|
||||
}
|
||||
|
||||
if widget.GitLabToken != "" {
|
||||
request.Token = &gitLabTokenAsString
|
||||
}
|
||||
} else if parts[0] == string(feed.ReleaseSourceDockerHub) {
|
||||
request = &feed.ReleaseRequest{
|
||||
Source: feed.ReleaseSourceDockerHub,
|
||||
Repository: parts[1],
|
||||
}
|
||||
} else {
|
||||
return errors.New("invalid repository source " + parts[0])
|
||||
}
|
||||
}
|
||||
|
||||
widget.releaseRequests = append(widget.releaseRequests, request)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (widget *Releases) Update(ctx context.Context) {
|
||||
releases, err := feed.FetchLatestReleasesFromGithub(widget.Repositories, string(widget.Token))
|
||||
releases, err := feed.FetchLatestReleases(widget.releaseRequests)
|
||||
|
||||
if !widget.canContinueUpdateAfterHandlingErr(err) {
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user