releases: Add support for gitlab

This commit is contained in:
Albin Parou
2024-07-03 08:17:51 +02:00
parent 39f40670d0
commit 7d1ede8c91
3 changed files with 127 additions and 3 deletions

View File

@@ -1,9 +1,11 @@
package feed
import (
"errors"
"fmt"
"log/slog"
"net/http"
"net/url"
"sync"
"time"
)
@@ -17,6 +19,19 @@ type githubReleaseLatestResponseJson struct {
} `json:"reactions"`
}
type gitlabReleaseResponseJson struct {
TagName string `json:"tag_name"`
PublishedAt string `json:"created_at"`
Links struct {
Self string `json:"self"`
} `json:"_links"`
Draft bool `json:"draft"`
PreRelease bool `json:"prerelease"`
Reactions struct {
Downvotes int `json:"-1"`
} `json:"reactions"`
}
func parseGithubTime(t string) time.Time {
parsedTime, err := time.Parse("2006-01-02T15:04:05Z", t)
@@ -27,7 +42,107 @@ func parseGithubTime(t string) time.Time {
return parsedTime
}
func FetchLatestReleasesFromGithub(repositories []string, token string) (AppReleases, error) {
func FetchLatestReleasesFromGitForge(repositories []string, token string, source string) (AppReleases, error) {
switch source {
case "github":
return fetchLatestReleasesFromGithub(repositories, token)
case "gitlab":
return fetchLatestReleasesFromGitlab(repositories, token)
default:
return nil, errors.New(fmt.Sprintf("Release source %s is invalid", source))
}
}
func fetchLatestReleasesFromGitlab(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://gitlab.com/api/v4/projects/%s/releases/", url.QueryEscape(repository)), nil)
if token != "" {
request.Header.Add("PRIVATE-TOKEN", token)
}
requests[i] = request
}
task := decodeJsonFromRequestTask[[]gitlabReleaseResponseJson](defaultClient)
job := newJob(task, requests).withWorkers(15)
responses, errs, err := workerPoolDo(job)
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 gitlab release", "error", errs[i], "url", requests[i].URL)
continue
}
releases := responses[i]
if len(releases) < 1 {
failed++
slog.Error("No releases found", "repository", repositories[i], "url", requests[i].URL)
continue
}
var liveRelease *gitlabReleaseResponseJson
for i := range releases {
release := &releases[i]
if !release.Draft && !release.PreRelease {
liveRelease = release
break
}
}
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.Links.Self,
TimeReleased: parseGithubTime(liveRelease.PublishedAt),
Downvotes: liveRelease.Reactions.Downvotes,
})
}
if len(appReleases) == 0 {
return nil, ErrNoContent
}
appReleases.SortByNewest()
if failed > 0 {
return appReleases, fmt.Errorf("%w: could not get %d releases", ErrPartialContent, failed)
}
return appReleases, nil
}
func fetchLatestReleasesFromGithub(repositories []string, token string) (AppReleases, error) {
appReleases := make(AppReleases, 0, len(repositories))
if len(repositories) == 0 {