fix(updater): 官方仓库 404 不再提示私有仓库
This commit is contained in:
3 files changed
+27
-8
No files matched your search
@@ -45,7 +45,8 @@ type github struct {
|
|||||||
// from a private fork, where its absence does not look like an auth failure:
|
// from a private fork, where its absence does not look like an auth failure:
|
||||||
// GitHub answers 404 — not 401 or 403 — for a private repo the caller cannot see, so
|
// GitHub answers 404 — not 401 or 403 — for a private repo the caller cannot see, so
|
||||||
// "no token" is indistinguishable from "no release published yet" by status alone.
|
// "no token" is indistinguishable from "no release published yet" by status alone.
|
||||||
// latestStable says both in the error rather than making an operator guess.
|
// latestStable says both in the error rather than making an operator guess, for any
|
||||||
|
// repository other than the official one, which is public.
|
||||||
//
|
//
|
||||||
// It is read from the environment and never compiled in. A constant would be
|
// It is read from the environment and never compiled in. A constant would be
|
||||||
// committed to the very repository it protects, ship inside every felis binary where
|
// committed to the very repository it protects, ship inside every felis binary where
|
||||||
@@ -56,7 +57,7 @@ type github struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tokenEnv names the environment variable holding the GitHub credential. deploy/bootstrap.sh
|
// tokenEnv names the environment variable holding the GitHub credential. deploy/bootstrap.sh
|
||||||
// reads the same variable to clone a private repo, so an operator sets one value once.
|
// reads the same variable to clone a private fork, so an operator sets one value once.
|
||||||
const tokenEnv = "FELIS_GITHUB_TOKEN"
|
const tokenEnv = "FELIS_GITHUB_TOKEN"
|
||||||
|
|
||||||
// newGitHub builds a source pointed at the live GitHub REST API with sane defaults.
|
// newGitHub builds a source pointed at the live GitHub REST API with sane defaults.
|
||||||
@@ -148,7 +149,10 @@ func (g github) latestTag(ctx context.Context, repo string) (string, error) {
|
|||||||
// 404 is the ambiguous one: GitHub hides a private repo behind it rather than
|
// 404 is the ambiguous one: GitHub hides a private repo behind it rather than
|
||||||
// answering 401/403, so an unauthenticated miss and a repo with no stable release
|
// answering 401/403, so an unauthenticated miss and a repo with no stable release
|
||||||
// are the same status. Name both causes, and name the fix for the one an operator
|
// are the same status. Name both causes, and name the fix for the one an operator
|
||||||
// can act on.
|
// can act on. The official repository is public, so there only the first applies.
|
||||||
|
if resp.StatusCode == http.StatusNotFound && strings.EqualFold(repo, officialRepo) {
|
||||||
|
return "", fmt.Errorf("github: %s releases/latest returned HTTP 404 — it has no published stable release", repo)
|
||||||
|
}
|
||||||
if resp.StatusCode == http.StatusNotFound && g.token == "" {
|
if resp.StatusCode == http.StatusNotFound && g.token == "" {
|
||||||
return "", fmt.Errorf(
|
return "", fmt.Errorf(
|
||||||
"github: %s releases/latest returned HTTP 404 — either it has no published stable release, or it is private and %s is unset",
|
"github: %s releases/latest returned HTTP 404 — either it has no published stable release, or it is private and %s is unset",
|
||||||
|
|||||||
@@ -223,4 +223,18 @@ func TestGitHubNamesTheTokenOnAnUnauthenticated404(t *testing.T) {
|
|||||||
if strings.Contains(err.Error(), tokenEnv) {
|
if strings.Contains(err.Error(), tokenEnv) {
|
||||||
t.Errorf("a 404 WITH a token set must not blame the missing token; got: %v", err)
|
t.Errorf("a 404 WITH a token set must not blame the missing token; got: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The official repository is public: a 404 there means no stable release, whatever
|
||||||
|
// the token.
|
||||||
|
g.token = ""
|
||||||
|
_, err = g.latestStable(context.Background(), "felismc/felis")
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("want an error on 404")
|
||||||
|
}
|
||||||
|
if strings.Contains(err.Error(), tokenEnv) || strings.Contains(err.Error(), "private") {
|
||||||
|
t.Errorf("a 404 from the public official repository must not suggest it is private; got: %v", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(err.Error(), "no published stable release") {
|
||||||
|
t.Errorf("a 404 from the official repository must say it has no stable release; got: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,9 @@ const (
|
|||||||
sourcePostgres // postgresql.org/versions.json, within Current's major
|
sourcePostgres // postgresql.org/versions.json, within Current's major
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// officialRepo is Felis's own GitHub repository, which is public.
|
||||||
|
const officialRepo = "FelisMC/Felis"
|
||||||
|
|
||||||
// Spec is one platform component's static update policy plus how to find its latest
|
// Spec is one platform component's static update policy plus how to find its latest
|
||||||
// upstream version. Current is deliberately NOT here — it is gathered at runtime
|
// upstream version. Current is deliberately NOT here — it is gathered at runtime
|
||||||
// (integration: an image tag, `k3s --version`, a jar manifest) and combined with the
|
// (integration: an image tag, `k3s --version`, a jar manifest) and combined with the
|
||||||
@@ -56,11 +59,9 @@ type Spec struct {
|
|||||||
func Topology() []Spec {
|
func Topology() []Spec {
|
||||||
return []Spec{
|
return []Spec{
|
||||||
// Felis's own release repo, and the same slug deploy/bootstrap.sh clones from
|
// Felis's own release repo, and the same slug deploy/bootstrap.sh clones from
|
||||||
// (FELIS_REPO_URL). It is PRIVATE today, which is why the github source carries an
|
// (FELIS_REPO_URL). It is public, like k3s and cloudflared; the github source's
|
||||||
// optional token: unauthenticated, this coord answers 404 — the status GitHub uses
|
// optional token is for a build whose coord names a private fork.
|
||||||
// to hide a repo's existence — and felis-api is the one tracked component where
|
{Name: "felis-api", Policy: updates.PolicyScheduled, Manageable: true, Source: sourceGitHub, Coord: officialRepo},
|
||||||
// that happens. k3s and cloudflared are public and need no credential.
|
|
||||||
{Name: "felis-api", Policy: updates.PolicyScheduled, Manageable: true, Source: sourceGitHub, Coord: "FelisMC/Felis"},
|
|
||||||
{Name: "k3s", Policy: updates.PolicyNotify, Manageable: false, Source: sourceGitHub, Coord: "k3s-io/k3s"},
|
{Name: "k3s", Policy: updates.PolicyNotify, Manageable: false, Source: sourceGitHub, Coord: "k3s-io/k3s"},
|
||||||
{Name: "cloudflared", Policy: updates.PolicyScheduled, Manageable: true, Source: sourceGitHub, Coord: "cloudflare/cloudflared"},
|
{Name: "cloudflared", Policy: updates.PolicyScheduled, Manageable: true, Source: sourceGitHub, Coord: "cloudflare/cloudflared"},
|
||||||
{Name: "velocity", Policy: updates.PolicyNotify, Manageable: false, Source: sourcePaperMC, Coord: "velocity"},
|
{Name: "velocity", Policy: updates.PolicyNotify, Manageable: false, Source: sourcePaperMC, Coord: "velocity"},
|
||||||
|
|||||||
Reference in new issue
Block a user