diff --git a/appview/pages/pages.go b/appview/pages/pages.go index 9b436bef..debee4b9 100644 --- a/appview/pages/pages.go +++ b/appview/pages/pages.go @@ -1758,7 +1758,7 @@ type PipelineStatusesParams struct { } func (p *Pages) PipelineStatusesFragment(w io.Writer, params PipelineStatusesParams) error { - return p.executePlain("repo/fragments/commitPipelineStatuses", w, params) + return p.executePlain("repo/fragments/pipelineStatuses", w, params) } type WorkflowParams struct { diff --git a/appview/pages/templates/repo/fragments/commitPipelineStatuses.html b/appview/pages/templates/repo/fragments/commitPipelineStatuses.html deleted file mode 100644 index 2069278c..00000000 --- a/appview/pages/templates/repo/fragments/commitPipelineStatuses.html +++ /dev/null @@ -1,9 +0,0 @@ -{{ define "repo/fragments/commitPipelineStatuses" }} - {{ range $sha, $pipeline := .Pipelines }} - {{ if gt (len $pipeline.Statuses) 0 }} - - {{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $.RepoInfo "Pipeline" $pipeline) }} - - {{ end }} - {{ end }} -{{ end }} diff --git a/appview/pages/templates/repo/fragments/pipelineStatuses.html b/appview/pages/templates/repo/fragments/pipelineStatuses.html new file mode 100644 index 00000000..39e9a65d --- /dev/null +++ b/appview/pages/templates/repo/fragments/pipelineStatuses.html @@ -0,0 +1,9 @@ +{{ define "repo/fragments/pipelineStatuses" }} + {{ $root := . }} + {{ range $sha, $pipeline := .Pipelines }} + {{ if gt (len $pipeline.Statuses) 0 }} + {{ $id := printf "pipeline-status-%s" $sha }} + {{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $root.RepoInfo "Pipeline" $pipeline) }} + {{ end }} + {{ end }} +{{ end }} diff --git a/appview/pages/templates/repo/index.html b/appview/pages/templates/repo/index.html index 49b6fcd0..adcb7882 100644 --- a/appview/pages/templates/repo/index.html +++ b/appview/pages/templates/repo/index.html @@ -254,7 +254,7 @@ {{ end }} {{ end }} - + {{ end }} diff --git a/appview/pages/templates/repo/log.html b/appview/pages/templates/repo/log.html index 0fb28f36..4d1e2dbf 100644 --- a/appview/pages/templates/repo/log.html +++ b/appview/pages/templates/repo/log.html @@ -72,7 +72,7 @@ - + @@ -151,7 +151,7 @@ {{ template "repo/fragments/shortTime" $commit.Committer.When }} - + {{ end }} diff --git a/appview/pages/templates/repo/pulls/fragments/pullStack.html b/appview/pages/templates/repo/pulls/fragments/pullStack.html index 786d9947..f4280e6e 100644 --- a/appview/pages/templates/repo/pulls/fragments/pullStack.html +++ b/appview/pages/templates/repo/pulls/fragments/pullStack.html @@ -34,7 +34,7 @@ {{ end }}
- {{ template "repo/pulls/fragments/summarizedPullHeader" (list $pull $pipeline) }} + {{ template "repo/pulls/fragments/summarizedPullHeader" (list $pull $pipeline $root.RepoInfo) }}
diff --git a/appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html b/appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html index daf67219..7d457299 100644 --- a/appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html +++ b/appview/pages/templates/repo/pulls/fragments/summarizedPullHeader.html @@ -1,6 +1,7 @@ {{ define "repo/pulls/fragments/summarizedPullHeader" }} {{ $pull := index . 0 }} {{ $pipeline := index . 1 }} + {{ $repoInfo := index . 2 }} {{ with $pull }}
@@ -16,10 +17,7 @@
{{ $latestRound := .LastRoundNumber }} {{ $commentCount := .TotalComments }} - {{ if and $pipeline $pipeline.Id }} - {{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }} - - {{ end }} + {{ if and $pipeline $pipeline.Id }}{{ template "repo/pipelines/fragments/pipelineSymbolLong" (dict "RepoInfo" $repoInfo "Pipeline" $pipeline) }}{{ end }}
{{ i "message-square" "w-3 h-3 md:hidden" }} diff --git a/appview/pages/templates/repo/pulls/pulls.html b/appview/pages/templates/repo/pulls/pulls.html index 2f80ecc5..ef6d93fb 100644 --- a/appview/pages/templates/repo/pulls/pulls.html +++ b/appview/pages/templates/repo/pulls/pulls.html @@ -102,11 +102,7 @@ - {{ $pipeline := index $.Pipelines $topPR.LatestSha }} - {{ if and $pipeline $pipeline.Id }} - - {{ template "repo/pipelines/fragments/pipelineSymbol" (dict "Pipeline" $pipeline "ShortSummary" true) }} - {{ end }} + {{ $state := $topPR.Labels }} {{ range $k, $d := $.LabelDefs }} @@ -144,6 +140,14 @@ "QueryParams" (queryParams "q" .FilterQuery) ) }} {{ end }} + {{ if and .Stacks .RepoInfo.Spindle }} + + {{ end }} {{ end }} {{ define "stackedPullList" }} @@ -155,7 +159,7 @@
- {{ template "repo/pulls/fragments/summarizedPullHeader" (list $pull $pipeline) }} + {{ template "repo/pulls/fragments/summarizedPullHeader" (list $pull $pipeline $root.RepoInfo) }}
diff --git a/appview/pipelines/pipelines.go b/appview/pipelines/pipelines.go index add12d35..67c72c9a 100644 --- a/appview/pipelines/pipelines.go +++ b/appview/pipelines/pipelines.go @@ -14,6 +14,7 @@ import ( "tangled.org/core/appview/config" "tangled.org/core/appview/db" "tangled.org/core/appview/middleware" + "tangled.org/core/appview/models" "tangled.org/core/appview/oauth" "tangled.org/core/appview/pages" "tangled.org/core/appview/reporesolver" @@ -78,6 +79,69 @@ func New( } } +// FetchStatuses fetches pipelines from the repo's spindle, keyed by commit sha. +func FetchStatuses( + ctx context.Context, + repo *models.Repo, + shas []string, +) (map[string]types.Pipeline, error) { + m := make(map[string]types.Pipeline) + + if len(shas) == 0 || repo.Spindle == "" { + return m, nil + } + + spindleUrl, err := hostutil.EnsureHttpScheme(repo.Spindle) + if err != nil { + return m, nil + } + + xrpcc := &indigoxrpc.Client{Host: spindleUrl} + out, err := tangled.CiQueryPipelines(ctx, xrpcc, shas, "", nil, 0, repo.RepoDid) + if err != nil { + return nil, err + } + + return types.PipelinesByCommit(out.Pipelines), nil +} + +// StatusesHandler renders the pipeline-statuses fragment for a set of commit +// shas (given as repeated "sha" query params). It backs both the repo's +// commit-statuses endpoint and the pull request's pipeline-statuses endpoint. +func StatusesHandler( + oauth *oauth.OAuth, + repoResolver *reporesolver.RepoResolver, + pgs *pages.Pages, + logger *slog.Logger, +) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + l := logger.With("handler", "StatusesHandler") + + f, err := repoResolver.Resolve(r) + if err != nil { + l.Error("failed to resolve repo", "err", err) + return + } + + user := oauth.GetMultiAccountUser(r) + shas := r.URL.Query()["sha"] + + statuses, err := FetchStatuses(r.Context(), f, shas) + if err != nil { + l.Error("failed to fetch pipeline statuses", "err", err) + return + } + + err = pgs.PipelineStatusesFragment(w, pages.PipelineStatusesParams{ + RepoInfo: repoResolver.GetRepoInfo(r, user), + Pipelines: statuses, + }) + if err != nil { + l.Error("failed to render pipeline statuses", "err", err) + } + } +} + func (p *Pipelines) Index(w http.ResponseWriter, r *http.Request) { user := p.oauth.GetMultiAccountUser(r) l := p.logger.With("handler", "Index") diff --git a/appview/pulls/list.go b/appview/pulls/list.go index 2d9b883d..269e5aed 100644 --- a/appview/pulls/list.go +++ b/appview/pulls/list.go @@ -14,9 +14,6 @@ import ( "tangled.org/core/orm" "github.com/bluesky-social/indigo/atproto/syntax" - indigoxrpc "github.com/bluesky-social/indigo/xrpc" - "tangled.org/core/hostutil" - "tangled.org/core/types" ) func (s *Pulls) RepoPulls(w http.ResponseWriter, r *http.Request) { @@ -211,11 +208,9 @@ func (s *Pulls) RepoPulls(w http.ResponseWriter, r *http.Request) { } var stacks []models.Stack - var shas []string pullMap := make(map[string]*models.Pull) for _, p := range pulls { - shas = append(shas, p.LatestSha()) pullMap[p.AtUri().String()] = p } @@ -264,27 +259,6 @@ func (s *Pulls) RepoPulls(w http.ResponseWriter, r *http.Request) { stacks = append(stacks, stack) } - // commitId -> latest pipeline - pipelines := func(ctx context.Context, shas []string) map[string]types.Pipeline { - m := make(map[string]types.Pipeline) - if f.Spindle == "" { - return m - } - spindleUrl, err := hostutil.EnsureHttpScheme(f.Spindle) - if err != nil { - l.Error("invalid spindle host", "host", f.Spindle, "err", err) - return m - } - xrpcc := &indigoxrpc.Client{Host: spindleUrl} - out, err := tangled.CiQueryPipelines(ctx, xrpcc, shas, "", nil, 0, f.RepoDid) - if err != nil { - l.Error("failed to fetch pipelines", "err", err) - return m - } - - return types.PipelinesByCommit(out.Pipelines) - }(r.Context(), shas) - labelDefs, err := db.GetLabelDefinitions( s.db, orm.FilterIn("at_uri", f.Labels), @@ -326,7 +300,6 @@ func (s *Pulls) RepoPulls(w http.ResponseWriter, r *http.Request) { FilterState: filterState, FilterQuery: query.String(), Stacks: stacks, - Pipelines: pipelines, Page: page, PullCount: totalPulls, VouchRelationships: vouchRelationships, diff --git a/appview/pulls/router.go b/appview/pulls/router.go index b9f8e81b..4127db4c 100644 --- a/appview/pulls/router.go +++ b/appview/pulls/router.go @@ -5,11 +5,13 @@ import ( "github.com/go-chi/chi/v5" "tangled.org/core/appview/middleware" + "tangled.org/core/appview/pipelines" ) func (s *Pulls) Router(mw *middleware.Middleware) http.Handler { r := chi.NewRouter() r.With(middleware.Paginate).Get("/", s.RepoPulls) + r.Get("/pipeline-statuses", pipelines.StatusesHandler(s.oauth, s.repoResolver, s.pages, s.logger)) r.With(middleware.AuthMiddleware(s.oauth)).Route("/new", func(r chi.Router) { r.Get("/", s.NewPull) r.Get("/refresh", s.RefreshCompose) diff --git a/appview/repo/index.go b/appview/repo/index.go index 9aef7ce1..7aa03b29 100644 --- a/appview/repo/index.go +++ b/appview/repo/index.go @@ -23,6 +23,7 @@ import ( "tangled.org/core/appview/models" "tangled.org/core/appview/pages" "tangled.org/core/appview/pages/markup" + "tangled.org/core/appview/pipelines" "tangled.org/core/types" "github.com/go-chi/chi/v5" @@ -122,7 +123,7 @@ func (rp *Repo) Index(w http.ResponseWriter, r *http.Request) { } pipelineCh := make(chan pipelineResult, 1) go func() { - p, err := getPipelineStatuses(r.Context(), f, shas) + p, err := pipelines.FetchStatuses(r.Context(), f, shas) pipelineCh <- pipelineResult{p, err} }() @@ -201,30 +202,6 @@ func (rp *Repo) Index(w http.ResponseWriter, r *http.Request) { }) } -func (rp *Repo) PipelineStatuses(w http.ResponseWriter, r *http.Request) { - l := rp.logger.With("handler", "PipelineStatuses") - - f, err := rp.repoResolver.Resolve(r) - if err != nil { - l.Error("failed to resolve repo", "err", err) - return - } - - user := rp.oauth.GetMultiAccountUser(r) - shas := r.URL.Query()["sha"] - - pipelines, err := getPipelineStatuses(r.Context(), f, shas) - if err != nil { - l.Error("failed to fetch pipeline statuses", "err", err) - return - } - - rp.pages.PipelineStatusesFragment(w, pages.PipelineStatusesParams{ - RepoInfo: rp.repoResolver.GetRepoInfo(r, user), - Pipelines: pipelines, - }) -} - func (rp *Repo) getLanguageInfo( ctx context.Context, repoId syntax.DID, diff --git a/appview/repo/log.go b/appview/repo/log.go index cf7a8929..09f4d9fb 100644 --- a/appview/repo/log.go +++ b/appview/repo/log.go @@ -12,6 +12,7 @@ import ( "tangled.org/core/appview/commitverify" "tangled.org/core/appview/db" "tangled.org/core/appview/pages" + "tangled.org/core/appview/pipelines" "tangled.org/core/types" xrpcclient "tangled.org/core/xrpc/xrpcclient" @@ -238,13 +239,13 @@ func (rp *Repo) Commit(w http.ResponseWriter, r *http.Request) { } user := rp.oauth.GetMultiAccountUser(r) - pipelines, err := getPipelineStatuses(r.Context(), f, []string{result.Diff.Commit.This}) + statuses, err := pipelines.FetchStatuses(r.Context(), f, []string{result.Diff.Commit.This}) if err != nil { - l.Error("failed to getPipelineStatuses", "err", err) + l.Error("failed to FetchStatuses", "err", err) // non-fatal } var pipeline *types.Pipeline - if p, ok := pipelines[result.Diff.Commit.This]; ok { + if p, ok := statuses[result.Diff.Commit.This]; ok { pipeline = &p } diff --git a/appview/repo/repo_util.go b/appview/repo/repo_util.go index e33f4273..e9616475 100644 --- a/appview/repo/repo_util.go +++ b/appview/repo/repo_util.go @@ -1,16 +1,11 @@ package repo import ( - "context" "maps" "slices" "sort" "strings" - indigoxrpc "github.com/bluesky-social/indigo/xrpc" - "tangled.org/core/api/tangled" - "tangled.org/core/appview/models" - "tangled.org/core/hostutil" "tangled.org/core/types" ) @@ -87,33 +82,3 @@ func balanceIndexItems(commitCount, branchCount, tagCount, fileCount int) (commi return } - -// fetch pipelines from spindle and map by commit sha -func getPipelineStatuses( - ctx context.Context, - repo *models.Repo, - shas []string, -) (map[string]types.Pipeline, error) { - m := make(map[string]types.Pipeline) - - if len(shas) == 0 { - return m, nil - } - - if repo.Spindle == "" { - return m, nil - } - - spindleUrl, err := hostutil.EnsureHttpScheme(repo.Spindle) - if err != nil { - return m, nil - } - - xrpcc := &indigoxrpc.Client{Host: spindleUrl} - out, err := tangled.CiQueryPipelines(ctx, xrpcc, shas, "", nil, 0, repo.RepoDid) - if err != nil { - return nil, err - } - - return types.PipelinesByCommit(out.Pipelines), nil -} diff --git a/appview/repo/router.go b/appview/repo/router.go index 8fa49f7f..ea17ad28 100644 --- a/appview/repo/router.go +++ b/appview/repo/router.go @@ -5,12 +5,13 @@ import ( "github.com/go-chi/chi/v5" "tangled.org/core/appview/middleware" + "tangled.org/core/appview/pipelines" ) func (rp *Repo) Router(mw *middleware.Middleware) http.Handler { r := chi.NewRouter() r.Get("/", rp.Index) - r.Get("/commit-statuses", rp.PipelineStatuses) + r.Get("/commit-statuses", pipelines.StatusesHandler(rp.oauth, rp.repoResolver, rp.pages, rp.logger)) r.Get("/opengraph", rp.Opengraph) r.Get("/feed.atom", rp.AtomFeed) r.Get("/commits/{ref}", rp.Log)