From 4e5083cd4d765a9f727f11c3968d032ca4846edf Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Thu, 4 Sep 2025 14:25:37 +0300 Subject: [PATCH] appview: knot upgrade banner Signed-off-by: Anirudh Oppiliappan --- appview/knots/knots.go | 33 ++++++++++++++++--- appview/pages/pages.go | 7 +++- .../{banner.html => bannerReadOnly.html} | 3 +- .../fragments/bannerRequiresUpgrade.html | 12 +++++++ .../pages/templates/repo/needsUpgrade.html | 24 ++++++++++++++ appview/repo/index.go | 9 +++++ 6 files changed, 80 insertions(+), 8 deletions(-) rename appview/pages/templates/knots/fragments/{banner.html => bannerReadOnly.html} (92%) create mode 100644 appview/pages/templates/knots/fragments/bannerRequiresUpgrade.html create mode 100644 appview/pages/templates/repo/needsUpgrade.html diff --git a/appview/knots/knots.go b/appview/knots/knots.go index 742fe2d3..9487a9f2 100644 --- a/appview/knots/knots.go +++ b/appview/knots/knots.go @@ -681,25 +681,48 @@ func (k *Knots) removeMember(w http.ResponseWriter, r *http.Request) { func (k *Knots) banner(w http.ResponseWriter, r *http.Request) { user := k.OAuth.GetUser(r) - l := k.Logger.With("handler", "removeMember") + l := k.Logger.With("handler", "banner") l = l.With("did", user.Did) l = l.With("handle", user.Handle) - registrations, err := db.GetRegistrations( + allRegistrations, err := db.GetRegistrations( k.Db, db.FilterEq("did", user.Did), - db.FilterEq("read_only", 1), ) if err != nil { l.Error("non-fatal: failed to get registrations") return } - if registrations == nil { + httpClient := &http.Client{Timeout: 5 * time.Second} + regs404 := []db.Registration{} + for _, reg := range allRegistrations { + healthURL := fmt.Sprintf("http://%s/xrpc/_health", reg.Domain) + + fmt.Println(healthURL) + + req, err := http.NewRequestWithContext(r.Context(), http.MethodGet, healthURL, nil) + if err != nil { + l.Error("failed to create health check request", "domain", reg.Domain, "err", err) + continue + } + + resp, err := httpClient.Do(req) + if err != nil { + l.Error("failed to make health check request", "domain", reg.Domain, "err", err) + continue + } + defer resp.Body.Close() + + if resp.StatusCode == http.StatusNotFound { + regs404 = append(regs404, reg) + } + } + if len(regs404) == 0 { return } k.Pages.KnotBanner(w, pages.KnotBannerParams{ - Registrations: registrations, + Registrations: regs404, }) } diff --git a/appview/pages/pages.go b/appview/pages/pages.go index ee62bd02..5340a86c 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -356,7 +356,7 @@ type KnotBannerParams struct { } func (p *Pages) KnotBanner(w io.Writer, params KnotBannerParams) error { - return p.executePlain("knots/fragments/banner", w, params) + return p.executePlain("knots/fragments/bannerRequiresUpgrade", w, params) } type KnotsParams struct { @@ -616,6 +616,7 @@ type RepoIndexParams struct { VerifiedCommits commitverify.VerifiedCommits Languages []types.RepoLanguageDetails Pipelines map[string]db.Pipeline + NeedsKnotUpgrade bool types.RepoIndexResponse } @@ -625,6 +626,10 @@ func (p *Pages) RepoIndexPage(w io.Writer, params RepoIndexParams) error { return p.executeRepo("repo/empty", w, params) } + if params.NeedsKnotUpgrade { + return p.executeRepo("repo/needsUpgrade", w, params) + } + p.rctx.RepoInfo = params.RepoInfo p.rctx.RepoInfo.Ref = params.Ref p.rctx.RendererType = markup.RendererTypeRepoMarkdown diff --git a/appview/pages/templates/knots/fragments/banner.html b/appview/pages/templates/knots/fragments/bannerReadOnly.html similarity index 92% rename from appview/pages/templates/knots/fragments/banner.html rename to appview/pages/templates/knots/fragments/bannerReadOnly.html index aa7c2f6c..1f200d79 100644 --- a/appview/pages/templates/knots/fragments/banner.html +++ b/appview/pages/templates/knots/fragments/bannerReadOnly.html @@ -1,4 +1,4 @@ -{{ define "knots/fragments/banner" }} +{{ define "knots/fragments/bannerReadOnly" }}
A knot ({{range $i, $r := .Registrations}}{{if ne $i 0}}, {{end}}{{ $r.Domain }}{{ end }}) that you administer is presently read-only. Consider upgrading this knot to @@ -6,4 +6,3 @@ Click to read the upgrade guide.
{{ end }} - diff --git a/appview/pages/templates/knots/fragments/bannerRequiresUpgrade.html b/appview/pages/templates/knots/fragments/bannerRequiresUpgrade.html new file mode 100644 index 00000000..5d389d10 --- /dev/null +++ b/appview/pages/templates/knots/fragments/bannerRequiresUpgrade.html @@ -0,0 +1,12 @@ +{{ define "knots/fragments/bannerRequiresUpgrade" }} +
+ The following knots that you administer require upgrade to be compatible with the latest version of Tangled: +
    + {{range $i, $r := .Registrations}} +
  • {{ $r.Domain }}
  • + {{ end }} +
+ Repositories hosted on these knots will not be accessible until upgraded. + Click to read the upgrade guide. +
+{{ end }} diff --git a/appview/pages/templates/repo/needsUpgrade.html b/appview/pages/templates/repo/needsUpgrade.html new file mode 100644 index 00000000..c84d9cab --- /dev/null +++ b/appview/pages/templates/repo/needsUpgrade.html @@ -0,0 +1,24 @@ +{{ define "title" }}{{ .RepoInfo.FullName }}{{ end }} + +{{ define "extrameta" }} + {{ template "repo/fragments/meta" . }} + {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo) }} +{{ end }} + +{{ define "repoContent" }} +
+
+
+ {{ if .LoggedInUser }} +

+ Your knot needs an upgrade. This repository is currently unavailable to users. +

+ {{ else }} +

+ The knot hosting this repository needs an upgrade. This repository is currently unavailable. +

+ {{ end }} +
+
+
+{{ end }} diff --git a/appview/repo/index.go b/appview/repo/index.go index 9a6f6045..bbc00113 100644 --- a/appview/repo/index.go +++ b/appview/repo/index.go @@ -1,6 +1,7 @@ package repo import ( + "errors" "fmt" "log" "net/http" @@ -46,9 +47,16 @@ func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { Host: host, } + var needsKnotUpgrade bool // Build index response from multiple XRPC calls result, err := rp.buildIndexResponse(r.Context(), xrpcc, f, ref) if err != nil { + if errors.Is(err, xrpcclient.ErrXrpcUnsupported) { + log.Println("failed to call XRPC repo.index", err) + needsKnotUpgrade = true + return + } + rp.pages.Error503(w) log.Println("failed to build index response", err) return @@ -133,6 +141,7 @@ func (rp *Repo) RepoIndex(w http.ResponseWriter, r *http.Request) { rp.pages.RepoIndexPage(w, pages.RepoIndexParams{ LoggedInUser: user, + NeedsKnotUpgrade: needsKnotUpgrade, RepoInfo: repoInfo, TagMap: tagMap, RepoIndexResponse: *result, -- 2.51.2