diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt index 0191471fd0..6a78d9f3d9 100644 --- a/Documentation/rest-api-changes.txt +++ b/Documentation/rest-api-changes.txt @@ -5232,6 +5232,14 @@ change operation. Allow creating a new branch when set to `true`. |`merge` |optional| The detail of a merge commit as a link:#merge-input[MergeInput] entity. +|`notify` |optional| +Notify handling that defines to whom email notifications should be sent +after the change is created. + +Allowed values are `NONE`, `OWNER`, `OWNER_REVIEWERS` and `ALL`. + +If not set, the default is `ALL`. +|`notify_details` |optional| +Additional information about whom to notify about the change creation +as a map of recipient type to link:#notify-info[NotifyInfo] entity. |================================== [[change-message-info]] diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java index d1f0b55214..40bd81a47d 100644 --- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java +++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/AbstractDaemonTest.java @@ -49,6 +49,7 @@ import com.google.gerrit.extensions.api.projects.BranchInput; import com.google.gerrit.extensions.api.projects.ProjectInput; import com.google.gerrit.extensions.client.InheritableBoolean; import com.google.gerrit.extensions.client.ListChangesOption; +import com.google.gerrit.extensions.client.ProjectWatchInfo; import com.google.gerrit.extensions.client.SubmitType; import com.google.gerrit.extensions.common.ActionInfo; import com.google.gerrit.extensions.common.ChangeInfo; @@ -1237,4 +1238,17 @@ public abstract class AbstractDaemonTest { assertThat(m.headers().get("To").isEmpty()).isTrue(); assertThat(m.headers().get("CC").isEmpty()).isTrue(); } + + protected void watch(String project, String filter) + throws RestApiException { + List projectsToWatch = new ArrayList<>(); + ProjectWatchInfo pwi = new ProjectWatchInfo(); + pwi.project = project; + pwi.filter = filter; + pwi.notifyAbandonedChanges = true; + pwi.notifyNewChanges = true; + pwi.notifyAllComments = true; + projectsToWatch.add(pwi); + gApi.accounts().self().setWatchedProjects(projectsToWatch); + } } diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java index bcd4280f17..d85356c2d1 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java @@ -28,6 +28,7 @@ import com.google.gerrit.acceptance.PushOneCommit.Result; import com.google.gerrit.acceptance.RestResponse; import com.google.gerrit.extensions.api.changes.ChangeApi; import com.google.gerrit.extensions.api.changes.CherryPickInput; +import com.google.gerrit.extensions.api.changes.NotifyHandling; import com.google.gerrit.extensions.api.changes.ReviewInput; import com.google.gerrit.extensions.client.ChangeStatus; import com.google.gerrit.extensions.client.GeneralPreferencesInfo; @@ -43,6 +44,7 @@ import com.google.gerrit.server.config.AnonymousCowardNameProvider; import com.google.gerrit.server.git.ChangeAlreadyMergedException; import com.google.gerrit.testutil.ConfigSuite; import com.google.gerrit.testutil.TestTimeUtil; +import com.google.gerrit.testutil.FakeEmailSender.Message; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.ObjectId; @@ -55,6 +57,8 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.util.List; + public class CreateChangeIT extends AbstractDaemonTest { @ConfigSuite.Config public static Config allowDraftsDisabled() { @@ -100,6 +104,30 @@ public class CreateChangeIT extends AbstractDaemonTest { assertCreateSucceeds(newChangeInput(ChangeStatus.NEW)); } + @Test + public void notificationsOnChangeCreation() throws Exception { + setApiUser(user); + watch(project.get(), null); + + // check that watcher is notified + setApiUser(admin); + assertCreateSucceeds(newChangeInput(ChangeStatus.NEW)); + + List messages = sender.getMessages(); + assertThat(messages).hasSize(1); + Message m = messages.get(0); + assertThat(m.rcpt()).containsExactly(user.emailAddress); + assertThat(m.body()) + .contains(admin.fullName + " has uploaded this change for review."); + + // check that watcher is not notified if notify=NONE + sender.clear(); + ChangeInput input = newChangeInput(ChangeStatus.NEW); + input.notify = NotifyHandling.NONE; + assertCreateSucceeds(input); + assertThat(sender.getMessages()).isEmpty(); + } + @Test public void createNewChangeSignedOffByFooter() throws Exception { assume().that(isAllowDrafts()).isTrue(); diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java index b0b50fd00e..bed737d5ff 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java @@ -21,8 +21,6 @@ import com.google.gerrit.acceptance.NoHttpd; import com.google.gerrit.acceptance.PushOneCommit; import com.google.gerrit.acceptance.Sandboxed; import com.google.gerrit.acceptance.TestAccount; -import com.google.gerrit.extensions.client.ProjectWatchInfo; -import com.google.gerrit.extensions.restapi.RestApiException; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.account.WatchConfig.NotifyType; import com.google.gerrit.server.git.NotifyConfig; @@ -34,7 +32,6 @@ import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository; import org.eclipse.jgit.junit.TestRepository; import org.junit.Test; -import java.util.ArrayList; import java.util.EnumSet; import java.util.List; @@ -312,17 +309,4 @@ public class ProjectWatchIT extends AbstractDaemonTest { // assert email notification assertThat(sender.getMessages()).hasSize(0); } - - private void watch(String project, String filter) - throws RestApiException { - List projectsToWatch = new ArrayList<>(); - ProjectWatchInfo pwi = new ProjectWatchInfo(); - pwi.project = project; - pwi.filter = filter; - pwi.notifyAbandonedChanges = true; - pwi.notifyNewChanges = true; - pwi.notifyAllComments = true; - projectsToWatch.add(pwi); - gApi.accounts().self().setWatchedProjects(projectsToWatch); - } } diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java index 88c3ea8ce6..b033190c04 100644 --- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java +++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/common/ChangeInput.java @@ -14,8 +14,13 @@ package com.google.gerrit.extensions.common; +import com.google.gerrit.extensions.api.changes.NotifyHandling; +import com.google.gerrit.extensions.api.changes.NotifyInfo; +import com.google.gerrit.extensions.api.changes.RecipientType; import com.google.gerrit.extensions.client.ChangeStatus; +import java.util.Map; + public class ChangeInput { public String project; public String branch; @@ -26,4 +31,8 @@ public class ChangeInput { public String baseChange; public Boolean newBranch; public MergeInput merge; + + /** Who to send email notifications to after change is created. */ + public NotifyHandling notify = NotifyHandling.ALL; + public Map notifyDetails; } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java index f5ddfe5f31..62d9b53eab 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateChange.java @@ -106,6 +106,7 @@ public class CreateChange implements private final boolean allowDrafts; private final MergeUtil.Factory mergeUtilFactory; private final SubmitType submitType; + private final NotifyUtil notifyUtil; @Inject CreateChange(@AnonymousCowardName String anonymousCowardName, @@ -122,7 +123,8 @@ public class CreateChange implements BatchUpdate.Factory updateFactory, PatchSetUtil psUtil, @GerritServerConfig Config config, - MergeUtil.Factory mergeUtilFactory) { + MergeUtil.Factory mergeUtilFactory, + NotifyUtil notifyUtil) { this.anonymousCowardName = anonymousCowardName; this.db = db; this.gitManager = gitManager; @@ -140,6 +142,7 @@ public class CreateChange implements this.submitType = config .getEnum("project", null, "submitType", SubmitType.MERGE_IF_NECESSARY); this.mergeUtilFactory = mergeUtilFactory; + this.notifyUtil = notifyUtil; } @Override @@ -269,6 +272,8 @@ public class CreateChange implements ins.setTopic(topic); ins.setDraft(input.status == ChangeStatus.DRAFT); ins.setGroups(groups); + ins.setNotify(input.notify); + ins.setAccountsToNotify(notifyUtil.resolveAccounts(input.notifyDetails)); try (BatchUpdate bu = updateFactory.create( db.get(), project, me, now)) { bu.setRepository(git, rw, oi);