-
-
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
Open
6543
wants to merge
70
commits into
go-gitea:main
Choose a base branch
from
6543-forks:pull_review_fixfix-builder
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 7 commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
4568fce
add index to columns we use filter
6543 8f75edc
database done right!!!
6543 d54ec89
single source of truth for reviewType who affect reviews
6543 1c27639
rename func to be more apropriate
6543 d248a0a
use introduced GetReviewOption
6543 9d44369
CreateReview now make sure to clean up and not leafe reviews in stran…
6543 9f34f03
note todo
6543 189db73
Update models/issues/review.go
6543 70b1b6d
remove ReviewID on CommentTypeReviewRequest as its not important and …
6543 1ace570
wrap errors
6543 fd51505
finish
6543 4481841
not use anymore
6543 2bba3bb
RequestReview get deleted on review. So we dont have to try to load t…
6543 cf0f77d
Clean up old reviews on creating a new one
6543 3c21bd7
func caller use the created comment to retrieve created review too
6543 05db236
Merge branch 'main' into cleanup_old-reviews-on-review
6543 3667b97
Merge branch 'main' into no_error-when-notfound-is-expected
6543 9245e65
Merge branch 'main' into cleanup_old-reviews-on-review
6543 8e643a1
Merge branch 'main' into pull_review_fixfix-builder
6543 aa70e2e
fix conflict
6543 369bf6b
Merge branch 'main' into no_error-when-notfound-is-expected
6543 9a71752
Merge branch 'main' into cleanup_old-reviews-on-review
6543 a6adb7e
Merge branch 'main' into cleanup_old-reviews-on-review
6543 e08e306
else if
6543 4858468
Merge branch 'main' into no_error-when-notfound-is-expected
6543 5810f61
Merge branch 'main' into pull_review_fixfix-builder
6543 00abbf6
Merge branch 'main' into cleanup_old-reviews-on-review
6543 8a06ccb
handle ReviewTypePending
6543 91e3b66
Merge branch 'cleanup_old-reviews-on-review' into pull_review_fixfix-…
6543 92e237c
Merge branch 'main' into no_error-when-notfound-is-expected
6543 9fcea4c
Update models/issues/review.go
6543 3729221
add back
6543 e78ad74
Merge branch 'main' into no_error-when-notfound-is-expected
6543 dcad850
Merge branch 'main' into no_error-when-notfound-is-expected
6543 b03faf4
Merge branch 'main' into cleanup_old-reviews-on-review
6543 6406fd4
Merge branch 'main' into no_error-when-notfound-is-expected
6543 ec62290
add note why we do skip it
6543 bcdebcc
Merge branch 'no_error-when-notfound-is-expected' into pull_review_fi…
6543 726e7ba
Merge branch 'cleanup_old-reviews-on-review' into pull_review_fixfix-…
6543 b775268
Merge branch 'main' into pull_review_fixfix-builder
6543 4d4c6d7
fix merge conflict resolve
6543 0df942a
Merge branch 'main' into cleanup_old-reviews-on-review
6543 c2d62ae
Merge branch 'main' into no_error-when-notfound-is-expected
6543 84024c1
Merge branch 'main' into cleanup_old-reviews-on-review
6543 090dde4
Merge branch 'main' into no_error-when-notfound-is-expected
6543 34ea361
ignore error
6543 67208a1
Merge branch 'main' into no_error-when-notfound-is-expected
6543 7e26578
Merge branch 'main' into pull_review_fixfix-builder
6543 f1b38c0
Merge branch 'main' into cleanup_old-reviews-on-review
6543 ba24e26
ignore error msg
6543 2d0d3b4
Update models/issues/comment_list.go
6543 ee71a43
Merge branch 'no_error-when-notfound-is-expected' into pull_review_fi…
6543 1eb0a84
Merge branch 'cleanup_old-reviews-on-review' into pull_review_fixfix-…
6543 79e50b5
Merge branch 'main' into pull_review_fixfix-builder
6543 f4fbcf5
Merge branch 'main' into cleanup_old-reviews-on-review
6543 d4049d9
return result for unittest.AssertCount* helper func
6543 2db7e7c
Add TestAPIPullReviewStayDismissed test
6543 18dc9b3
Merge branch 'main' into cleanup_old-reviews-on-review
6543 8bc501b
Merge branch 'cleanup_old-reviews-on-review' into pull_review_fixfix-…
6543 758dd63
Merge branch 'main' into cleanup_old-reviews-on-review
6543 ab2ef38
Merge branch 'main' into cleanup_old-reviews-on-review
6543 01dafcc
Merge branch 'main' into cleanup_old-reviews-on-review
6543 36a2152
Merge branch 'main' into cleanup_old-reviews-on-review
6543 68c4de2
Merge branch 'main' into cleanup_old-reviews-on-review
6543 d23ace7
Merge branch 'main' into cleanup_old-reviews-on-review
lafriks b3d062d
test against rerequest and add some codecomments
6543 48fa3ad
Merge branch 'main' into cleanup_old-reviews-on-review
6543 4102b16
Merge branch 'main' into pull_review_fixfix-builder
6543 10a3727
Merge branch 'cleanup_old-reviews-on-review' into pull_review_fixfix-…
6543 89ba349
Merge branch 'main' into pull_review_fixfix-builder
6543 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -797,14 +797,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.DismissStaleApprovals { | ||
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 | ||
|
@@ -818,11 +820,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 | ||
|
@@ -837,10 +841,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 | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
@@ -138,6 +143,7 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) { | |
if r.CodeComments != nil { | ||
return err | ||
} | ||
|
||
6543 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err = r.loadIssue(ctx); err != nil { | ||
return err | ||
} | ||
|
@@ -284,8 +290,14 @@ func IsOfficialReviewerTeam(ctx context.Context, issue *Issue, team *organizatio | |
|
||
// CreateReview creates a new review based on opts | ||
func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error) { | ||
ctx, committer, err := db.TxContext(ctx) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer committer.Close() | ||
sess := db.GetEngine(ctx) | ||
|
||
review := &Review{ | ||
Type: opts.Type, | ||
Issue: opts.Issue, | ||
IssueID: opts.Issue.ID, | ||
Reviewer: opts.Reviewer, | ||
|
@@ -295,19 +307,42 @@ func CreateReview(ctx context.Context, opts CreateReviewOptions) (*Review, error | |
CommitID: opts.CommitID, | ||
Stale: opts.Stale, | ||
} | ||
if opts.Reviewer != nil { | ||
|
||
switch { | ||
case opts.Reviewer != nil: | ||
review.Type = opts.Type | ||
review.ReviewerID = opts.Reviewer.ID | ||
} else { | ||
if review.Type != ReviewTypeRequest { | ||
review.Type = ReviewTypeRequest | ||
|
||
opt := &GetReviewOption{ | ||
ReviewerID: opts.Reviewer.ID, | ||
IssueID: opts.Issue.ID, | ||
} | ||
// make sure user review requests are cleared | ||
sess.Where(opt.toCond().And(builder.Eq{"type": ReviewTypeRequest})).Delete(new(Review)) | ||
// make sure if the created review gets dismissed no old review surface | ||
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 | ||
} | ||
} | ||
|
||
case opts.ReviewerTeam != nil: | ||
review.Type = ReviewTypeRequest | ||
review.ReviewerTeamID = opts.ReviewerTeam.ID | ||
|
||
default: | ||
return nil, fmt.Errorf("provide either reviewer or reviewer team") | ||
} | ||
return review, db.Insert(ctx, review) | ||
|
||
if _, err := sess.Insert(review); err != nil { | ||
return nil, err | ||
} | ||
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 | ||
} | ||
|
@@ -356,7 +391,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 | ||
|
@@ -366,7 +401,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 | ||
|
@@ -396,7 +431,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 | ||
|
@@ -432,7 +467,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 | ||
|
@@ -456,13 +491,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).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_id = ? AND original_author_id = 0 AND type in (?, ?, ?))", | ||
issueID, userID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest). | ||
Get(review) | ||
opt := &GetReviewOption{ | ||
Types: []ReviewType{ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest}, | ||
IssueID: issueID, | ||
ReviewerID: userID, | ||
} | ||
has, err := db.GetEngine(ctx).Where(opt.toCond()).OrderBy("id").Desc().Get(review) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
@@ -475,13 +560,14 @@ 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 *Review, err error) { | ||
review = new(Review) | ||
|
||
var has bool | ||
if has, err = db.GetEngine(ctx).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = ?)", | ||
issueID, teamID). | ||
Get(review); err != nil { | ||
func GetTeamReviewerByIssueIDAndTeamID(ctx context.Context, issueID, teamID int64) (*Review, error) { | ||
review := new(Review) | ||
opt := &GetReviewOption{ | ||
IssueID: issueID, | ||
TeamID: teamID, | ||
} | ||
has, err := db.GetEngine(ctx).Where(opt.toCond()).OrderBy("id").Desc().Get(review) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
|
@@ -508,7 +594,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 | ||
} | ||
|
||
|
@@ -579,7 +665,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 | ||
} | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.