From 83b73ce78ea77e682bad30698dd4eacadf87d8c5 Mon Sep 17 00:00:00 2001 From: Norwin Date: Thu, 17 Dec 2020 01:16:50 +0800 Subject: [PATCH] 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 Reviewed-on: https://gitea.com/gitea/tea/pulls/306 Reviewed-by: Lunny Xiao Reviewed-by: 6543 <6543@obermui.de> Co-Authored-By: Norwin Co-Committed-By: Norwin --- cmd/pulls.go | 7 ++- modules/print/pull.go | 87 ++++++++++++++++++++++++++++++------- modules/task/pull_create.go | 2 +- 3 files changed, 78 insertions(+), 18 deletions(-) diff --git a/cmd/pulls.go b/cmd/pulls.go index 05633e0..515b8c7 100644 --- a/cmd/pulls.go +++ b/cmd/pulls.go @@ -60,6 +60,11 @@ func runPullDetail(cmd *cli.Context, index string) error { fmt.Printf("error while loading reviews: %v\n", err) } - print.PullDetails(pr, reviews) + ci, _, err := client.GetCombinedStatus(ctx.Owner, ctx.Repo, pr.Head.Sha) + if err != nil { + fmt.Printf("error while loading CI: %v\n", err) + } + + print.PullDetails(pr, reviews, ci) return nil } diff --git a/modules/print/pull.go b/modules/print/pull.go index d072aa0..436d0ca 100644 --- a/modules/print/pull.go +++ b/modules/print/pull.go @@ -7,12 +7,21 @@ 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) { +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 { @@ -23,11 +32,16 @@ func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview) { } } + 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", + "# #%d %s (%s)\n@%s created %s\t**%s** <- **%s**\n\n%s\n\n", pr.Index, pr.Title, - pr.State, + state, pr.Poster.UserName, FormatTime(*pr.Created), base, @@ -35,29 +49,70 @@ func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview) { pr.Body, ) - if len(reviews) != 0 { - out += "\n" - revMap := make(map[string]gitea.ReviewStateType) - for _, review := range reviews { - switch review.State { - case gitea.ReviewStateApproved, - gitea.ReviewStateRequestChanges, - gitea.ReviewStateRequestReview: - revMap[review.Reviewer.UserName] = review.State + 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) } } - for k, v := range revMap { - out += fmt.Sprintf("\n @%s: %s", k, v) + if len(ciStatus.Statuses) != 0 { + out += fmt.Sprintf("- CI: %s\n%s", summary, errors) } } - if pr.State == gitea.StateOpen && pr.Mergeable { - out += "\nNo Conflicts" + 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( diff --git a/modules/task/pull_create.go b/modules/task/pull_create.go index b1f2e7a..a8e0f1a 100644 --- a/modules/task/pull_create.go +++ b/modules/task/pull_create.go @@ -76,7 +76,7 @@ func CreatePull(login *config.Login, repoOwner, repoName, base, head, title, des return fmt.Errorf("Could not create PR from %s to %s:%s: %s", head, repoOwner, base, err) } - print.PullDetails(pr, nil) + print.PullDetails(pr, nil, nil) fmt.Println(pr.HTMLURL)