Skip to content

Commit 17030ce

Browse files
Improve notifications for WIP draft PR's (#14663)
* #14559 Reduce amount of email notifications for WIP draft PR's don't notify repo watchers of WIP draft PR's * #13190 Notification when WIP Pull Request is ready for review * Send email notification to repo watchers when WIP PR is created * Send ui notification to repo watchers when WIP PR is created * send specific email notification when PR is marked ready for review instead of reusing the CreatePullRequest action * Fix lint error Co-authored-by: techknowlogick <[email protected]>
1 parent 66f8da5 commit 17030ce

File tree

8 files changed

+97
-43
lines changed

8 files changed

+97
-43
lines changed

models/action.go

+26-25
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,32 @@ type ActionType int
2626

2727
// Possible action types.
2828
const (
29-
ActionCreateRepo ActionType = iota + 1 // 1
30-
ActionRenameRepo // 2
31-
ActionStarRepo // 3
32-
ActionWatchRepo // 4
33-
ActionCommitRepo // 5
34-
ActionCreateIssue // 6
35-
ActionCreatePullRequest // 7
36-
ActionTransferRepo // 8
37-
ActionPushTag // 9
38-
ActionCommentIssue // 10
39-
ActionMergePullRequest // 11
40-
ActionCloseIssue // 12
41-
ActionReopenIssue // 13
42-
ActionClosePullRequest // 14
43-
ActionReopenPullRequest // 15
44-
ActionDeleteTag // 16
45-
ActionDeleteBranch // 17
46-
ActionMirrorSyncPush // 18
47-
ActionMirrorSyncCreate // 19
48-
ActionMirrorSyncDelete // 20
49-
ActionApprovePullRequest // 21
50-
ActionRejectPullRequest // 22
51-
ActionCommentPull // 23
52-
ActionPublishRelease // 24
53-
ActionPullReviewDismissed // 25
29+
ActionCreateRepo ActionType = iota + 1 // 1
30+
ActionRenameRepo // 2
31+
ActionStarRepo // 3
32+
ActionWatchRepo // 4
33+
ActionCommitRepo // 5
34+
ActionCreateIssue // 6
35+
ActionCreatePullRequest // 7
36+
ActionTransferRepo // 8
37+
ActionPushTag // 9
38+
ActionCommentIssue // 10
39+
ActionMergePullRequest // 11
40+
ActionCloseIssue // 12
41+
ActionReopenIssue // 13
42+
ActionClosePullRequest // 14
43+
ActionReopenPullRequest // 15
44+
ActionDeleteTag // 16
45+
ActionDeleteBranch // 17
46+
ActionMirrorSyncPush // 18
47+
ActionMirrorSyncCreate // 19
48+
ActionMirrorSyncDelete // 20
49+
ActionApprovePullRequest // 21
50+
ActionRejectPullRequest // 22
51+
ActionCommentPull // 23
52+
ActionPublishRelease // 24
53+
ActionPullReviewDismissed // 25
54+
ActionPullRequestReadyForReview // 26
5455
)
5556

5657
// Action represents user operation type and other information to

