Allow uploader to control who should be notified on upload
A new 'notify' option is added that can be specified on push: git push ssh://bot@gerrit:29418/foo HEAD:refs/for/master%notify=NONE It supports the same values as the notify option in ReviewInput: NONE, OWNER, OWNER_REVIEWERS, ALL This is useful to reduce email noise when bot users are automatically uploading changes and patch sets. E.g. a bot that is able to forge committer and author may want to upload a commit without cc-ing the author and the committer of that commit. Change-Id: I473703a439018c3097f5c3de8f47d3f8371551ab Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -146,6 +146,27 @@ Other users (e.g. project owners) who have configured Gerrit to
|
|||||||
notify them of new changes will be automatically sent an email
|
notify them of new changes will be automatically sent an email
|
||||||
message when the push is completed.
|
message when the push is completed.
|
||||||
|
|
||||||
|
[[notify]]
|
||||||
|
|
||||||
|
Uploaders can control to whom email notifications are sent by setting
|
||||||
|
the `notify` option:
|
||||||
|
|
||||||
|
* `NONE`: No email notification will be sent to anyone.
|
||||||
|
* `OWNER`: Only the change owner is notified.
|
||||||
|
* `OWNER_REVIEWERS`: Only owners and reviewers will be notified. This
|
||||||
|
includes all reviewers, existing reviewers of the change and new
|
||||||
|
reviewers that are added by the `reviewer` option or by mentioning
|
||||||
|
in the commit message.
|
||||||
|
* `ALL`: All email notifications will be sent. This includes
|
||||||
|
notifications to watchers, users that have starred the change, CCs
|
||||||
|
and the committer and author of the uploaded commit.
|
||||||
|
|
||||||
|
By default all email notifications are sent.
|
||||||
|
|
||||||
|
====
|
||||||
|
git push ssh://bot@git.example.com:29418/kernel/common HEAD:refs/for/master%notify=NONE
|
||||||
|
====
|
||||||
|
|
||||||
[[topic]]
|
[[topic]]
|
||||||
To include a short tag associated with all of the changes in the
|
To include a short tag associated with all of the changes in the
|
||||||
same group, such as the local topic branch name, append it after
|
same group, such as the local topic branch name, append it after
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.google.common.base.MoreObjects;
|
|||||||
import com.google.gerrit.common.ChangeHooks;
|
import com.google.gerrit.common.ChangeHooks;
|
||||||
import com.google.gerrit.common.FooterConstants;
|
import com.google.gerrit.common.FooterConstants;
|
||||||
import com.google.gerrit.common.data.LabelTypes;
|
import com.google.gerrit.common.data.LabelTypes;
|
||||||
|
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||||
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.Branch;
|
import com.google.gerrit.reviewdb.client.Branch;
|
||||||
@@ -102,6 +103,7 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
|
|||||||
private Iterable<String> groups;
|
private Iterable<String> groups;
|
||||||
private CommitValidators.Policy validatePolicy =
|
private CommitValidators.Policy validatePolicy =
|
||||||
CommitValidators.Policy.GERRIT;
|
CommitValidators.Policy.GERRIT;
|
||||||
|
private NotifyHandling notify = NotifyHandling.ALL;
|
||||||
private Set<Account.Id> reviewers;
|
private Set<Account.Id> reviewers;
|
||||||
private Set<Account.Id> extraCC;
|
private Set<Account.Id> extraCC;
|
||||||
private Map<String, Short> approvals;
|
private Map<String, Short> approvals;
|
||||||
@@ -206,6 +208,11 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ChangeInserter setNotify(NotifyHandling notify) {
|
||||||
|
this.notify = notify;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public ChangeInserter setReviewers(Set<Account.Id> reviewers) {
|
public ChangeInserter setReviewers(Set<Account.Id> reviewers) {
|
||||||
this.reviewers = reviewers;
|
this.reviewers = reviewers;
|
||||||
return this;
|
return this;
|
||||||
@@ -347,6 +354,7 @@ public class ChangeInserter extends BatchUpdate.InsertChangeOp {
|
|||||||
createChangeSenderFactory.create(change.getId());
|
createChangeSenderFactory.create(change.getId());
|
||||||
cm.setFrom(change.getOwner());
|
cm.setFrom(change.getOwner());
|
||||||
cm.setPatchSet(patchSet, patchSetInfo);
|
cm.setPatchSet(patchSet, patchSetInfo);
|
||||||
|
cm.setNotify(notify);
|
||||||
cm.addReviewers(reviewers);
|
cm.addReviewers(reviewers);
|
||||||
cm.addExtraCC(extraCC);
|
cm.addExtraCC(extraCC);
|
||||||
cm.send();
|
cm.send();
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import com.google.gerrit.common.data.LabelTypes;
|
|||||||
import com.google.gerrit.common.data.Permission;
|
import com.google.gerrit.common.data.Permission;
|
||||||
import com.google.gerrit.common.data.PermissionRule;
|
import com.google.gerrit.common.data.PermissionRule;
|
||||||
import com.google.gerrit.extensions.api.changes.HashtagsInput;
|
import com.google.gerrit.extensions.api.changes.HashtagsInput;
|
||||||
|
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
import com.google.gerrit.extensions.registration.DynamicMap.Entry;
|
import com.google.gerrit.extensions.registration.DynamicMap.Entry;
|
||||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
@@ -1188,6 +1189,12 @@ public class ReceiveCommits {
|
|||||||
@Option(name = "--submit", usage = "immediately submit the change")
|
@Option(name = "--submit", usage = "immediately submit the change")
|
||||||
boolean submit;
|
boolean submit;
|
||||||
|
|
||||||
|
@Option(name = "--notify",
|
||||||
|
usage = "Notify handling that defines to whom email notifications "
|
||||||
|
+ "should be sent. Allowed values are NONE, OWNER, "
|
||||||
|
+ "OWNER_REVIEWERS, ALL. If not set, the default is ALL.")
|
||||||
|
NotifyHandling notify = NotifyHandling.ALL;
|
||||||
|
|
||||||
@Option(name = "--reviewer", aliases = {"-r"}, metaVar = "EMAIL",
|
@Option(name = "--reviewer", aliases = {"-r"}, metaVar = "EMAIL",
|
||||||
usage = "add reviewer to changes")
|
usage = "add reviewer to changes")
|
||||||
void reviewer(Account.Id id) {
|
void reviewer(Account.Id id) {
|
||||||
@@ -2372,6 +2379,9 @@ public class ReceiveCommits {
|
|||||||
cm.setFrom(me);
|
cm.setFrom(me);
|
||||||
cm.setPatchSet(newPatchSet, info);
|
cm.setPatchSet(newPatchSet, info);
|
||||||
cm.setChangeMessage(msg);
|
cm.setChangeMessage(msg);
|
||||||
|
if (magicBranch != null) {
|
||||||
|
cm.setNotify(magicBranch.notify);
|
||||||
|
}
|
||||||
cm.addReviewers(recipients.getReviewers());
|
cm.addReviewers(recipients.getReviewers());
|
||||||
cm.addExtraCC(recipients.getCcOnly());
|
cm.addExtraCC(recipients.getCcOnly());
|
||||||
cm.send();
|
cm.send();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.google.gerrit.server.mail;
|
|||||||
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
|
import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
|
||||||
|
|
||||||
import com.google.gerrit.common.errors.EmailException;
|
import com.google.gerrit.common.errors.EmailException;
|
||||||
|
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGroup;
|
import com.google.gerrit.reviewdb.client.AccountGroup;
|
||||||
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
|
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
|
||||||
@@ -294,6 +295,10 @@ public abstract class ChangeEmail extends NotificationEmail {
|
|||||||
|
|
||||||
/** BCC any user who has starred this change. */
|
/** BCC any user who has starred this change. */
|
||||||
protected void bccStarredBy() {
|
protected void bccStarredBy() {
|
||||||
|
if (!NotifyHandling.ALL.equals(notify)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// BCC anyone who has starred this change.
|
// BCC anyone who has starred this change.
|
||||||
//
|
//
|
||||||
@@ -311,6 +316,10 @@ public abstract class ChangeEmail extends NotificationEmail {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final Watchers getWatchers(NotifyType type) throws OrmException {
|
protected final Watchers getWatchers(NotifyType type) throws OrmException {
|
||||||
|
if (!NotifyHandling.ALL.equals(notify)) {
|
||||||
|
return new Watchers();
|
||||||
|
}
|
||||||
|
|
||||||
ProjectWatch watch = new ProjectWatch(
|
ProjectWatch watch = new ProjectWatch(
|
||||||
args, branch.getParentKey(), projectState, changeData);
|
args, branch.getParentKey(), projectState, changeData);
|
||||||
return watch.getWatchers(type);
|
return watch.getWatchers(type);
|
||||||
@@ -318,6 +327,11 @@ public abstract class ChangeEmail extends NotificationEmail {
|
|||||||
|
|
||||||
/** Any user who has published comments on this change. */
|
/** Any user who has published comments on this change. */
|
||||||
protected void ccAllApprovals() {
|
protected void ccAllApprovals() {
|
||||||
|
if (!NotifyHandling.ALL.equals(notify)
|
||||||
|
&& !NotifyHandling.OWNER_REVIEWERS.equals(notify)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (Account.Id id : changeData.reviewers().values()) {
|
for (Account.Id id : changeData.reviewers().values()) {
|
||||||
add(RecipientType.CC, id);
|
add(RecipientType.CC, id);
|
||||||
@@ -329,6 +343,11 @@ public abstract class ChangeEmail extends NotificationEmail {
|
|||||||
|
|
||||||
/** Users who have non-zero approval codes on the change. */
|
/** Users who have non-zero approval codes on the change. */
|
||||||
protected void ccExistingReviewers() {
|
protected void ccExistingReviewers() {
|
||||||
|
if (!NotifyHandling.ALL.equals(notify)
|
||||||
|
&& !NotifyHandling.OWNER_REVIEWERS.equals(notify)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (Account.Id id : changeData.reviewers().get(REVIEWER)) {
|
for (Account.Id id : changeData.reviewers().get(REVIEWER)) {
|
||||||
add(RecipientType.CC, id);
|
add(RecipientType.CC, id);
|
||||||
@@ -356,18 +375,29 @@ public abstract class ChangeEmail extends NotificationEmail {
|
|||||||
protected Set<Account.Id> getAuthors() {
|
protected Set<Account.Id> getAuthors() {
|
||||||
Set<Account.Id> authors = new HashSet<>();
|
Set<Account.Id> authors = new HashSet<>();
|
||||||
|
|
||||||
authors.add(change.getOwner());
|
switch (notify) {
|
||||||
if (patchSet != null) {
|
case NONE:
|
||||||
authors.add(patchSet.getUploader());
|
break;
|
||||||
}
|
case ALL:
|
||||||
if (patchSetInfo != null) {
|
default:
|
||||||
if (patchSetInfo.getAuthor().getAccount() != null) {
|
if (patchSet != null) {
|
||||||
authors.add(patchSetInfo.getAuthor().getAccount());
|
authors.add(patchSet.getUploader());
|
||||||
}
|
}
|
||||||
if (patchSetInfo.getCommitter().getAccount() != null) {
|
if (patchSetInfo != null) {
|
||||||
authors.add(patchSetInfo.getCommitter().getAccount());
|
if (patchSetInfo.getAuthor().getAccount() != null) {
|
||||||
}
|
authors.add(patchSetInfo.getAuthor().getAccount());
|
||||||
|
}
|
||||||
|
if (patchSetInfo.getCommitter().getAccount() != null) {
|
||||||
|
authors.add(patchSetInfo.getCommitter().getAccount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//$FALL-THROUGH$
|
||||||
|
case OWNER_REVIEWERS:
|
||||||
|
case OWNER:
|
||||||
|
authors.add(change.getOwner());
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return authors;
|
return authors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,19 @@ public abstract class NewChangeSender extends ChangeEmail {
|
|||||||
|
|
||||||
setHeader("Message-ID", getChangeMessageThreadId());
|
setHeader("Message-ID", getChangeMessageThreadId());
|
||||||
|
|
||||||
add(RecipientType.TO, reviewers);
|
switch (notify) {
|
||||||
add(RecipientType.CC, extraCC);
|
case NONE:
|
||||||
|
case OWNER:
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
default:
|
||||||
|
add(RecipientType.CC, extraCC);
|
||||||
|
//$FALL-THROUGH$
|
||||||
|
case OWNER_REVIEWERS:
|
||||||
|
add(RecipientType.TO, reviewers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
rcptToAuthors(RecipientType.CC);
|
rcptToAuthors(RecipientType.CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
|
|||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.gerrit.common.errors.EmailException;
|
import com.google.gerrit.common.errors.EmailException;
|
||||||
|
import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling;
|
||||||
import com.google.gerrit.reviewdb.client.Account;
|
import com.google.gerrit.reviewdb.client.Account;
|
||||||
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.EmailStrategy;
|
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.EmailStrategy;
|
||||||
import com.google.gerrit.reviewdb.client.UserIdentity;
|
import com.google.gerrit.reviewdb.client.UserIdentity;
|
||||||
@@ -66,7 +67,7 @@ public abstract class OutgoingEmail {
|
|||||||
|
|
||||||
protected final EmailArguments args;
|
protected final EmailArguments args;
|
||||||
protected Account.Id fromId;
|
protected Account.Id fromId;
|
||||||
|
protected NotifyHandling notify = NotifyHandling.ALL;
|
||||||
|
|
||||||
protected OutgoingEmail(EmailArguments ea, String mc) {
|
protected OutgoingEmail(EmailArguments ea, String mc) {
|
||||||
args = ea;
|
args = ea;
|
||||||
@@ -78,12 +79,20 @@ public abstract class OutgoingEmail {
|
|||||||
fromId = id;
|
fromId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setNotify(NotifyHandling notify) {
|
||||||
|
this.notify = notify;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format and enqueue the message for delivery.
|
* Format and enqueue the message for delivery.
|
||||||
*
|
*
|
||||||
* @throws EmailException
|
* @throws EmailException
|
||||||
*/
|
*/
|
||||||
public void send() throws EmailException {
|
public void send() throws EmailException {
|
||||||
|
if (NotifyHandling.NONE.equals(notify)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!args.emailSender.isEnabled()) {
|
if (!args.emailSender.isEnabled()) {
|
||||||
// Server has explicitly disabled email sending.
|
// Server has explicitly disabled email sending.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user