Skip to content
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

Add reviewers selection to new pull request fixes #26289 #32403

Merged
merged 30 commits into from
Nov 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d37f246
Add reviewers selection to new pull request form
splitt3r Aug 19, 2023
5929b87
Add translatanle clear reviewers label
splitt3r Aug 19, 2023
452828a
Add missing continue statement
splitt3r Aug 19, 2023
906514e
Check pr creator permissions
splitt3r Sep 1, 2023
45b8a96
Remove unintended change
splitt3r Sep 1, 2023
3e0dcea
Check if Pull + run linter
splitt3r Sep 9, 2023
978c465
Fix invisible class name
sebastian-sauer Oct 20, 2023
c92202e
Add request review to API
sebastian-sauer Oct 20, 2023
df3f363
Fix call to locale in tmpl
sebastian-sauer Nov 15, 2023
e4858b2
Improve markup
sebastian-sauer Nov 15, 2023
f604ab1
Fix teamreviewer ids
sebastian-sauer Nov 15, 2023
60d9d96
update template to merge main
CalK16 Oct 31, 2024
f7c0ea4
move logics to proper file
CalK16 Nov 2, 2024
c34dd4a
postpone the review request notification
CalK16 Nov 2, 2024
f7f0b7a
Merge branch 'main' into main
CalK16 Nov 2, 2024
0304324
fix linting issues
CalK16 Nov 2, 2024
800232b
more updates on templates
CalK16 Nov 3, 2024
d8d66b5
simplify a condition statement
CalK16 Nov 3, 2024
25ebf69
fix an internal error
CalK16 Nov 3, 2024
418a13c
Merge branch 'main' into CalK16-pr-reviewer
wxiaoguang Nov 3, 2024
941f7fd
fix conflicts
wxiaoguang Nov 3, 2024
a2a06f1
Merge branch 'main' into CalK16-pr-reviewer
wxiaoguang Nov 8, 2024
8de6e40
make code easier to maintain
wxiaoguang Nov 8, 2024
6fb9583
fix duplicate code
wxiaoguang Nov 8, 2024
e4e2de3
refactor reviewer list
wxiaoguang Nov 8, 2024
637e4fb
fix lint
wxiaoguang Nov 8, 2024
4c9169a
Merge branch 'main' into CalK16-pr-reviewer
wxiaoguang Nov 8, 2024
9ccb69c
fix lint
wxiaoguang Nov 8, 2024
1759ea4
fine tune
wxiaoguang Nov 8, 2024
be102f5
fine tune and add comments
wxiaoguang Nov 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion modules/structs/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ type CreatePullRequestOption struct {
Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"`
// swagger:strfmt date-time
Deadline *time.Time `json:"due_date"`
Deadline *time.Time `json:"due_date"`
Reviewers []string `json:"reviewers"`
TeamReviewers []string `json:"team_reviewers"`
}

// EditPullRequestOption options when modify pull request
Expand Down
2 changes: 1 addition & 1 deletion options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ issues.new.closed_milestone = Closed Milestones
issues.new.assignees = Assignees
issues.new.clear_assignees = Clear assignees
issues.new.no_assignees = No Assignees
issues.new.no_reviewers = No reviewers
issues.new.no_reviewers = No Reviewers
issues.new.blocked_user = Cannot create issue because you are blocked by the repository owner.
issues.edit.already_changed = Unable to save changes to the issue. It appears the content has already been changed by another user. Please refresh the page and try editing again to avoid overwriting their changes
issues.edit.blocked_user = Cannot edit content because you are blocked by the poster or repository owner.
Expand Down
14 changes: 13 additions & 1 deletion routers/api/v1/repo/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,7 +554,19 @@ func CreatePullRequest(ctx *context.APIContext) {
}
}

if err := pull_service.NewPullRequest(ctx, repo, prIssue, labelIDs, []string{}, pr, assigneeIDs); err != nil {
prOpts := &pull_service.NewPullRequestOptions{
Repo: repo,
Issue: prIssue,
LabelIDs: labelIDs,
PullRequest: pr,
AssigneeIDs: assigneeIDs,
}
prOpts.Reviewers, prOpts.TeamReviewers = parseReviewersByNames(ctx, form.Reviewers, form.TeamReviewers)
if ctx.Written() {
return
}

if err := pull_service.NewPullRequest(ctx, prOpts); err != nil {
if repo_model.IsErrUserDoesNotHaveAccessToRepo(err) {
ctx.Error(http.StatusBadRequest, "UserDoesNotHaveAccessToRepo", err)
} else if errors.Is(err, user_model.ErrBlockedUser) {
Expand Down
108 changes: 54 additions & 54 deletions routers/api/v1/repo/pull_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,47 @@ func DeleteReviewRequests(ctx *context.APIContext) {
apiReviewRequest(ctx, *opts, false)
}

func parseReviewersByNames(ctx *context.APIContext, reviewerNames, teamReviewerNames []string) (reviewers []*user_model.User, teamReviewers []*organization.Team) {
var err error
for _, r := range reviewerNames {
var reviewer *user_model.User
if strings.Contains(r, "@") {
reviewer, err = user_model.GetUserByEmail(ctx, r)
} else {
reviewer, err = user_model.GetUserByName(ctx, r)
}

if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.NotFound("UserNotExist", fmt.Sprintf("User '%s' not exist", r))
return nil, nil
}
ctx.Error(http.StatusInternalServerError, "GetUser", err)
return nil, nil
}

reviewers = append(reviewers, reviewer)
}

if ctx.Repo.Repository.Owner.IsOrganization() && len(teamReviewerNames) > 0 {
for _, t := range teamReviewerNames {
var teamReviewer *organization.Team
teamReviewer, err = organization.GetTeam(ctx, ctx.Repo.Owner.ID, t)
if err != nil {
if organization.IsErrTeamNotExist(err) {
ctx.NotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
return nil, nil
}
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
return nil, nil
}

teamReviewers = append(teamReviewers, teamReviewer)
}
}
return reviewers, teamReviewers
}

func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions, isAdd bool) {
pr, err := issues_model.GetPullRequestByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":index"))
if err != nil {
Expand All @@ -672,42 +713,15 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
return
}

