-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
[WIP] Refactor review related code #28544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4568fce
8f75edc
d54ec89
1c27639
d248a0a
9d44369
9f34f03
189db73
70b1b6d
1ace570
fd51505
4481841
2bba3bb
cf0f77d
3c21bd7
05db236
3667b97
9245e65
8e643a1
aa70e2e
369bf6b
9a71752
a6adb7e
e08e306
4858468
5810f61
00abbf6
8a06ccb
91e3b66
92e237c
9fcea4c
3729221
e78ad74
dcad850
b03faf4
6406fd4
ec62290
bcdebcc
726e7ba
b775268
4d4c6d7
0df942a
c2d62ae
84024c1
090dde4
34ea361
67208a1
7e26578
f1b38c0
ba24e26
2d0d3b4
ee71a43
1eb0a84
79e50b5
f4fbcf5
d4049d9
2db7e7c
18dc9b3
8bc501b
758dd63
ab2ef38
01dafcc
36a2152
68c4de2
d23ace7
b3d062d
48fa3ad
4102b16
10a3727
89ba349
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -798,14 +798,16 @@ func HasEnoughApprovals(ctx context.Context, protectBranch *git_model.ProtectedB | |
|
||
// GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist. | ||
func GetGrantedApprovalsCount(ctx context.Context, protectBranch *git_model.ProtectedBranch, pr *PullRequest) int64 { | ||
sess := db.GetEngine(ctx).Where("issue_id = ?", pr.IssueID). | ||
And("type = ?", ReviewTypeApprove). | ||
And("official = ?", true). | ||
And("dismissed = ?", false) | ||
opt := &GetReviewOption{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lunny suggest: How about reuse db.Find here? |
||
Dismissed: util.OptionalBoolFalse, | ||
Official: util.OptionalBoolTrue, | ||
Types: []ReviewType{ReviewTypeApprove}, | ||
IssueID: pr.IssueID, | ||
} | ||
if protectBranch.IgnoreStaleApprovals { | ||
sess = sess.And("stale = ?", false) | ||
opt.Stale = util.OptionalBoolFalse | ||
} | ||
approvals, err := sess.Count(new(Review)) | ||
approvals, err := db.GetEngine(ctx).Where(opt.toCond()).Count(new(Review)) | ||
if err != nil { | ||
log.Error("GetGrantedApprovalsCount: %v", err) | ||
return 0 | ||
|
@@ -819,11 +821,13 @@ func MergeBlockedByRejectedReview(ctx context.Context, protectBranch *git_model. | |
if !protectBranch.BlockOnRejectedReviews { | ||
return false | ||
} | ||
rejectExist, err := db.GetEngine(ctx).Where("issue_id = ?", pr.IssueID). | ||
And("type = ?", ReviewTypeReject). | ||
And("official = ?", true). | ||
And("dismissed = ?", false). | ||
Exist(new(Review)) | ||
opt := &GetReviewOption{ | ||
Dismissed: util.OptionalBoolFalse, | ||
Official: util.OptionalBoolTrue, | ||
Types: []ReviewType{ReviewTypeReject}, | ||
IssueID: pr.IssueID, | ||
} | ||
rejectExist, err := db.GetEngine(ctx).Where(opt.toCond()).Exist(new(Review)) | ||
if err != nil { | ||
log.Error("MergeBlockedByRejectedReview: %v", err) | ||
return true | ||
|
@@ -838,10 +842,12 @@ func MergeBlockedByOfficialReviewRequests(ctx context.Context, protectBranch *gi | |
if !protectBranch.BlockOnOfficialReviewRequests { | ||
return false | ||
} | ||
has, err := db.GetEngine(ctx).Where("issue_id = ?", pr.IssueID). | ||
And("type = ?", ReviewTypeRequest). | ||
And("official = ?", true). | ||
Exist(new(Review)) | ||
opt := &GetReviewOption{ | ||
Official: util.OptionalBoolTrue, | ||
Types: []ReviewType{ReviewTypeRequest}, | ||
IssueID: pr.IssueID, | ||
} | ||
has, err := db.GetEngine(ctx).Where(opt.toCond()).Exist(new(Review)) | ||
if err != nil { | ||
log.Error("MergeBlockedByOfficialReviewRequests: %v", err) | ||
return true | ||
|
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -85,6 +85,11 @@ const ( | |||
ReviewTypeRequest | ||||
) | ||||
|
||||
// AffectReview indicate if this review type alter a pull state | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. write about branch protection |
||||
func (rt ReviewType) AffectReview() bool { | ||||
return rt == ReviewTypeApprove || rt == ReviewTypeReject | ||||
} | ||||
|
||||
// Icon returns the corresponding icon for the review type | ||||
func (rt ReviewType) Icon() string { | ||||
switch rt { | ||||
|
@@ -103,11 +108,11 @@ func (rt ReviewType) Icon() string { | |||
|
||||
// Review represents collection of code comments giving feedback for a PR | ||||
type Review struct { | ||||
ID int64 `xorm:"pk autoincr"` | ||||
Type ReviewType | ||||
ID int64 `xorm:"pk autoincr"` | ||||
Type ReviewType `xorm:"index"` | ||||
Reviewer *user_model.User `xorm:"-"` | ||||
ReviewerID int64 `xorm:"index"` | ||||
ReviewerTeamID int64 `xorm:"NOT NULL DEFAULT 0"` | ||||
ReviewerTeamID int64 `xorm:"index NOT NULL DEFAULT 0"` | ||||
ReviewerTeam *organization.Team `xorm:"-"` | ||||
OriginalAuthor string | ||||
OriginalAuthorID int64 | ||||
|
@@ -314,17 +319,20 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error | |||
review.Type = opts.Type | ||||
review.ReviewerID = opts.Reviewer.ID | ||||
|
||||
reviewCond := builder.Eq{"reviewer_id": opts.Reviewer.ID, "issue_id": opts.Issue.ID} | ||||
opt := &GetReviewOption{ | ||||
ReviewerID: opts.Reviewer.ID, | ||||
IssueID: opts.Issue.ID, | ||||
} | ||||
// make sure user review requests are cleared | ||||
if opts.Type != ReviewTypePending { | ||||
if _, err := sess.Where(reviewCond.And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)); err != nil { | ||||
if _, err := sess.Where(opt.toCond().And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)); err != nil { | ||||
return nil, err | ||||
} | ||||
} | ||||
// make sure if the created review gets dismissed no old review surface | ||||
// other types can be ignored, as they don't affect branch protection | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
with the new helper it should be self explaining cc @wxiaoguang ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PS: this code might be deleted later on anyway if i'm done refactoring |
||||
if opts.Type == ReviewTypeApprove || opts.Type == ReviewTypeReject { | ||||
if _, err := sess.Where(reviewCond.And(builder.In("type", ReviewTypeApprove, ReviewTypeReject))). | ||||
if opts.Type.AffectReview() { | ||||
if _, err := sess.Where(opt.toCond().And(builder.In("type", ReviewTypeApprove, ReviewTypeReject))). | ||||
Cols("dismissed").Update(&Review{Dismissed: true}); err != nil { | ||||
return nil, err | ||||
} | ||||
|
@@ -344,8 +352,8 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error | |||
return review, committer.Commit() | ||||
} | ||||
|
||||
// GetCurrentReview returns the current pending review of reviewer for given issue | ||||
func GetCurrentReview(ctx context.Context, reviewer *user_model.User, issue *Issue) (*Review, error) { | ||||
// GetCurrentPendingReview returns the current pending review of reviewer for given issue | ||||
func GetCurrentPendingReview(ctx context.Context, reviewer *user_model.User, issue *Issue) (*Review, error) { | ||||
if reviewer == nil { | ||||
return nil, nil | ||||
} | ||||
|
@@ -394,7 +402,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, revi | |||
|
||||
official := false | ||||
|
||||
review, err := GetCurrentReview(ctx, doer, issue) | ||||
review, err := GetCurrentPendingReview(ctx, doer, issue) | ||||
if err != nil { | ||||
if !IsErrReviewNotExist(err) { | ||||
return nil, nil, err | ||||
|
@@ -404,7 +412,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, revi | |||
return nil, nil, ContentEmptyErr{} | ||||
} | ||||
|
||||
if reviewType == ReviewTypeApprove || reviewType == ReviewTypeReject { | ||||
if reviewType.AffectReview() { | ||||
// Only reviewers latest review of type approve and reject shall count as "official", so existing reviews needs to be cleared | ||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_id=?", false, issue.ID, doer.ID); err != nil { | ||||
return nil, nil, err | ||||
|
@@ -434,7 +442,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, revi | |||
return nil, nil, ContentEmptyErr{} | ||||
} | ||||
|
||||
if reviewType == ReviewTypeApprove || reviewType == ReviewTypeReject { | ||||
if reviewType.AffectReview() { | ||||
// Only reviewers latest review of type approve and reject shall count as "official", so existing reviews needs to be cleared | ||||
if _, err := db.Exec(ctx, "UPDATE `review` SET official=? WHERE issue_id=? AND reviewer_id=?", false, issue.ID, doer.ID); err != nil { | ||||
return nil, nil, err | ||||
|
@@ -470,7 +478,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, revi | |||
} | ||||
|
||||
// try to remove team review request if need | ||||
if issue.Repo.Owner.IsOrganization() && (reviewType == ReviewTypeApprove || reviewType == ReviewTypeReject) { | ||||
if issue.Repo.Owner.IsOrganization() && reviewType.AffectReview() { | ||||
teamReviewRequests := make([]*Review, 0, 10) | ||||
if err := sess.SQL("SELECT * FROM review WHERE issue_id = ? AND reviewer_team_id > 0 AND type = ?", issue.ID, ReviewTypeRequest).Find(&teamReviewRequests); err != nil { | ||||
return nil, nil, err | ||||
|
@@ -494,15 +502,63 @@ func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, revi | |||
return review, comm, committer.Commit() | ||||
} | ||||
|
||||
type GetReviewOption struct { | ||||
Dismissed util.OptionalBool | ||||
Official util.OptionalBool | ||||
Stale util.OptionalBool | ||||
Types []ReviewType | ||||
IssueID int64 | ||||
ReviewerID int64 | ||||
TeamID int64 | ||||
} | ||||
|
||||
func (o *GetReviewOption) toCond() builder.Cond { | ||||
cond := builder.And(builder.Eq{"review.issue_id": o.IssueID}) | ||||
|
||||
if !o.Dismissed.IsNone() { | ||||
cond = cond.And(builder.Eq{"review.dismissed": o.Dismissed.IsTrue()}) | ||||
} | ||||
if !o.Official.IsNone() { | ||||
cond = cond.And(builder.Eq{"review.official": o.Official.IsTrue()}) | ||||
} | ||||
if !o.Stale.IsNone() { | ||||
cond = cond.And(builder.Eq{"review.stale": o.Stale.IsTrue()}) | ||||
} | ||||
if len(o.Types) != 0 { | ||||
cond = cond.And(builder.In("review.type", o.Types)) | ||||
} | ||||
if o.ReviewerID > 0 { | ||||
cond = cond.And(builder.Eq{"review.reviewer_id": o.ReviewerID, "original_author_id": 0}) | ||||
} | ||||
if o.TeamID > 0 { | ||||
cond = cond.And(builder.Eq{"review.reviewer_team_id": o.TeamID}) | ||||
} | ||||
|
||||
return cond | ||||
} | ||||
|
||||
// GetReviewByOption get the latest review for a pull request filtered by given option | ||||
func GetReviewByOption(ctx context.Context, opt *GetReviewOption) (*Review, error) { | ||||
review := new(Review) | ||||
has, err := db.GetEngine(ctx).Where(opt.toCond()).OrderBy("id").Desc().Get(review) | ||||
if err != nil { | ||||
return nil, err | ||||
} | ||||
if !has { | ||||
return nil, ErrReviewNotExist{} | ||||
} | ||||
return review, nil | ||||
} | ||||
|
||||
// GetReviewByIssueIDAndUserID get the latest review of reviewer for a pull request | ||||
func GetReviewByIssueIDAndUserID(ctx context.Context, issueID, userID int64) (*Review, error) { | ||||
review := new(Review) | ||||
|
||||
has, err := db.GetEngine(ctx).Where( | ||||
builder.In("type", ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). | ||||
And(builder.Eq{"issue_id": issueID, "reviewer_id": userID, "original_author_id": 0})). | ||||
Desc("id"). | ||||
Get(review) | ||||
opt := &GetReviewOption{ | ||||
Types: []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest}, | ||||
IssueID: issueID, | ||||
ReviewerID: userID, | ||||
} | ||||
has, err := db.GetEngine(ctx).Where(opt.toCond()).Desc("review.id").Get(review) | ||||
if err != nil { | ||||
return nil, err | ||||
} | ||||
|
@@ -517,10 +573,11 @@ func GetReviewByIssueIDAndUserID(ctx context.Context, issueID, userID int64) (*R | |||
// GetTeamReviewerByIssueIDAndTeamID get the latest review request of reviewer team for a pull request | ||||
func GetTeamReviewerByIssueIDAndTeamID(ctx context.Context, issueID, teamID int64) (*Review, error) { | ||||
review := new(Review) | ||||
|
||||
has, err := db.GetEngine(ctx).Where(builder.Eq{"issue_id": issueID, "reviewer_team_id": teamID}). | ||||
Desc("id"). | ||||
Get(review) | ||||
opt := &GetReviewOption{ | ||||
IssueID: issueID, | ||||
TeamID: teamID, | ||||
} | ||||
has, err := db.GetEngine(ctx).Where(opt.toCond()).Desc("review.id").Get(review) | ||||
if err != nil { | ||||
return nil, err | ||||
} | ||||
|
@@ -548,7 +605,7 @@ func MarkReviewsAsNotStale(ctx context.Context, issueID int64, commitID string) | |||
|
||||
// DismissReview change the dismiss status of a review | ||||
func DismissReview(ctx context.Context, review *Review, isDismiss bool) (err error) { | ||||
if review.Dismissed == isDismiss || (review.Type != ReviewTypeApprove && review.Type != ReviewTypeReject) { | ||||
if review.Dismissed == isDismiss || !review.Type.AffectReview() { | ||||
return nil | ||||
} | ||||
|
||||
|
@@ -619,7 +676,7 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo | |||
return nil, err | ||||
} | ||||
|
||||
// skip it when reviewer hase been request to review | ||||
// skip it when reviewer has been request to review | ||||
if review != nil && review.Type == ReviewTypeRequest { | ||||
return nil, nil | ||||
} | ||||
|
@@ -635,7 +692,7 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo | |||
} | ||||
} | ||||
|
||||
review, err = CreateReview(ctx, CreateReviewOptions{ | ||||
_, err = CreateReview(ctx, CreateReviewOptions{ | ||||
Type: ReviewTypeRequest, | ||||
Issue: issue, | ||||
Reviewer: reviewer, | ||||
|
@@ -653,7 +710,6 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo | |||
Issue: issue, | ||||
RemovedAssignee: false, // Use RemovedAssignee as !isRequest | ||||
AssigneeID: reviewer.ID, // Use AssigneeID as reviewer ID | ||||
ReviewID: review.ID, | ||||
}) | ||||
if err != nil { | ||||
return nil, err | ||||
|
Uh oh!
There was an error while loading. Please reload this page.