loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

New webhook trigger for receiving Pull Request review requests (#24481)

close https://github.com/go-gitea/gitea/issues/16321

Provided a webhook trigger for requesting someone to review the Pull
Request.

Some modifications have been made to the returned `PullRequestPayload`
based on the GitHub webhook settings, including:
- add a description of the current reviewer object as
`RequestedReviewer` .
- setting the action to either **review_requested** or
**review_request_removed** based on the operation.
- adding the `RequestedReviewers` field to the issues_model.PullRequest.
This field will be loaded into the PullRequest through
`LoadRequestedReviewers()` when `ToAPIPullRequest` is called.

After the Pull Request is merged, I will supplement the relevant
documentation.

authored by

谈笑风生间 and committed by
GitHub
309354c7 93c6a9a6

+304 -116
+27 -3
models/issues/pull.go
··· 175 175 176 176 ChangedProtectedFiles []string `xorm:"TEXT JSON"` 177 177 178 - IssueID int64 `xorm:"INDEX"` 179 - Issue *Issue `xorm:"-"` 180 - Index int64 178 + IssueID int64 `xorm:"INDEX"` 179 + Issue *Issue `xorm:"-"` 180 + Index int64 181 + RequestedReviewers []*user_model.User `xorm:"-"` 181 182 182 183 HeadRepoID int64 `xorm:"INDEX"` 183 184 HeadRepo *repo_model.Repository `xorm:"-"` ··· 298 299 return fmt.Errorf("pr[%d].LoadHeadRepo[%d]: %w", pr.ID, pr.HeadRepoID, err) 299 300 } 300 301 pr.isHeadRepoLoaded = true 302 + } 303 + return nil 304 + } 305 + 306 + // LoadRequestedReviewers loads the requested reviewers. 307 + func (pr *PullRequest) LoadRequestedReviewers(ctx context.Context) error { 308 + if len(pr.RequestedReviewers) > 0 { 309 + return nil 310 + } 311 + 312 + reviews, err := GetReviewsByIssueID(pr.Issue.ID) 313 + if err != nil { 314 + return err 315 + } 316 + 317 + if len(reviews) > 0 { 318 + err = LoadReviewers(ctx, reviews) 319 + if err != nil { 320 + return err 321 + } 322 + for _, review := range reviews { 323 + pr.RequestedReviewers = append(pr.RequestedReviewers, review.Reviewer) 324 + } 301 325 } 302 326 return nil 303 327 }
+29
models/issues/pull_test.go
··· 9 9 "code.gitea.io/gitea/models/db" 10 10 issues_model "code.gitea.io/gitea/models/issues" 11 11 "code.gitea.io/gitea/models/unittest" 12 + user_model "code.gitea.io/gitea/models/user" 12 13 13 14 "github.com/stretchr/testify/assert" 14 15 ) ··· 72 73 assert.EqualValues(t, 2, prs[1].ID) 73 74 assert.EqualValues(t, 1, prs[2].ID) 74 75 } 76 + } 77 + 78 + func TestLoadRequestedReviewers(t *testing.T) { 79 + assert.NoError(t, unittest.PrepareTestDatabase()) 80 + 81 + pull := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) 82 + assert.NoError(t, pull.LoadIssue(db.DefaultContext)) 83 + issue := pull.Issue 84 + assert.NoError(t, issue.LoadRepo(db.DefaultContext)) 85 + assert.Len(t, pull.RequestedReviewers, 0) 86 + 87 + user1, err := user_model.GetUserByID(db.DefaultContext, 1) 88 + assert.NoError(t, err) 89 + 90 + comment, err := issues_model.AddReviewRequest(issue, user1, &user_model.User{}) 91 + assert.NoError(t, err) 92 + assert.NotNil(t, comment) 93 + 94 + assert.NoError(t, pull.LoadRequestedReviewers(db.DefaultContext)) 95 + assert.Len(t, pull.RequestedReviewers, 1) 96 + 97 + comment, err = issues_model.RemoveReviewRequest(issue, user1, &user_model.User{}) 98 + assert.NoError(t, err) 99 + assert.NotNil(t, comment) 100 + 101 + pull.RequestedReviewers = nil 102 + assert.NoError(t, pull.LoadRequestedReviewers(db.DefaultContext)) 103 + assert.Empty(t, pull.RequestedReviewers) 75 104 } 76 105 77 106 func TestPullRequestsOldest(t *testing.T) {
+23 -2
models/issues/review.go
··· 162 162 return err 163 163 } 164 164 165 + // LoadReviewers loads reviewers 166 + func LoadReviewers(ctx context.Context, reviews []*Review) (err error) { 167 + reviewerIds := make([]int64, len(reviews)) 168 + for i := 0; i < len(reviews); i++ { 169 + reviewerIds[i] = reviews[i].ReviewerID 170 + } 171 + reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIds) 172 + if err != nil { 173 + return err 174 + } 175 + 176 + userMap := make(map[int64]*user_model.User, len(reviewers)) 177 + for _, reviewer := range reviewers { 178 + userMap[reviewer.ID] = reviewer 179 + } 180 + for _, review := range reviews { 181 + review.Reviewer = userMap[review.ReviewerID] 182 + } 183 + return nil 184 + } 185 + 165 186 // LoadReviewerTeam loads reviewer team 166 187 func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) { 167 188 if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil { ··· 520 541 return reviews, sess.Find(&reviews) 521 542 } 522 543 523 - // GetReviewersByIssueID gets the latest review of each reviewer for a pull request 524 - func GetReviewersByIssueID(issueID int64) ([]*Review, error) { 544 + // GetReviewsByIssueID gets the latest review of each reviewer for a pull request 545 + func GetReviewsByIssueID(issueID int64) ([]*Review, error) { 525 546 reviews := make([]*Review, 0, 10) 526 547 527 548 sess := db.GetEngine(db.DefaultContext)
+14 -3
models/issues/review_test.go
··· 132 132 UpdatedUnix: 946684814, 133 133 }) 134 134 135 - allReviews, err := issues_model.GetReviewersByIssueID(issue.ID) 136 - for _, reviewer := range allReviews { 137 - assert.NoError(t, reviewer.LoadReviewer(db.DefaultContext)) 135 + allReviews, err := issues_model.GetReviewsByIssueID(issue.ID) 136 + assert.NoError(t, err) 137 + for _, review := range allReviews { 138 + assert.NoError(t, review.LoadReviewer(db.DefaultContext)) 139 + } 140 + if assert.Len(t, allReviews, 3) { 141 + for i, review := range allReviews { 142 + assert.Equal(t, expectedReviews[i].Reviewer, review.Reviewer) 143 + assert.Equal(t, expectedReviews[i].Type, review.Type) 144 + assert.Equal(t, expectedReviews[i].UpdatedUnix, review.UpdatedUnix) 145 + } 138 146 } 147 + 148 + allReviews, err = issues_model.GetReviewsByIssueID(issue.ID) 139 149 assert.NoError(t, err) 150 + assert.NoError(t, issues_model.LoadReviewers(db.DefaultContext, allReviews)) 140 151 if assert.Len(t, allReviews, 3) { 141 152 for i, review := range allReviews { 142 153 assert.Equal(t, expectedReviews[i].Reviewer, review.Reviewer)
+29
models/user/user.go
··· 20 20 "code.gitea.io/gitea/modules/auth/openid" 21 21 "code.gitea.io/gitea/modules/auth/password/hash" 22 22 "code.gitea.io/gitea/modules/base" 23 + "code.gitea.io/gitea/modules/container" 23 24 "code.gitea.io/gitea/modules/git" 24 25 "code.gitea.io/gitea/modules/log" 25 26 "code.gitea.io/gitea/modules/setting" ··· 910 911 return u, nil 911 912 } 912 913 914 + // GetUserByIDs returns the user objects by given IDs if exists. 915 + func GetUserByIDs(ctx context.Context, ids []int64) ([]*User, error) { 916 + users := make([]*User, 0, len(ids)) 917 + err := db.GetEngine(ctx).In("id", ids). 918 + Table("user"). 919 + Find(&users) 920 + return users, err 921 + } 922 + 913 923 // GetPossibleUserByID returns the user if id > 0 or return system usrs if id < 0 914 924 func GetPossibleUserByID(ctx context.Context, id int64) (*User, error) { 915 925 switch id { ··· 922 932 default: 923 933 return GetUserByID(ctx, id) 924 934 } 935 + } 936 + 937 + // GetPossibleUserByIDs returns the users if id > 0 or return system users if id < 0 938 + func GetPossibleUserByIDs(ctx context.Context, ids []int64) ([]*User, error) { 939 + uniqueIDs := container.SetOf(ids...) 940 + users := make([]*User, 0, len(ids)) 941 + _ = uniqueIDs.Remove(0) 942 + if uniqueIDs.Remove(-1) { 943 + users = append(users, NewGhostUser()) 944 + } 945 + if uniqueIDs.Remove(ActionsUserID) { 946 + users = append(users, NewActionsUser()) 947 + } 948 + res, err := GetUserByIDs(ctx, uniqueIDs.Values()) 949 + if err != nil { 950 + return nil, err 951 + } 952 + users = append(users, res...) 953 + return users, nil 925 954 } 926 955 927 956 // GetUserByNameCtx returns user by given name.
+7
models/webhook/webhook.go
··· 298 298 (w.ChooseEvents && w.HookEvents.Package) 299 299 } 300 300 301 + // HasPullRequestReviewRequestEvent returns true if hook enabled pull request review request event. 302 + func (w *Webhook) HasPullRequestReviewRequestEvent() bool { 303 + return w.SendEverything || 304 + (w.ChooseEvents && w.HookEvents.PullRequestReviewRequest) 305 + } 306 + 301 307 // EventCheckers returns event checkers 302 308 func (w *Webhook) EventCheckers() []struct { 303 309 Has func() bool ··· 329 335 {w.HasRepositoryEvent, webhook_module.HookEventRepository}, 330 336 {w.HasReleaseEvent, webhook_module.HookEventRelease}, 331 337 {w.HasPackageEvent, webhook_module.HookEventPackage}, 338 + {w.HasPullRequestReviewRequestEvent, webhook_module.HookEventPullRequestReviewRequest}, 332 339 } 333 340 } 334 341
+1 -1
models/webhook/webhook_test.go
··· 73 73 "pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone", 74 74 "pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected", 75 75 "pull_request_review_comment", "pull_request_sync", "wiki", "repository", "release", 76 - "package", 76 + "package", "pull_request_review_request", 77 77 }, 78 78 (&Webhook{ 79 79 HookEvent: &webhook_module.HookEvent{SendEverything: true},
+13 -8
modules/structs/hook.go
··· 342 342 HookIssueDemilestoned HookIssueAction = "demilestoned" 343 343 // HookIssueReviewed is an issue action for when a pull request is reviewed 344 344 HookIssueReviewed HookIssueAction = "reviewed" 345 + // HookIssueReviewRequested is an issue action for when a reviewer is requested for a pull request. 346 + HookIssueReviewRequested HookIssueAction = "review_requested" 347 + // HookIssueReviewRequestRemoved is an issue action for removing a review request to someone on a pull request. 348 + HookIssueReviewRequestRemoved HookIssueAction = "review_request_removed" 345 349 ) 346 350 347 351 // IssuePayload represents the payload information that is sent along with an issue event. ··· 381 385 382 386 // PullRequestPayload represents a payload information of pull request event. 383 387 type PullRequestPayload struct { 384 - Action HookIssueAction `json:"action"` 385 - Index int64 `json:"number"` 386 - Changes *ChangesPayload `json:"changes,omitempty"` 387 - PullRequest *PullRequest `json:"pull_request"` 388 - Repository *Repository `json:"repository"` 389 - Sender *User `json:"sender"` 390 - CommitID string `json:"commit_id"` 391 - Review *ReviewPayload `json:"review"` 388 + Action HookIssueAction `json:"action"` 389 + Index int64 `json:"number"` 390 + Changes *ChangesPayload `json:"changes,omitempty"` 391 + PullRequest *PullRequest `json:"pull_request"` 392 + RequestedReviewer *User `json:"requested_reviewer"` 393 + Repository *Repository `json:"repository"` 394 + Sender *User `json:"sender"` 395 + CommitID string `json:"commit_id"` 396 + Review *ReviewPayload `json:"review"` 392 397 } 393 398 394 399 // JSONPayload FIXME
+14 -13
modules/structs/pull.go
··· 9 9 10 10 // PullRequest represents a pull request 11 11 type PullRequest struct { 12 - ID int64 `json:"id"` 13 - URL string `json:"url"` 14 - Index int64 `json:"number"` 15 - Poster *User `json:"user"` 16 - Title string `json:"title"` 17 - Body string `json:"body"` 18 - Labels []*Label `json:"labels"` 19 - Milestone *Milestone `json:"milestone"` 20 - Assignee *User `json:"assignee"` 21 - Assignees []*User `json:"assignees"` 22 - State StateType `json:"state"` 23 - IsLocked bool `json:"is_locked"` 24 - Comments int `json:"comments"` 12 + ID int64 `json:"id"` 13 + URL string `json:"url"` 14 + Index int64 `json:"number"` 15 + Poster *User `json:"user"` 16 + Title string `json:"title"` 17 + Body string `json:"body"` 18 + Labels []*Label `json:"labels"` 19 + Milestone *Milestone `json:"milestone"` 20 + Assignee *User `json:"assignee"` 21 + Assignees []*User `json:"assignees"` 22 + RequestedReviewers []*User `json:"requested_reviewers"` 23 + State StateType `json:"state"` 24 + IsLocked bool `json:"is_locked"` 25 + Comments int `json:"comments"` 25 26 26 27 HTMLURL string `json:"html_url"` 27 28 DiffURL string `json:"diff_url"`
+21 -20
modules/webhook/structs.go
··· 5 5 6 6 // HookEvents is a set of web hook events 7 7 type HookEvents struct { 8 - Create bool `json:"create"` 9 - Delete bool `json:"delete"` 10 - Fork bool `json:"fork"` 11 - Issues bool `json:"issues"` 12 - IssueAssign bool `json:"issue_assign"` 13 - IssueLabel bool `json:"issue_label"` 14 - IssueMilestone bool `json:"issue_milestone"` 15 - IssueComment bool `json:"issue_comment"` 16 - Push bool `json:"push"` 17 - PullRequest bool `json:"pull_request"` 18 - PullRequestAssign bool `json:"pull_request_assign"` 19 - PullRequestLabel bool `json:"pull_request_label"` 20 - PullRequestMilestone bool `json:"pull_request_milestone"` 21 - PullRequestComment bool `json:"pull_request_comment"` 22 - PullRequestReview bool `json:"pull_request_review"` 23 - PullRequestSync bool `json:"pull_request_sync"` 24 - Wiki bool `json:"wiki"` 25 - Repository bool `json:"repository"` 26 - Release bool `json:"release"` 27 - Package bool `json:"package"` 8 + Create bool `json:"create"` 9 + Delete bool `json:"delete"` 10 + Fork bool `json:"fork"` 11 + Issues bool `json:"issues"` 12 + IssueAssign bool `json:"issue_assign"` 13 + IssueLabel bool `json:"issue_label"` 14 + IssueMilestone bool `json:"issue_milestone"` 15 + IssueComment bool `json:"issue_comment"` 16 + Push bool `json:"push"` 17 + PullRequest bool `json:"pull_request"` 18 + PullRequestAssign bool `json:"pull_request_assign"` 19 + PullRequestLabel bool `json:"pull_request_label"` 20 + PullRequestMilestone bool `json:"pull_request_milestone"` 21 + PullRequestComment bool `json:"pull_request_comment"` 22 + PullRequestReview bool `json:"pull_request_review"` 23 + PullRequestSync bool `json:"pull_request_sync"` 24 + PullRequestReviewRequest bool `json:"pull_request_review_request"` 25 + Wiki bool `json:"wiki"` 26 + Repository bool `json:"repository"` 27 + Release bool `json:"release"` 28 + Package bool `json:"package"` 28 29 } 29 30 30 31 // HookEvent represents events that will delivery hook.
+2 -1
modules/webhook/type.go
··· 26 26 HookEventPullRequestReviewRejected HookEventType = "pull_request_review_rejected" 27 27 HookEventPullRequestReviewComment HookEventType = "pull_request_review_comment" 28 28 HookEventPullRequestSync HookEventType = "pull_request_sync" 29 + HookEventPullRequestReviewRequest HookEventType = "pull_request_review_request" 29 30 HookEventWiki HookEventType = "wiki" 30 31 HookEventRepository HookEventType = "repository" 31 32 HookEventRelease HookEventType = "release" ··· 46 47 case HookEventIssues, HookEventIssueAssign, HookEventIssueLabel, HookEventIssueMilestone: 47 48 return "issues" 48 49 case HookEventPullRequest, HookEventPullRequestAssign, HookEventPullRequestLabel, HookEventPullRequestMilestone, 49 - HookEventPullRequestSync: 50 + HookEventPullRequestSync, HookEventPullRequestReviewRequest: 50 51 return "pull_request" 51 52 case HookEventIssueComment, HookEventPullRequestComment: 52 53 return "issue_comment"
+2
options/locale/locale_en-US.ini
··· 2118 2118 settings.event_pull_request_review_desc = Pull request approved, rejected, or review comment. 2119 2119 settings.event_pull_request_sync = Pull Request Synchronized 2120 2120 settings.event_pull_request_sync_desc = Pull request synchronized. 2121 + settings.event_pull_request_review_request = Pull Request Review Requested 2122 + settings.event_pull_request_review_request_desc = Pull request review requested or review request removed. 2121 2123 settings.event_pull_request_approvals = Pull Request Approvals 2122 2124 settings.event_pull_request_merge = Pull Request Merge 2123 2125 settings.event_package = Package
+21 -19
routers/api/v1/utils/hook.go
··· 179 179 HookEvent: &webhook_module.HookEvent{ 180 180 ChooseEvents: true, 181 181 HookEvents: webhook_module.HookEvents{ 182 - Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true), 183 - Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true), 184 - Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true), 185 - Issues: issuesHook(form.Events, "issues_only"), 186 - IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)), 187 - IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)), 188 - IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)), 189 - IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)), 190 - Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true), 191 - PullRequest: pullHook(form.Events, "pull_request_only"), 192 - PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)), 193 - PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)), 194 - PullRequestMilestone: pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)), 195 - PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)), 196 - PullRequestReview: pullHook(form.Events, "pull_request_review"), 197 - PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)), 198 - Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true), 199 - Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true), 200 - Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), 182 + Create: util.SliceContainsString(form.Events, string(webhook_module.HookEventCreate), true), 183 + Delete: util.SliceContainsString(form.Events, string(webhook_module.HookEventDelete), true), 184 + Fork: util.SliceContainsString(form.Events, string(webhook_module.HookEventFork), true), 185 + Issues: issuesHook(form.Events, "issues_only"), 186 + IssueAssign: issuesHook(form.Events, string(webhook_module.HookEventIssueAssign)), 187 + IssueLabel: issuesHook(form.Events, string(webhook_module.HookEventIssueLabel)), 188 + IssueMilestone: issuesHook(form.Events, string(webhook_module.HookEventIssueMilestone)), 189 + IssueComment: issuesHook(form.Events, string(webhook_module.HookEventIssueComment)), 190 + Push: util.SliceContainsString(form.Events, string(webhook_module.HookEventPush), true), 191 + PullRequest: pullHook(form.Events, "pull_request_only"), 192 + PullRequestAssign: pullHook(form.Events, string(webhook_module.HookEventPullRequestAssign)), 193 + PullRequestLabel: pullHook(form.Events, string(webhook_module.HookEventPullRequestLabel)), 194 + PullRequestMilestone: pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)), 195 + PullRequestComment: pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)), 196 + PullRequestReview: pullHook(form.Events, "pull_request_review"), 197 + PullRequestReviewRequest: pullHook(form.Events, string(webhook_module.HookEventPullRequestReviewRequest)), 198 + PullRequestSync: pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)), 199 + Wiki: util.SliceContainsString(form.Events, string(webhook_module.HookEventWiki), true), 200 + Repository: util.SliceContainsString(form.Events, string(webhook_module.HookEventRepository), true), 201 + Release: util.SliceContainsString(form.Events, string(webhook_module.HookEventRelease), true), 201 202 }, 202 203 BranchFilter: form.BranchFilter, 203 204 }, ··· 379 380 w.PullRequestMilestone = pullHook(form.Events, string(webhook_module.HookEventPullRequestMilestone)) 380 381 w.PullRequestComment = pullHook(form.Events, string(webhook_module.HookEventPullRequestComment)) 381 382 w.PullRequestReview = pullHook(form.Events, "pull_request_review") 383 + w.PullRequestReviewRequest = pullHook(form.Events, string(webhook_module.HookEventPullRequestReviewRequest)) 382 384 w.PullRequestSync = pullHook(form.Events, string(webhook_module.HookEventPullRequestSync)) 383 385 384 386 if err := w.UpdateEvent(); err != nil {
+1 -1
routers/web/repo/issue.go
··· 576 576 } 577 577 ctx.Data["OriginalReviews"] = originalAuthorReviews 578 578 579 - reviews, err := issues_model.GetReviewersByIssueID(issue.ID) 579 + reviews, err := issues_model.GetReviewsByIssueID(issue.ID) 580 580 if err != nil { 581 581 ctx.ServerError("GetReviewersByIssueID", err) 582 582 return
+21 -20
routers/web/repo/webhook.go
··· 160 160 SendEverything: form.SendEverything(), 161 161 ChooseEvents: form.ChooseEvents(), 162 162 HookEvents: webhook_module.HookEvents{ 163 - Create: form.Create, 164 - Delete: form.Delete, 165 - Fork: form.Fork, 166 - Issues: form.Issues, 167 - IssueAssign: form.IssueAssign, 168 - IssueLabel: form.IssueLabel, 169 - IssueMilestone: form.IssueMilestone, 170 - IssueComment: form.IssueComment, 171 - Release: form.Release, 172 - Push: form.Push, 173 - PullRequest: form.PullRequest, 174 - PullRequestAssign: form.PullRequestAssign, 175 - PullRequestLabel: form.PullRequestLabel, 176 - PullRequestMilestone: form.PullRequestMilestone, 177 - PullRequestComment: form.PullRequestComment, 178 - PullRequestReview: form.PullRequestReview, 179 - PullRequestSync: form.PullRequestSync, 180 - Wiki: form.Wiki, 181 - Repository: form.Repository, 182 - Package: form.Package, 163 + Create: form.Create, 164 + Delete: form.Delete, 165 + Fork: form.Fork, 166 + Issues: form.Issues, 167 + IssueAssign: form.IssueAssign, 168 + IssueLabel: form.IssueLabel, 169 + IssueMilestone: form.IssueMilestone, 170 + IssueComment: form.IssueComment, 171 + Release: form.Release, 172 + Push: form.Push, 173 + PullRequest: form.PullRequest, 174 + PullRequestAssign: form.PullRequestAssign, 175 + PullRequestLabel: form.PullRequestLabel, 176 + PullRequestMilestone: form.PullRequestMilestone, 177 + PullRequestComment: form.PullRequestComment, 178 + PullRequestReview: form.PullRequestReview, 179 + PullRequestSync: form.PullRequestSync, 180 + PullRequestReviewRequest: form.PullRequestReviewRequest, 181 + Wiki: form.Wiki, 182 + Repository: form.Repository, 183 + Package: form.Package, 183 184 }, 184 185 BranchFilter: form.BranchFilter, 185 186 }
+8
services/convert/pull.go
··· 88 88 }, 89 89 } 90 90 91 + if err = pr.LoadRequestedReviewers(ctx); err != nil { 92 + log.Error("LoadRequestedReviewers[%d]: %v", pr.ID, err) 93 + return nil 94 + } 95 + for _, reviewer := range pr.RequestedReviewers { 96 + apiPullRequest.RequestedReviewers = append(apiPullRequest.RequestedReviewers, ToUser(ctx, reviewer, nil)) 97 + } 98 + 91 99 if pr.Issue.ClosedUnix != 0 { 92 100 apiPullRequest.Closed = pr.Issue.ClosedUnix.AsTimePtr() 93 101 }
+25 -24
services/forms/repo_form.go
··· 228 228 229 229 // WebhookForm form for changing web hook 230 230 type WebhookForm struct { 231 - Events string 232 - Create bool 233 - Delete bool 234 - Fork bool 235 - Issues bool 236 - IssueAssign bool 237 - IssueLabel bool 238 - IssueMilestone bool 239 - IssueComment bool 240 - Release bool 241 - Push bool 242 - PullRequest bool 243 - PullRequestAssign bool 244 - PullRequestLabel bool 245 - PullRequestMilestone bool 246 - PullRequestComment bool 247 - PullRequestReview bool 248 - PullRequestSync bool 249 - Wiki bool 250 - Repository bool 251 - Package bool 252 - Active bool 253 - BranchFilter string `binding:"GlobPattern"` 254 - AuthorizationHeader string 231 + Events string 232 + Create bool 233 + Delete bool 234 + Fork bool 235 + Issues bool 236 + IssueAssign bool 237 + IssueLabel bool 238 + IssueMilestone bool 239 + IssueComment bool 240 + Release bool 241 + Push bool 242 + PullRequest bool 243 + PullRequestAssign bool 244 + PullRequestLabel bool 245 + PullRequestMilestone bool 246 + PullRequestComment bool 247 + PullRequestReview bool 248 + PullRequestSync bool 249 + PullRequestReviewRequest bool 250 + Wiki bool 251 + Repository bool 252 + Package bool 253 + Active bool 254 + BranchFilter string `binding:"GlobPattern"` 255 + AuthorizationHeader string 255 256 } 256 257 257 258 // PushOnly if the hook will be triggered when push
+28
services/webhook/notifier.go
··· 719 719 } 720 720 } 721 721 722 + func (m *webhookNotifier) NotifyPullReviewRequest(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, reviewer *user_model.User, isRequest bool, comment *issues_model.Comment) { 723 + if !issue.IsPull { 724 + log.Warn("NotifyPullReviewRequest: issue is not a pull request: %v", issue.ID) 725 + return 726 + } 727 + mode, _ := access_model.AccessLevelUnit(ctx, doer, issue.Repo, unit.TypePullRequests) 728 + if err := issue.LoadPullRequest(ctx); err != nil { 729 + log.Error("LoadPullRequest failed: %v", err) 730 + return 731 + } 732 + apiPullRequest := &api.PullRequestPayload{ 733 + Index: issue.Index, 734 + PullRequest: convert.ToAPIPullRequest(ctx, issue.PullRequest, nil), 735 + RequestedReviewer: convert.ToUser(ctx, reviewer, nil), 736 + Repository: convert.ToRepo(ctx, issue.Repo, mode), 737 + Sender: convert.ToUser(ctx, doer, nil), 738 + } 739 + if isRequest { 740 + apiPullRequest.Action = api.HookIssueReviewRequested 741 + } else { 742 + apiPullRequest.Action = api.HookIssueReviewRequestRemoved 743 + } 744 + if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventPullRequestReviewRequest, apiPullRequest); err != nil { 745 + log.Error("PrepareWebhooks [review_requested: %v]: %v", isRequest, err) 746 + return 747 + } 748 + } 749 + 722 750 func (m *webhookNotifier) NotifyCreateRef(ctx context.Context, pusher *user_model.User, repo *repo_model.Repository, refType, refFullName, refID string) { 723 751 apiPusher := convert.ToUser(ctx, pusher, nil) 724 752 apiRepo := convert.ToRepo(ctx, repo, perm.AccessModeNone)
+1 -1
services/webhook/payloader.go
··· 43 43 case webhook_module.HookEventPush: 44 44 return s.Push(p.(*api.PushPayload)) 45 45 case webhook_module.HookEventPullRequest, webhook_module.HookEventPullRequestAssign, webhook_module.HookEventPullRequestLabel, 46 - webhook_module.HookEventPullRequestMilestone, webhook_module.HookEventPullRequestSync: 46 + webhook_module.HookEventPullRequestMilestone, webhook_module.HookEventPullRequestSync, webhook_module.HookEventPullRequestReviewRequest: 47 47 return s.PullRequest(p.(*api.PullRequestPayload)) 48 48 case webhook_module.HookEventPullRequestReviewApproved, webhook_module.HookEventPullRequestReviewRejected, webhook_module.HookEventPullRequestReviewComment: 49 49 return s.Review(p.(*api.PullRequestPayload), event)
+10
templates/repo/settings/webhook/settings.tmpl
··· 238 238 </div> 239 239 </div> 240 240 </div> 241 + <!-- Pull Request Review Request --> 242 + <div class="seven wide column"> 243 + <div class="field"> 244 + <div class="ui checkbox"> 245 + <input name="pull_request_review_request" type="checkbox" tabindex="0" {{if .Webhook.PullRequestReviewRequest}}checked{{end}}> 246 + <label>{{.locale.Tr "repo.settings.event_pull_request_review_request"}}</label> 247 + <span class="help">{{.locale.Tr "repo.settings.event_pull_request_review_request_desc"}}</span> 248 + </div> 249 + </div> 250 + </div> 241 251 </div> 242 252 </div> 243 253
+7
templates/swagger/v1_json.tmpl
··· 19934 19934 "type": "string", 19935 19935 "x-go-name": "PatchURL" 19936 19936 }, 19937 + "requested_reviewers": { 19938 + "type": "array", 19939 + "items": { 19940 + "$ref": "#/definitions/User" 19941 + }, 19942 + "x-go-name": "RequestedReviewers" 19943 + }, 19937 19944 "state": { 19938 19945 "$ref": "#/definitions/StateType" 19939 19946 },