reviewers := make([]*user_model.User, 0, len(opts.Reviewers))

permDoer, err := access_model.GetUserRepoPermission(ctx, pr.Issue.Repo, ctx.Doer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "GetUserRepoPermission", err)
return
}

for _, r := range opts.Reviewers {
var reviewer *user_model.User
if strings.Contains(r, "@") {
reviewer, err = user_model.GetUserByEmail(ctx, r)
} else {
reviewer, err = user_model.GetUserByName(ctx, r)
}

if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.NotFound("UserNotExist", fmt.Sprintf("User '%s' not exist", r))
return
}
ctx.Error(http.StatusInternalServerError, "GetUser", err)
return
}

err = issue_service.IsValidReviewRequest(ctx, reviewer, ctx.Doer, isAdd, pr.Issue, &permDoer)
if err != nil {
if issues_model.IsErrNotValidReviewRequest(err) {
ctx.Error(http.StatusUnprocessableEntity, "NotValidReviewRequest", err)
return
}
ctx.Error(http.StatusInternalServerError, "IsValidReviewRequest", err)
return
}

reviewers = append(reviewers, reviewer)
reviewers, teamReviewers := parseReviewersByNames(ctx, opts.Reviewers, opts.TeamReviewers)
if ctx.Written() {
return
}

var reviews []*issues_model.Review
Expand All @@ -716,12 +730,16 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
}

for _, reviewer := range reviewers {
comment, err := issue_service.ReviewRequest(ctx, pr.Issue, ctx.Doer, reviewer, isAdd)
comment, err := issue_service.ReviewRequest(ctx, pr.Issue, ctx.Doer, &permDoer, reviewer, isAdd)
if err != nil {
if issues_model.IsErrReviewRequestOnClosedPR(err) {
ctx.Error(http.StatusForbidden, "", err)
return
}
if issues_model.IsErrNotValidReviewRequest(err) {
ctx.Error(http.StatusUnprocessableEntity, "", err)
return
}
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
return
}
Expand All @@ -736,35 +754,17 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions
}

if ctx.Repo.Repository.Owner.IsOrganization() && len(opts.TeamReviewers) > 0 {
teamReviewers := make([]*organization.Team, 0, len(opts.TeamReviewers))
for _, t := range opts.TeamReviewers {
var teamReviewer *organization.Team
teamReviewer, err = organization.GetTeam(ctx, ctx.Repo.Owner.ID, t)
for _, teamReviewer := range teamReviewers {
comment, err := issue_service.TeamReviewRequest(ctx, pr.Issue, ctx.Doer, teamReviewer, isAdd)
if err != nil {
if organization.IsErrTeamNotExist(err) {
ctx.NotFound("TeamNotExist", fmt.Sprintf("Team '%s' not exist", t))
if issues_model.IsErrReviewRequestOnClosedPR(err) {
ctx.Error(http.StatusForbidden, "", err)
return
}
ctx.Error(http.StatusInternalServerError, "ReviewRequest", err)
return
}

err = issue_service.IsValidTeamReviewRequest(ctx, teamReviewer, ctx.Doer, isAdd, pr.Issue)
if err != nil {
if issues_model.IsErrNotValidReviewRequest(err) {
ctx.Error(http.StatusUnprocessableEntity, "NotValidReviewRequest", err)
ctx.Error(http.StatusUnprocessableEntity, "", err)
return
}
ctx.Error(http.StatusInternalServerError, "IsValidTeamReviewRequest", err)
return
}

teamReviewers = append(teamReviewers, teamReviewer)
}

for _, teamReviewer := range teamReviewers {
comment, err := issue_service.TeamReviewRequest(ctx, pr.Issue, ctx.Doer, teamReviewer, isAdd)
if err != nil {
ctx.ServerError("TeamReviewRequest", err)
return
}
Expand Down
4 changes: 4 additions & 0 deletions routers/web/repo/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,10 @@ func CompareDiff(ctx *context.Context) {
if ctx.Written() {
return
}
RetrieveRepoReviewers(ctx, ctx.Repo.Repository, nil, true)
if ctx.Written() {
return
}
}
}
beforeCommitID := ctx.Data["BeforeCommitID"].(string)
Expand Down
Loading
Loading