appview: show CI status on log and commit pages #256

merged
opened by oppi.li targeting master from push-mwkwusmyymno
Changed files
+112 -68
appview
+3 -1
appview/pages/pages.go
···
EmailToDidOrHandle map[string]string
VerifiedCommits commitverify.VerifiedCommits
Languages *types.RepoLanguageResponse
-
Pipelines map[plumbing.Hash]db.Pipeline
types.RepoIndexResponse
}
···
Active string
EmailToDidOrHandle map[string]string
VerifiedCommits commitverify.VerifiedCommits
}
func (p *Pages) RepoLog(w io.Writer, params RepoLogParams) error {
···
RepoInfo repoinfo.RepoInfo
Active string
EmailToDidOrHandle map[string]string
// singular because it's always going to be just one
VerifiedCommit commitverify.VerifiedCommits
···
EmailToDidOrHandle map[string]string
VerifiedCommits commitverify.VerifiedCommits
Languages *types.RepoLanguageResponse
+
Pipelines map[string]db.Pipeline
types.RepoIndexResponse
}
···
Active string
EmailToDidOrHandle map[string]string
VerifiedCommits commitverify.VerifiedCommits
+
Pipelines map[string]db.Pipeline
}
func (p *Pages) RepoLog(w io.Writer, params RepoLogParams) error {
···
RepoInfo repoinfo.RepoInfo
Active string
EmailToDidOrHandle map[string]string
+
Pipeline *db.Pipeline
// singular because it's always going to be just one
VerifiedCommit commitverify.VerifiedCommits
+6
appview/pages/templates/repo/commit.html
···
</div>
</div>
{{ end }}
</div>
</section>
···
</div>
</div>
{{ end }}
+
+
<div class="text-sm">
+
{{ if $.Pipeline }}
+
{{ template "repo/fragments/pipelineStatusSymbol" $.Pipeline }}
+
{{ end }}
+
</div>
</div>
</section>
+2 -1
appview/pages/templates/repo/fragments/pipelineStatusSymbol.html
···
{{ if $allPass }}
<div class="flex gap-1 items-center">
-
{{ i "check" "size-4 text-green-600 dark:text-green-400 " }} {{ $total }}/{{ $total }}
</div>
{{ else }}
{{ $radius := f64 8 }}
···
{{ if $allPass }}
<div class="flex gap-1 items-center">
+
{{ i "check" "size-4 text-green-600 dark:text-green-400 " }}
+
<span>{{ $total }}/{{ $total }}</span>
</div>
{{ else }}
{{ $radius := f64 8 }}
+1 -1
appview/pages/templates/repo/index.html
···
{{ end }}
<!-- ci status -->
-
{{ $pipeline := index $.Pipelines .Hash }}
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
<div class="inline-block px-1 select-none after:content-['·']"></div>
{{ template "repo/fragments/pipelineStatusSymbol" $pipeline }}
···
{{ end }}
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
<div class="inline-block px-1 select-none after:content-['·']"></div>
{{ template "repo/fragments/pipelineStatusSymbol" $pipeline }}
+64 -51
appview/pages/templates/repo/log.html
···
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Author</th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Commit</th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Message</th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Date</th>
</tr>
</thead>
···
{{ i "folder-code" "w-4 h-4" }}
</a>
</div>
</td>
<td class=" py-3 align-top">
-
<div>
-
<div class="flex items-center justify-start">
-
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="dark:text-white no-underline hover:underline">{{ index $messageParts 0 }}</a>
-
{{ if gt (len $messageParts) 1 }}
-
<button class="ml-2 py-1/2 px-1 bg-gray-200 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 rounded" hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">{{ i "ellipsis" "w-3 h-3" }}</button>
-
{{ end }}
-
-
-
{{ if index $.TagMap $commit.Hash.String }}
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
-
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
-
{{ $tag }}
-
</span>
-
{{ end }}
-
{{ end }}
-
-
</div>
-
{{ if gt (len $messageParts) 1 }}
-
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">{{ nl2br (index $messageParts 1) }}</p>
{{ end }}
</td>
<td class=" py-3 align-top text-gray-500 dark:text-gray-400">{{ timeFmt $commit.Committer.When }}</td>
</tr>
···
<div id="commit-message">
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
<div class="text-base cursor-pointer">
-
<div>
-
<div class="flex items-center justify-between">
-
<div class="flex-1">
-
<div class="inline">
-
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
-
class="inline no-underline hover:underline dark:text-white">
-
{{ index $messageParts 0 }}
-
</a>
-
{{ if gt (len $messageParts) 1 }}
-
<button
-
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600 ml-2"
-
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
-
{{ i "ellipsis" "w-3 h-3" }}
-
</button>
-
{{ end }}
-
{{ if index $.TagMap $commit.Hash.String }}
-
{{ range $tag := index $.TagMap $commit.Hash.String }}
-
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
-
{{ $tag }}
-
</span>
-
{{ end }}
{{ end }}
-
</div>
-
-
{{ if gt (len $messageParts) 1 }}
-
<p class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
-
{{ nl2br (index $messageParts 1) }}
-
</p>
{{ end }}
</div>
-
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
-
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
-
title="Browse repository at this commit">
-
{{ i "folder-code" "w-4 h-4" }}
-
</a>
</div>
</div>
</div>
</div>
···
</span>
<div class="inline-block px-1 select-none after:content-['·']"></div>
<span>{{ shortTimeFmt $commit.Committer.When }}</span>
</div>
</div>
{{ end }}
···
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Author</th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Commit</th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Message</th>
+
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold"></th>
<th class="py-2 text-sm text-left text-gray-700 dark:text-gray-300 uppercase font-bold">Date</th>
</tr>
</thead>
···
{{ i "folder-code" "w-4 h-4" }}
</a>
</div>
+
</td>
<td class=" py-3 align-top">
+
<div class="flex items-center justify-start gap-2">
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}" class="dark:text-white no-underline hover:underline">{{ index $messageParts 0 }}</a>
{{ if gt (len $messageParts) 1 }}
+
<button class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 dark:bg-gray-700 dark:hover:bg-gray-600 rounded" hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">{{ i "ellipsis" "w-3 h-3" }}</button>
{{ end }}
+
+
{{ if index $.TagMap $commit.Hash.String }}
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
+
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
+
{{ $tag }}
+
</span>
+
{{ end }}
+
{{ end }}
+
</div>
+
+
{{ if gt (len $messageParts) 1 }}
+
<p class="hidden mt-1 text-sm text-gray-600 dark:text-gray-400">{{ nl2br (index $messageParts 1) }}</p>
+
{{ end }}
+
</td>
+
<td class="py-3 align-top">
+
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
+
{{ template "repo/fragments/pipelineStatusSymbol" $pipeline }}
+
{{ end }}
</td>
<td class=" py-3 align-top text-gray-500 dark:text-gray-400">{{ timeFmt $commit.Committer.When }}</td>
</tr>
···
<div id="commit-message">
{{ $messageParts := splitN $commit.Message "\n\n" 2 }}
<div class="text-base cursor-pointer">
+
<div class="flex items-center justify-between">
+
<div class="flex-1">
+
<div class="inline-flex items-end">
+
<a href="/{{ $.RepoInfo.FullName }}/commit/{{ $commit.Hash.String }}"
+
class="inline no-underline hover:underline dark:text-white">
+
{{ index $messageParts 0 }}
+
</a>
+
{{ if gt (len $messageParts) 1 }}
+
<button
+
class="py-1/2 px-1 bg-gray-200 hover:bg-gray-400 rounded dark:bg-gray-700 dark:hover:bg-gray-600 ml-2"
+
hx-on:click="this.parentElement.nextElementSibling.classList.toggle('hidden')">
+
{{ i "ellipsis" "w-3 h-3" }}
+
</button>
+
{{ end }}
+
{{ if index $.TagMap $commit.Hash.String }}
+
{{ range $tag := index $.TagMap $commit.Hash.String }}
+
<span class="ml-2 text-xs rounded bg-gray-100 dark:bg-gray-700 text-black dark:text-white font-mono px-2 inline-flex items-center">
+
{{ $tag }}
+
</span>
{{ end }}
{{ end }}
</div>
+
+
{{ if gt (len $messageParts) 1 }}
+
<p class="hidden mt-1 text-sm cursor-text pb-2 dark:text-gray-300">
+
{{ nl2br (index $messageParts 1) }}
+
</p>
+
{{ end }}
</div>
+
<a href="/{{ $.RepoInfo.FullName }}/tree/{{ $commit.Hash.String }}"
+
class="p-1 mr-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded"
+
title="Browse repository at this commit">
+
{{ i "folder-code" "w-4 h-4" }}
+
</a>
</div>
</div>
</div>
···
</span>
<div class="inline-block px-1 select-none after:content-['·']"></div>
<span>{{ shortTimeFmt $commit.Committer.When }}</span>
+
+
<!-- ci status -->
+
{{ $pipeline := index $.Pipelines .Hash.String }}
+
{{ if and $pipeline (gt (len $pipeline.Statuses) 0) }}
+
<div class="inline-block px-1 select-none after:content-['·']"></div>
+
<span class="text-sm">
+
{{ template "repo/fragments/pipelineStatusSymbol" $pipeline }}
+
</span>
+
{{ end }}
</div>
</div>
{{ end }}
+5 -1
appview/repo/index.go
···
// non-fatal
}
-
pipelines, err := rp.getPipelineStatuses(repoInfo, commitsTrunc)
if err != nil {
log.Printf("failed to fetch pipeline statuses: %s", err)
// non-fatal
···
// non-fatal
}
+
var shas []string
+
for _, c := range commitsTrunc {
+
shas = append(shas, c.Hash.String())
+
}
+
pipelines, err := rp.getPipelineStatuses(repoInfo, shas)
if err != nil {
log.Printf("failed to fetch pipeline statuses: %s", err)
// non-fatal
+26 -1
appview/repo/repo.go
···
log.Println(err)
}
rp.pages.RepoLog(w, pages.RepoLogParams{
LoggedInUser: user,
TagMap: tagMap,
-
RepoInfo: f.RepoInfo(user),
RepoLogResponse: *repolog,
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
VerifiedCommits: vc,
})
return
}
···
}
user := rp.oauth.GetUser(r)
rp.pages.RepoCommit(w, pages.RepoCommitParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(user),
RepoCommitResponse: result,
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
VerifiedCommit: vc,
})
return
}
···
log.Println(err)
}
+
repoInfo := f.RepoInfo(user)
+
+
var shas []string
+
for _, c := range repolog.Commits {
+
shas = append(shas, c.Hash.String())
+
}
+
pipelines, err := rp.getPipelineStatuses(repoInfo, shas)
+
if err != nil {
+
log.Println(err)
+
// non-fatal
+
}
+
rp.pages.RepoLog(w, pages.RepoLogParams{
LoggedInUser: user,
TagMap: tagMap,
+
RepoInfo: repoInfo,
RepoLogResponse: *repolog,
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
VerifiedCommits: vc,
+
Pipelines: pipelines,
})
return
}
···
}
user := rp.oauth.GetUser(r)
+
repoInfo := f.RepoInfo(user)
+
pipelines, err := rp.getPipelineStatuses(repoInfo, []string{result.Diff.Commit.This})
+
if err != nil {
+
log.Println(err)
+
// non-fatal
+
}
+
var pipeline *db.Pipeline
+
if p, ok := pipelines[result.Diff.Commit.This]; ok {
+
pipeline = &p
+
}
+
rp.pages.RepoCommit(w, pages.RepoCommitParams{
LoggedInUser: user,
RepoInfo: f.RepoInfo(user),
RepoCommitResponse: result,
EmailToDidOrHandle: emailToDidOrHandle(rp, emailToDidMap),
VerifiedCommit: vc,
+
Pipeline: pipeline,
})
return
}
+5 -12
appview/repo/repo_util.go
···
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
-
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
···
// golang is so blessed that it requires 35 lines of imperative code for this
func (rp *Repo) getPipelineStatuses(
repoInfo repoinfo.RepoInfo,
-
commits []*object.Commit,
-
) (map[plumbing.Hash]db.Pipeline, error) {
-
m := make(map[plumbing.Hash]db.Pipeline)
-
if len(commits) == 0 {
return m, nil
}
-
shas := make([]string, len(commits))
-
for _, c := range commits {
-
shas = append(shas, c.Hash.String())
-
}
-
ps, err := db.GetPipelineStatuses(
rp.db,
db.FilterEq("repo_owner", repoInfo.OwnerDid),
···
}
for _, p := range ps {
-
hash := plumbing.NewHash(p.Sha)
-
m[hash] = p
}
return m, nil
···
"tangled.sh/tangled.sh/core/appview/db"
"tangled.sh/tangled.sh/core/appview/pages/repoinfo"
"github.com/go-git/go-git/v5/plumbing/object"
)
···
// golang is so blessed that it requires 35 lines of imperative code for this
func (rp *Repo) getPipelineStatuses(
repoInfo repoinfo.RepoInfo,
+
shas []string,
+
) (map[string]db.Pipeline, error) {
+
m := make(map[string]db.Pipeline)
+
if len(shas) == 0 {
return m, nil
}
ps, err := db.GetPipelineStatuses(
rp.db,
db.FilterEq("repo_owner", repoInfo.OwnerDid),
···
}
for _, p := range ps {
+
m[p.Sha] = p
}
return m, nil