mirror of
https://github.com/lukaszraczylo/ghtracker.git
synced 2026-10-13 00:48:42 +00:00
fix(collector): link a failed repository to the configured host
When the first scan of a repository failed, the repository link pointed at github.com. It now follows github.api_url: Enterprise Server hosts drop the /api/v3 suffix and Enterprise Cloud hosts drop the api. prefix.
This commit is contained in:
@@ -54,6 +54,7 @@ type Collector struct {
|
|||||||
repos map[string]model.Repo
|
repos map[string]model.Repo
|
||||||
now func() time.Time
|
now func() time.Time
|
||||||
log *slog.Logger
|
log *slog.Logger
|
||||||
|
webBase string
|
||||||
kick chan struct{}
|
kick chan struct{}
|
||||||
names []string
|
names []string
|
||||||
th config.Thresholds
|
th config.Thresholds
|
||||||
@@ -78,6 +79,7 @@ func New(f Fetcher, cfg *config.Config, log *slog.Logger) *Collector {
|
|||||||
interval: cfg.RefreshInterval,
|
interval: cfg.RefreshInterval,
|
||||||
concurrency: cfg.Concurrency,
|
concurrency: cfg.Concurrency,
|
||||||
now: time.Now,
|
now: time.Now,
|
||||||
|
webBase: config.WebBase(cfg.GitHub.APIURL),
|
||||||
log: log,
|
log: log,
|
||||||
kick: make(chan struct{}, 1),
|
kick: make(chan struct{}, 1),
|
||||||
repos: make(map[string]model.Repo, len(cfg.Repos)),
|
repos: make(map[string]model.Repo, len(cfg.Repos)),
|
||||||
@@ -174,7 +176,7 @@ func (c *Collector) refreshOne(ctx context.Context, name string, at time.Time) m
|
|||||||
prev, ok := c.repos[name]
|
prev, ok := c.repos[name]
|
||||||
c.mu.RUnlock()
|
c.mu.RUnlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
prev = model.Repo{FullName: name, URL: "https://github.com/" + name}
|
prev = model.Repo{FullName: name, URL: c.webBase + "/" + name}
|
||||||
}
|
}
|
||||||
prev.Up, prev.Err = false, err.Error()
|
prev.Up, prev.Err = false, err.Error()
|
||||||
return prev
|
return prev
|
||||||
|
|||||||
@@ -337,3 +337,17 @@ func TestScanProgressAdvancesAsReposFinish(t *testing.T) {
|
|||||||
t.Fatalf("after scan: done=%d total=%d", v.ScanDone, v.ScanTotal)
|
t.Fatalf("after scan: done=%d total=%d", v.ScanDone, v.ScanTotal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFailedFirstScanLinksToTheConfiguredHost(t *testing.T) {
|
||||||
|
fail := &fakeFetcher{fn: func(string) (model.Repo, error) { return model.Repo{}, errors.New("nope") }}
|
||||||
|
cfg := &config.Config{
|
||||||
|
Repos: []string{"o/a"}, RefreshInterval: time.Hour, Concurrency: 1, Thresholds: th(),
|
||||||
|
GitHub: config.GitHub{APIURL: "https://ghe.example.com/api/v3"},
|
||||||
|
}
|
||||||
|
c := New(fail, cfg, slog.New(slog.NewTextHandler(io.Discard, nil)))
|
||||||
|
c.now = func() time.Time { return t0 }
|
||||||
|
c.Refresh(context.Background())
|
||||||
|
if got := c.View().Repos[0].URL; got != "https://ghe.example.com/o/a" {
|
||||||
|
t.Fatalf("repo link = %q", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -161,3 +162,24 @@ func normalizeRepos(in []string) ([]string, error) {
|
|||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultWebURL = "https://github.com"
|
||||||
|
apiV3Suffix = "/api/v3"
|
||||||
|
apiHostPrefix = "api."
|
||||||
|
)
|
||||||
|
|
||||||
|
// WebBase returns the address of the web interface that belongs to a GitHub API address:
|
||||||
|
// github.com for the public API, the host without /api/v3 for Enterprise Server, and the host
|
||||||
|
// without its "api." prefix for Enterprise Cloud with data residency.
|
||||||
|
func WebBase(apiURL string) string {
|
||||||
|
u, err := url.Parse(strings.TrimRight(apiURL, "/"))
|
||||||
|
if err != nil || u.Host == "" || strings.EqualFold(u.Host, "api.github.com") {
|
||||||
|
return defaultWebURL
|
||||||
|
}
|
||||||
|
u.Path = strings.TrimSuffix(u.Path, apiV3Suffix)
|
||||||
|
if u.Path == "" {
|
||||||
|
u.Host = strings.TrimPrefix(u.Host, apiHostPrefix)
|
||||||
|
}
|
||||||
|
return strings.TrimRight(u.String(), "/")
|
||||||
|
}
|
||||||
|
|||||||
@@ -126,3 +126,22 @@ func TestManualRefreshCanBeDisabled(t *testing.T) {
|
|||||||
t.Fatal("explicit false must stay off")
|
t.Fatal("explicit false must stay off")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebBase(t *testing.T) {
|
||||||
|
tests := map[string]string{
|
||||||
|
"": "https://github.com",
|
||||||
|
"https://api.github.com": "https://github.com",
|
||||||
|
"https://api.github.com/": "https://github.com",
|
||||||
|
"https://ghe.example.com/api/v3": "https://ghe.example.com",
|
||||||
|
"https://ghe.example.com/api/v3/": "https://ghe.example.com",
|
||||||
|
"http://ghe.internal:8080/api/v3": "http://ghe.internal:8080",
|
||||||
|
"https://api.acme.ghe.com": "https://acme.ghe.com",
|
||||||
|
"https://github.example.com/sub/api/v3": "https://github.example.com/sub",
|
||||||
|
"not a url": "https://github.com",
|
||||||
|
}
|
||||||
|
for in, want := range tests {
|
||||||
|
if got := WebBase(in); got != want {
|
||||||
|
t.Errorf("WebBase(%q) = %q, want %q", in, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user