Support notify settings for rerunning checks
This way bots rerunning checks can control who is notified when the
combined check state changes due to rerunning a check.
Signed-off-by: Edwin Kempin <ekempin@google.com>
Change-Id: Ib9c42e5707c3a10e73e7930c5bbefd7ac065f0ab
diff --git a/java/com/google/gerrit/plugins/checks/api/CheckApi.java b/java/com/google/gerrit/plugins/checks/api/CheckApi.java
index 14acb41..ef42bda 100644
--- a/java/com/google/gerrit/plugins/checks/api/CheckApi.java
+++ b/java/com/google/gerrit/plugins/checks/api/CheckApi.java
@@ -27,7 +27,12 @@
CheckInfo update(CheckInput input) throws RestApiException;
/** Reruns the check and returns the {@link CheckInfo} for the updated check. */
- CheckInfo rerun() throws RestApiException;
+ default CheckInfo rerun() throws RestApiException {
+ return rerun(new RerunInput());
+ }
+
+ /** Reruns the check and returns the {@link CheckInfo} for the updated check. */
+ CheckInfo rerun(RerunInput input) throws RestApiException;
/**
* A default implementation which allows source compatibility when adding new methods to the
* interface.
@@ -44,7 +49,7 @@
}
@Override
- public CheckInfo rerun() throws RestApiException {
+ public CheckInfo rerun(RerunInput input) throws RestApiException {
throw new NotImplementedException();
}
}
diff --git a/java/com/google/gerrit/plugins/checks/api/CheckApiImpl.java b/java/com/google/gerrit/plugins/checks/api/CheckApiImpl.java
index 3be0a74..856eff0 100644
--- a/java/com/google/gerrit/plugins/checks/api/CheckApiImpl.java
+++ b/java/com/google/gerrit/plugins/checks/api/CheckApiImpl.java
@@ -64,9 +64,9 @@
}
@Override
- public CheckInfo rerun() throws RestApiException {
+ public CheckInfo rerun(RerunInput input) throws RestApiException {
try {
- return rerunCheck.apply(checkResource, null).value();
+ return rerunCheck.apply(checkResource, input).value();
} catch (Exception e) {
throw asRestApiException("Cannot rerun check", e);
}
diff --git a/java/com/google/gerrit/plugins/checks/api/RerunCheck.java b/java/com/google/gerrit/plugins/checks/api/RerunCheck.java
index 487742f..273e0f8 100644
--- a/java/com/google/gerrit/plugins/checks/api/RerunCheck.java
+++ b/java/com/google/gerrit/plugins/checks/api/RerunCheck.java
@@ -14,7 +14,6 @@
package com.google.gerrit.plugins.checks.api;
-import com.google.gerrit.extensions.common.Input;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -42,7 +41,7 @@
import org.eclipse.jgit.errors.ConfigInvalidException;
@Singleton
-public class RerunCheck implements RestModifyView<CheckResource, Input> {
+public class RerunCheck implements RestModifyView<CheckResource, RerunInput> {
private final Provider<CurrentUser> self;
private final Checks checks;
private final Provider<ChecksUpdate> checksUpdate;
@@ -64,7 +63,7 @@
}
@Override
- public Response<CheckInfo> apply(CheckResource checkResource, Input input)
+ public Response<CheckInfo> apply(CheckResource checkResource, RerunInput input)
throws RestApiException, IOException, PermissionBackendException, ConfigInvalidException {
if (!self.get().isIdentifiedUser()) {
throw new AuthException("Authentication required");
@@ -72,6 +71,9 @@
if (checkResource.getRevisionResource().getEdit().isPresent()) {
throw new ResourceConflictException("checks are not supported on a change edit");
}
+ if (input == null) {
+ input = new RerunInput();
+ }
CheckKey key =
CheckKey.create(
checkResource.getRevisionResource().getProject(),
@@ -103,7 +105,8 @@
.unsetStarted()
.setMessage("")
.setUrl("");
- updatedCheck = checksUpdate.get().updateCheck(key, builder.build(), null, null);
+ updatedCheck =
+ checksUpdate.get().updateCheck(key, builder.build(), input.notify, input.notifyDetails);
}
return Response.ok(checkJsonFactory.noOptions().format(updatedCheck));
}
diff --git a/java/com/google/gerrit/plugins/checks/api/RerunInput.java b/java/com/google/gerrit/plugins/checks/api/RerunInput.java
new file mode 100644
index 0000000..95b6dbe
--- /dev/null
+++ b/java/com/google/gerrit/plugins/checks/api/RerunInput.java
@@ -0,0 +1,56 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.plugins.checks.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.gerrit.common.Nullable;
+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 java.util.Map;
+import java.util.Objects;
+
+public class RerunInput {
+ /**
+ * Whom to send email notifications to when the combined check state changes due to rerunning this
+ * check.
+ */
+ @Nullable public NotifyHandling notify;
+ /** Additional information about whom to notify regardless of the {@link #notify} setting. */
+ @Nullable public Map<RecipientType, NotifyInfo> notifyDetails;
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof RerunInput)) {
+ return false;
+ }
+ RerunInput other = (RerunInput) o;
+ return Objects.equals(other.notify, notify)
+ && Objects.equals(other.notifyDetails, notifyDetails);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(notify, notifyDetails);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("notify", notify)
+ .add("notifyDetails", notifyDetails)
+ .toString();
+ }
+}
diff --git a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ChecksEmailIT.java b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ChecksEmailIT.java
index 922754d..9667978 100644
--- a/javatests/com/google/gerrit/plugins/checks/acceptance/api/ChecksEmailIT.java
+++ b/javatests/com/google/gerrit/plugins/checks/acceptance/api/ChecksEmailIT.java
@@ -40,6 +40,7 @@
import com.google.gerrit.plugins.checks.api.CheckInput;
import com.google.gerrit.plugins.checks.api.CheckState;
import com.google.gerrit.plugins.checks.api.CombinedCheckState;
+import com.google.gerrit.plugins.checks.api.RerunInput;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.testing.FakeEmailSender.Message;
@@ -351,6 +352,69 @@
assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);
}
+ @Test
+ public void rerunCheckRespectsNotifySettings() throws Exception {
+ testNotifySettingsForRerunCheck(NotifyHandling.ALL, owner, reviewer, starrer, watcher);
+ testNotifySettingsForRerunCheck(NotifyHandling.OWNER, owner);
+ testNotifySettingsForRerunCheck(NotifyHandling.OWNER_REVIEWERS, owner, reviewer);
+ testNotifySettingsForRerunCheck(NotifyHandling.NONE);
+
+ testNotifySettingsForRerunCheck(
+ ImmutableSet.of(user), NotifyHandling.ALL, user, owner, reviewer, starrer, watcher);
+ testNotifySettingsForRerunCheck(ImmutableSet.of(user), NotifyHandling.OWNER, user, owner);
+ testNotifySettingsForRerunCheck(
+ ImmutableSet.of(user), NotifyHandling.OWNER_REVIEWERS, user, owner, reviewer);
+ testNotifySettingsForRerunCheck(ImmutableSet.of(user), NotifyHandling.NONE, user);
+ }
+
+ private void testNotifySettingsForRerunCheck(
+ NotifyHandling notify, TestAccount... expectedRecipients) throws RestApiException {
+ testNotifySettingsForPostCheck(ImmutableSet.of(), notify, expectedRecipients);
+ }
+
+ private void testNotifySettingsForRerunCheck(
+ Set<TestAccount> accountsToNotify, NotifyHandling notify, TestAccount... expectedRecipients)
+ throws RestApiException {
+ // Create a check that sets the combined check state to FAILED.
+ CheckKey checkKey = CheckKey.create(project, patchSetId, checkerUuid1);
+ checkOperations.check(checkKey).forUpdate().state(CheckState.FAILED).upsert();
+ assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.FAILED);
+
+ sender.clear();
+
+ // Post a new check that changes the combined check state to FAILED.
+ requestScopeOperations.setApiUser(bot.id());
+ RerunInput rerunInput = new RerunInput();
+ if (!accountsToNotify.isEmpty()) {
+ rerunInput.notifyDetails =
+ ImmutableMap.of(
+ RecipientType.TO,
+ new NotifyInfo(
+ accountsToNotify.stream().map(TestAccount::username).collect(toImmutableList())));
+ }
+ rerunInput.notify = notify;
+ checksApiFactory.revision(patchSetId).id(checkKey.checkerUuid()).rerun(rerunInput);
+ assertThat(getCombinedCheckState()).isEqualTo(CombinedCheckState.IN_PROGRESS);
+
+ List<Message> messages = sender.getMessages();
+ if (expectedRecipients.length == 0) {
+ assertThat(messages).isEmpty();
+ } else {
+ assertThat(messages).hasSize(1);
+
+ Message message = messages.get(0);
+ assertThat(message.from().getName()).isEqualTo(bot.fullName() + " (Code Review)");
+ assertThat(message.body())
+ .contains(
+ "The combined check state has been updated to " + CombinedCheckState.IN_PROGRESS);
+ assertThat(message.rcpt())
+ .containsExactlyElementsIn(
+ Arrays.stream(expectedRecipients)
+ .map(TestAccount::getEmailAddress)
+ .collect(toImmutableList()));
+ }
+ }
+
private CombinedCheckState getCombinedCheckState() throws RestApiException {
ChangeInfo changeInfo =
gApi.changes()
diff --git a/resources/Documentation/rest-api-checks.md b/resources/Documentation/rest-api-checks.md
index 94346d5..bbab437 100644
--- a/resources/Documentation/rest-api-checks.md
+++ b/resources/Documentation/rest-api-checks.md
@@ -164,6 +164,8 @@
Reruns a check. As response the [CheckInfo](#check-info) entity is returned that
describes the created check.
+Notification options may be specified as [RerunInput](#rerun-input) entity in
+the request body.
This REST endpoint supports rerunning a check. It also resets all relevant check
fields such as `message`, `url`, `started` and `finished`.
@@ -205,6 +207,14 @@
| `notify` | optional | Notify handling that defines to whom email notifications should be sent when the combined check state changes due to posting this check. Allowed values are `NONE`, `OWNER`, `OWNER_REVIEWERS` and `ALL`. If not set, the default is `ALL`.
| `notifyDetails`| optional | Additional information about whom to notify when the combined check state changes due to posting this check as a map of recipient type to [NotifyInfo](../../../Documentation/rest-api-changes.html#notify-info) entity.
+### <a id="rerun-input"> RerunInput
+The `RerunInput` entity contains information for rerunning a check.
+
+| Field Name | | Description |
+| --------------- | -------- | ----------- |
+| `notify` | optional | Notify handling that defines to whom email notifications should be sent when the combined check state changes due to rerunning this check. Allowed values are `NONE`, `OWNER`, `OWNER_REVIEWERS` and `ALL`. If not set, the default is `ALL`.
+| `notifyDetails`| optional | Additional information about whom to notify when the combined check state changes due to rerunning this check as a map of recipient type to [NotifyInfo](../../../Documentation/rest-api-changes.html#notify-info) entity.
+
### <a id="check-state"> CheckState (enum)
The `CheckState` enum can have the following values: `NOT_STARTED`, `FAILED`,
`SCHEDULED`, `RUNNING`, `SUCCESSFUL` and `NOT_RELEVANT`.