2
1
forked from adamm/autogits
Files
autogits/common/reviews.go

159 lines
3.2 KiB
Go

package common
import (
"regexp"
"slices"
"strings"
"src.opensuse.org/autogits/common/gitea-generated/models"
)
type PRReviews struct {
reviews []*models.PullReview
reviewers []string
comments []*models.TimelineComment
}
func FetchGiteaReviews(rf GiteaReviewTimelineFetcher, reviewers []string, org, repo string, no int64) (*PRReviews, error) {
timeline, err := rf.GetTimeline(org, repo, no)
if err != nil {
return nil, err
}
rawReviews, err := rf.GetPullRequestReviews(org, repo, no)
if err != nil {
return nil, err
}
reviews := make([]*models.PullReview, 0, 10)
var comments []*models.TimelineComment
for idx, item := range timeline {
if item.Type == TimelineCommentType_Review {
for _, r := range rawReviews {
if r.ID == item.ReviewID {
reviews = append(reviews, r)
break
}
}
} else if item.Type == TimelineCommentType_Comment {
comments = append(comments, item)
} else if item.Type == TimelineCommentType_PushPull {
timeline = timeline[0:idx]
break
} else {
LogDebug("Unhandled timeline type:", item.Type)
}
}
return &PRReviews{
reviews: reviews,
reviewers: reviewers,
comments: comments,
}, nil
}
const ManualMergeOK = "^merge\\s+ok(\\W|$)"
var merge_ok_regex *regexp.Regexp = regexp.MustCompile(ManualMergeOK)
func bodyCommandManualMergeOK(body string) bool {
lines := SplitLines(body)
for _, line := range lines {
if merge_ok_regex.MatchString(strings.ToLower(line)) {
return true
}
}
return false
}
func (r *PRReviews) IsManualMergeOK() bool {
for _, c := range r.comments {
if c.Updated != c.Created {
continue
}
if slices.Contains(r.reviewers, c.User.UserName) {
if bodyCommandManualMergeOK(c.Body) {
return true
}
}
}
for _, c := range r.reviews {
if c.Updated != c.Submitted {
continue
}
if slices.Contains(r.reviewers, c.User.UserName) {
if bodyCommandManualMergeOK(c.Body) {
return true
}
}
}
return false
}
func (r *PRReviews) IsApproved() bool {
goodReview := true
for _, reviewer := range r.reviewers {
goodReview = false
for _, review := range r.reviews {
if review.User.UserName == reviewer && review.State == ReviewStateApproved && !review.Stale && !review.Dismissed {
LogDebug(" -- found review: ", review.User.UserName)
goodReview = true
break
}
}
if !goodReview {
break
}
}
return goodReview
}
func (r *PRReviews) HasPendingReviewBy(reviewer string) bool {
if !slices.Contains(r.reviewers, reviewer) {
return false
}
isPending := false
for _, r := range r.reviews {
if r.User.UserName == reviewer && !r.Stale {
switch r.State {
case ReviewStateApproved:
fallthrough
case ReviewStateRequestChanges:
return false
case ReviewStateRequestReview:
fallthrough
case ReviewStatePending:
isPending = true
}
}
}
return isPending
}
func (r *PRReviews) IsReviewedBy(reviewer string) bool {
if !slices.Contains(r.reviewers, reviewer) {
return false
}
for _, r := range r.reviews {
if r.User.UserName == reviewer && !r.Stale {
switch r.State {
case ReviewStateApproved:
return true
case ReviewStateRequestChanges:
return true
}
}
}
return false
}