1
0
mirror of https://gitea.com/gitea/tea.git synced 2024-11-03 04:27:21 -05:00
tea/modules/print/pull.go
Norwin 83b73ce78e Show PR CI status (#306)
fix layout of pr reviews

show PR CI status

put conflict info in status list

remove line

show merged state

deduplicate reviews by user

Co-authored-by: Norwin Roosen <git@nroo.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/306
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: 6543 <6543@obermui.de>
Co-Authored-By: Norwin <noerw@noreply.gitea.io>
Co-Committed-By: Norwin <noerw@noreply.gitea.io>
2020-12-17 01:16:50 +08:00

151 lines
3.2 KiB
Go

// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package print
import (
"fmt"
"strconv"
"strings"
"code.gitea.io/sdk/gitea"
)
var ciStatusSymbols = map[gitea.StatusState]string{
gitea.StatusSuccess: "✓ ",
gitea.StatusPending: "⭮ ",
gitea.StatusWarning: "⚠ ",
gitea.StatusError: "✘ ",
gitea.StatusFailure: "❌ ",
}
// PullDetails print an pull rendered to stdout
func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *gitea.CombinedStatus) {
base := pr.Base.Name
head := pr.Head.Name
if pr.Head.RepoID != pr.Base.RepoID {
if pr.Head.Repository != nil {
head = pr.Head.Repository.Owner.UserName + ":" + head
} else {
head = "delete:" + head
}
}
state := pr.State
if pr.Merged != nil {
state = "merged"
}
out := fmt.Sprintf(
"# #%d %s (%s)\n@%s created %s\t**%s** <- **%s**\n\n%s\n\n",
pr.Index,
pr.Title,
state,
pr.Poster.UserName,
FormatTime(*pr.Created),
base,
head,
pr.Body,
)
if ciStatus != nil || len(reviews) != 0 || pr.State == gitea.StateOpen {
out += "---\n"
}
out += formatReviews(reviews)
if ciStatus != nil {
var summary, errors string
for _, s := range ciStatus.Statuses {
summary += ciStatusSymbols[s.State]
if s.State != gitea.StatusSuccess {
errors += fmt.Sprintf(" - [**%s**:\t%s](%s)\n", s.Context, s.Description, s.TargetURL)
}
}
if len(ciStatus.Statuses) != 0 {
out += fmt.Sprintf("- CI: %s\n%s", summary, errors)
}
}
if pr.State == gitea.StateOpen {
if pr.Mergeable {
out += "- No Conflicts\n"
} else {
out += "- **Conflicting files**\n"
}
}
outputMarkdown(out)
}
func formatReviews(reviews []*gitea.PullReview) string {
result := ""
if len(reviews) == 0 {
return result
}
// deduplicate reviews by user (via review time & userID),
reviewByUser := make(map[int64]*gitea.PullReview)
for _, review := range reviews {
switch review.State {
case gitea.ReviewStateApproved,
gitea.ReviewStateRequestChanges,
gitea.ReviewStateRequestReview:
if r, ok := reviewByUser[review.Reviewer.ID]; !ok || review.Submitted.After(r.Submitted) {
reviewByUser[review.Reviewer.ID] = review
}
}
}
// group reviews by type
usersByState := make(map[gitea.ReviewStateType][]string)
for _, r := range reviewByUser {
u := r.Reviewer.UserName
users := usersByState[r.State]
usersByState[r.State] = append(users, u)
}
// stringify
for state, user := range usersByState {
result += fmt.Sprintf("- %s by @%s\n", state, strings.Join(user, ", @"))
}
return result
}
// PullsList prints a listing of pulls
func PullsList(prs []*gitea.PullRequest, output string) {
t := tableWithHeader(
"Index",
"Title",
"State",
"Author",
"Milestone",
"Updated",
)
for _, pr := range prs {
if pr == nil {
continue
}
author := pr.Poster.FullName
if len(author) == 0 {
author = pr.Poster.UserName
}
mile := ""
if pr.Milestone != nil {
mile = pr.Milestone.Title
}
t.addRow(
strconv.FormatInt(pr.Index, 10),
pr.Title,
string(pr.State),
author,
mile,
FormatTime(*pr.Updated),
)
}
t.print(output)
}