Skip to content

Commit

Permalink
Add reviewers selection to new pull request (#32403)
Browse files Browse the repository at this point in the history
Users could add reviewers when creating new PRs.

---------

Co-authored-by: splitt3r <[email protected]>
Co-authored-by: Sebastian Sauer <[email protected]>
Co-authored-by: bb-ben <[email protected]>
Co-authored-by: wxiaoguang <[email protected]>
  • Loading branch information
5 people authored Nov 9, 2024
1 parent d80f99e commit 18aeca5
Show file tree
Hide file tree
Showing 26 changed files with 500 additions and 268 deletions.
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

0 comments on commit 18aeca5

Please sign in to comment.