models/notification.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -207,13 +207,14 @@ func createOrUpdateIssueNotifications(e Engine, issueID, commentID, notification
207207
for _, id := range issueWatches {
208208
toNotify[id] = struct{}{}
209209
}
210-
211-
repoWatches, err := getRepoWatchersIDs(e, issue.RepoID)
212-
if err != nil {
213-
return err
214-
}
215-
for _, id := range repoWatches {
216-
toNotify[id] = struct{}{}
210+
if !(issue.IsPull && HasWorkInProgressPrefix(issue.Title)) {
211+
repoWatches, err := getRepoWatchersIDs(e, issue.RepoID)
212+
if err != nil {
213+
return err
214+
}
215+
for _, id := range repoWatches {
216+
toNotify[id] = struct{}{}
217+
}
217218
}
218219
issueParticipants, err := issue.getParticipantIDsByIssue(e)
219220
if err != nil {

models/pull.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -595,9 +595,13 @@ func (pr *PullRequest) IsWorkInProgress() bool {
595595
log.Error("LoadIssue: %v", err)
596596
return false
597597
}
598+
return HasWorkInProgressPrefix(pr.Issue.Title)
599+
}
598600

601+
// HasWorkInProgressPrefix determines if the given PR title has a Work In Progress prefix
602+
func HasWorkInProgressPrefix(title string) bool {
599603
for _, prefix := range setting.Repository.PullRequest.WorkInProgressPrefixes {
600-
if strings.HasPrefix(strings.ToUpper(pr.Issue.Title), prefix) {
604+
if strings.HasPrefix(strings.ToUpper(title), prefix) {
601605
return true
602606
}
603607
}

modules/notification/mail/mail.go

+12
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ func (m *mailNotifier) NotifyIssueChangeStatus(doer *models.User, issue *models.
7373
}
7474
}
7575

76+
func (m *mailNotifier) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
77+
if err := issue.LoadPullRequest(); err != nil {
78+
log.Error("issue.LoadPullRequest: %v", err)
79+
return
80+
}
81+
if issue.IsPull && models.HasWorkInProgressPrefix(oldTitle) && !issue.PullRequest.IsWorkInProgress() {
82+
if err := mailer.MailParticipants(issue, doer, models.ActionPullRequestReadyForReview, nil); err != nil {
83+
log.Error("MailParticipants: %v", err)
84+
}
85+
}
86+
}
87+
7688
func (m *mailNotifier) NotifyNewPullRequest(pr *models.PullRequest, mentions []*models.User) {
7789
if err := mailer.MailParticipants(pr.Issue, pr.Issue.Poster, models.ActionCreatePullRequest, mentions); err != nil {
7890
log.Error("MailParticipants: %v", err)

modules/notification/ui/ui.go

+35-5
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,19 @@ func (ns *notificationService) NotifyIssueChangeStatus(doer *models.User, issue
9494
})
9595
}
9696

97+
func (ns *notificationService) NotifyIssueChangeTitle(doer *models.User, issue *models.Issue, oldTitle string) {
98+
if err := issue.LoadPullRequest(); err != nil {
99+
log.Error("issue.LoadPullRequest: %v", err)
100+
return
101+
}
102+
if issue.IsPull && models.HasWorkInProgressPrefix(oldTitle) && !issue.PullRequest.IsWorkInProgress() {
103+
_ = ns.issueQueue.Push(issueNotificationOpts{
104+
IssueID: issue.ID,
105+
NotificationAuthorID: doer.ID,
106+
})
107+
}
108+
}
109+
97110
func (ns *notificationService) NotifyMergePullRequest(pr *models.PullRequest, doer *models.User) {
98111
_ = ns.issueQueue.Push(issueNotificationOpts{
99112
IssueID: pr.Issue.ID,
@@ -106,15 +119,32 @@ func (ns *notificationService) NotifyNewPullRequest(pr *models.PullRequest, ment
106119
log.Error("Unable to load issue: %d for pr: %d: Error: %v", pr.IssueID, pr.ID, err)
107120
return
108121
}
109-
_ = ns.issueQueue.Push(issueNotificationOpts{
110-
IssueID: pr.Issue.ID,
111-
NotificationAuthorID: pr.Issue.PosterID,
112-
})
122+
toNotify := make(map[int64]struct{}, 32)
123+
repoWatchers, err := models.GetRepoWatchersIDs(pr.Issue.RepoID)
124+
if err != nil {
125+
log.Error("GetRepoWatchersIDs: %v", err)
126+
return
127+
}
128+
for _, id := range repoWatchers {
129+
toNotify[id] = struct{}{}
130+
}
131+
issueParticipants, err := models.GetParticipantsIDsByIssueID(pr.IssueID)
132+
if err != nil {
133+
log.Error("GetParticipantsIDsByIssueID: %v", err)
134+
return
135+
}
136+
for _, id := range issueParticipants {
137+
toNotify[id] = struct{}{}
138+
}
139+
delete(toNotify, pr.Issue.PosterID)
113140
for _, mention := range mentions {
141+
toNotify[mention.ID] = struct{}{}
142+
}
143+
for receiverID := range toNotify {
114144
_ = ns.issueQueue.Push(issueNotificationOpts{
115145
IssueID: pr.Issue.ID,
116146
NotificationAuthorID: pr.Issue.PosterID,
117-
ReceiverID: mention.ID,
147+
ReceiverID: receiverID,
118148
})
119149
}
120150
}

services/mailer/mail.go

+2
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ func actionToTemplate(issue *models.Issue, actionType models.ActionType,
377377
name = "merge"
378378
case models.ActionPullReviewDismissed:
379379
name = "review_dismissed"
380+
case models.ActionPullRequestReadyForReview:
381+
name = "ready_for_review"
380382
default:
381383
switch commentType {
382384
case models.CommentTypeReview:

services/mailer/mail_issue.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const (
3030

3131
// mailIssueCommentToParticipants can be used for both new issue creation and comment.
3232
// This function sends two list of emails:
33-
// 1. Repository watchers and users who are participated in comments.
33+
// 1. Repository watchers (except for WIP pull requests) and users who are participated in comments.
3434
// 2. Users who are not in 1. but get mentioned in current issue/comment.
3535
func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*models.User) error {
3636

@@ -74,11 +74,13 @@ func mailIssueCommentToParticipants(ctx *mailCommentContext, mentions []*models.
7474

7575
// =========== Repo watchers ===========
7676
// Make repo watchers last, since it's likely the list with the most users
77-
ids, err = models.GetRepoWatchersIDs(ctx.Issue.RepoID)
78-
if err != nil {
79-
return fmt.Errorf("GetRepoWatchersIDs(%d): %v", ctx.Issue.RepoID, err)
77+
if !(ctx.Issue.IsPull && ctx.Issue.PullRequest.IsWorkInProgress() && ctx.ActionType != models.ActionCreatePullRequest) {
78+
ids, err = models.GetRepoWatchersIDs(ctx.Issue.RepoID)
79+
if err != nil {
80+
return fmt.Errorf("GetRepoWatchersIDs(%d): %v", ctx.Issue.RepoID, err)
81+
}
82+
unfiltered = append(ids, unfiltered...)
8083
}
81-
unfiltered = append(ids, unfiltered...)
8284

8385
visited := make(map[int64]bool, len(unfiltered)+len(mentions)+1)
8486

templates/mail/issue/default.tmpl

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
<b>@{{.Doer.Name}}</b> commented on this pull request.
5252
{{else if eq .ActionName "review_dismissed"}}
5353
<b>@{{.Doer.Name}}</b> dismissed last review from {{.Comment.Review.Reviewer.Name}} for this pull request.
54+
{{else if eq .ActionName "ready_for_review"}}
55+
<b>@{{.Doer.Name}}</b> marked this pull request ready for review.
5456
{{end}}
5557

5658
{{- if eq .Body ""}}

0 commit comments

Comments
 (0)