summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMika Hamalainen <mika.hamalainen@accenture.com>2011-09-02 14:39:28 +0300
committerMika Hamalainen <mika.hamalainen@accenture.com>2011-09-02 15:25:54 +0300
commitf94b1355d7066b0fb3194a4d98be6dc138f83386 (patch)
treeba0030a7d8d7ac7df08357fc01b18fac3d04ac60
parent7cf342c74c77ea88fc0de1512de1fdf1a09d84a0 (diff)
Notification e-mails when build is approved
Added e-mail notifications for approved and rejected builds. This includes new e-mail templates and sender classes. The e-mails are send from the staging approve command. Change-Id: I159c166ed1e62ecddfbfea0155d6ca278afe1eb7
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java4
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildApprovedSender.java156
-rw-r--r--gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildRejectedSender.java43
-rw-r--r--gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildApproved.vm44
-rw-r--r--gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildRejected.vm44
-rw-r--r--gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java49
6 files changed, 340 insertions, 0 deletions
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
index e98b49b509..42f145d2e0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
@@ -30,6 +30,8 @@ import com.google.gerrit.server.git.StagingMergeDelegate;
import com.google.gerrit.server.git.SubmitMergeDelegate;
import com.google.gerrit.server.mail.AbandonedSender;
import com.google.gerrit.server.mail.AddReviewerSender;
+import com.google.gerrit.server.mail.BuildApprovedSender;
+import com.google.gerrit.server.mail.BuildRejectedSender;
import com.google.gerrit.server.mail.CommentSender;
import com.google.gerrit.server.mail.CreateChangeSender;
import com.google.gerrit.server.mail.MergeFailSender;
@@ -83,5 +85,7 @@ public class GerritRequestModule extends FactoryModule {
factory(MergeFailSender.Factory.class);
factory(RegisterNewEmailSender.Factory.class);
factory(PerformCreateGroup.Factory.class);
+ factory(BuildApprovedSender.Factory.class);
+ factory(BuildRejectedSender.Factory.class);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildApprovedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildApprovedSender.java
new file mode 100644
index 0000000000..f4ec23f166
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildApprovedSender.java
@@ -0,0 +1,156 @@
+// Copyright (C) 2011 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.server.mail;
+
+import com.google.gerrit.common.data.ApprovalType;
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.AccountProjectWatch;
+import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
+import com.google.gerrit.reviewdb.ApprovalCategory;
+import com.google.gerrit.reviewdb.ApprovalCategoryValue;
+import com.google.gerrit.reviewdb.Change;
+import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gwtorm.client.OrmException;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** Send notice about a change successfully merged. */
+public class BuildApprovedSender extends ReplyToChangeSender {
+ public static interface Factory {
+ public BuildApprovedSender create(Change change);
+ }
+
+ private final ApprovalTypes approvalTypes;
+
+ @Inject
+ public BuildApprovedSender(EmailArguments ea, ApprovalTypes at, @Assisted Change c) {
+ super(ea, c, "build-approved");
+ approvalTypes = at;
+ }
+
+ @Override
+ protected void init() throws EmailException {
+ super.init();
+
+ ccAllApprovals();
+ bccStarredBy();
+ bccWatchesNotifyAllComments();
+ bccWatchesNotifySubmittedChanges();
+ }
+
+ @Override
+ protected void formatChange() throws EmailException {
+ appendText(velocifyFile("BuildApproved.vm"));
+ }
+
+ public String getApprovals() {
+ try {
+ final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> pos =
+ new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>();
+
+ final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> neg =
+ new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>();
+
+ for (PatchSetApproval ca : args.db.get().patchSetApprovals()
+ .byPatchSet(patchSet.getId())) {
+ if (ca.getValue() > 0) {
+ insert(pos, ca);
+ } else if (ca.getValue() < 0) {
+ insert(neg, ca);
+ }
+ }
+
+ return format("Approvals", pos) + format("Objections", neg);
+ } catch (OrmException err) {
+ // Don't list the approvals
+ }
+ return "";
+ }
+
+ private String format(final String type,
+ final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> list) {
+ StringBuilder txt = new StringBuilder();
+ if (list.isEmpty()) {
+ return "";
+ }
+ txt.append(type + ":\n");
+ for (final Map.Entry<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> ent : list
+ .entrySet()) {
+ final Map<ApprovalCategory.Id, PatchSetApproval> l = ent.getValue();
+ txt.append(" ");
+ txt.append(getNameFor(ent.getKey()));
+ txt.append(": ");
+ boolean first = true;
+ for (ApprovalType at : approvalTypes.getApprovalTypes()) {
+ final PatchSetApproval ca = l.get(at.getCategory().getId());
+ if (ca == null) {
+ continue;
+ }
+
+ if (first) {
+ first = false;
+ } else {
+ txt.append("; ");
+ }
+
+ final ApprovalCategoryValue v = at.getValue(ca);
+ if (v != null) {
+ txt.append(v.getName());
+ } else {
+ txt.append(at.getCategory().getName());
+ txt.append("=");
+ if (ca.getValue() > 0) {
+ txt.append("+");
+ }
+ txt.append("" + ca.getValue());
+ }
+ }
+ txt.append("\n");
+ }
+ txt.append("\n");
+ return txt.toString();
+ }
+
+ private void insert(
+ final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> list,
+ final PatchSetApproval ca) {
+ Map<ApprovalCategory.Id, PatchSetApproval> m = list.get(ca.getAccountId());
+ if (m == null) {
+ m = new HashMap<ApprovalCategory.Id, PatchSetApproval>();
+ list.put(ca.getAccountId(), m);
+ }
+ m.put(ca.getCategoryId(), ca);
+ }
+
+ private void bccWatchesNotifySubmittedChanges() {
+ try {
+ // BCC anyone else who has interest in this project's changes
+ //
+ for (final AccountProjectWatch w : getWatches()) {
+ if (w.isNotify(NotifyType.SUBMITTED_CHANGES)) {
+ add(RecipientType.BCC, w.getAccountId());
+ }
+ }
+ } catch (OrmException err) {
+ // Just don't CC everyone. Better to send a partial message to those
+ // we already have queued up then to fail deliver entirely to people
+ // who have a lower interest in the change.
+ }
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildRejectedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildRejectedSender.java
new file mode 100644
index 0000000000..29516a2b76
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/BuildRejectedSender.java
@@ -0,0 +1,43 @@
+// Copyright (C) 2009 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.server.mail;
+
+import com.google.gerrit.reviewdb.Change;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+/** Send notice about a change failing to merged. */
+public class BuildRejectedSender extends ReplyToChangeSender {
+ public static interface Factory {
+ public BuildRejectedSender create(Change change);
+ }
+
+ @Inject
+ public BuildRejectedSender(EmailArguments ea, @Assisted Change c) {
+ super(ea, c, "build-rejected");
+ }
+
+ @Override
+ protected void init() throws EmailException {
+ super.init();
+
+ ccExistingReviewers();
+ }
+
+ @Override
+ protected void formatChange() throws EmailException {
+ appendText(velocifyFile("BuildRejected.vm"));
+ }
+}
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildApproved.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildApproved.vm
new file mode 100644
index 0000000000..4d05422c9e
--- /dev/null
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildApproved.vm
@@ -0,0 +1,44 @@
+## Copyright (C) 2011 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.
+##
+##
+## Template Type:
+## -------------
+## This is a velocity mail template, see: http://velocity.apache.org and the
+## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates.
+##
+## Template File Names and extensions:
+## ----------------------------------
+## Gerrit will use templates ending in ".vm" but will ignore templates ending
+## in ".vm.example". If a .vm template does not exist, the default internal
+## gerrit template which is the same as the .vm.example will be used. If you
+## want to override the default template, copy the .vm.exmaple file to a .vm
+## file and edit it appropriately.
+##
+## This Template:
+## --------------
+## The Merged.vm template will determine the contents of the email related to
+## a change successfully merged to the head. It is a ChangeEmail: see
+## ChangeSubject.vm and ChangeFooter.vm.
+##
+#macro(elipses $length $str)
+#if($str.length() > $length)${str.substring(0,$length)}...#else$str#end
+#end
+$fromName has approved a build with this change and it was merged.
+
+Change subject: $change.subject
+......................................................................
+
+
+$email.changeDetail$email.approvals
diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildRejected.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildRejected.vm
new file mode 100644
index 0000000000..c72a34a9cd
--- /dev/null
+++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/BuildRejected.vm
@@ -0,0 +1,44 @@
+## Copyright (C) 2011 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.
+##
+##
+## Template Type:
+## -------------
+## This is a velocity mail template, see: http://velocity.apache.org and the
+## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates.
+##
+## Template File Names and extensions:
+## ----------------------------------
+## Gerrit will use templates ending in ".vm" but will ignore templates ending
+## in ".vm.example". If a .vm template does not exist, the default internal
+## gerrit template which is the same as the .vm.example will be used. If you
+## want to override the default template, copy the .vm.exmaple file to a .vm
+## file and edit it appropriately.
+##
+## This Template:
+## --------------
+## The MergeFail.vm template will determine the contents of the email related
+## to a failure upon attempting to merge a change to the head. It is a
+## ChangeEmail: see ChangeSubject.vm and ChangeFooter.vm.
+##
+$fromName has REJECTED a build with this change and it needs attention.
+
+Change subject: $change.subject
+......................................................................
+
+
+#if ($email.coverLetter)
+$email.coverLetter
+
+#end
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
index 2ec11326fd..11361a811e 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/StagingApprove.java
@@ -32,6 +32,9 @@ import com.google.gerrit.server.TopicUtil;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeOp;
import com.google.gerrit.server.git.MergeQueue;
+import com.google.gerrit.server.mail.BuildApprovedSender;
+import com.google.gerrit.server.mail.BuildRejectedSender;
+import com.google.gerrit.server.mail.EmailException;
import com.google.gerrit.server.patch.PublishComments;
import com.google.gerrit.server.project.CanSubmitResult;
import com.google.gerrit.server.project.ChangeControl;
@@ -57,6 +60,8 @@ import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Option;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
@@ -75,6 +80,8 @@ import java.util.List;
* $ ssh -p 29418 localhost gerrit staging-approve -p project -b master -i 123 -r=pass
*/
public class StagingApprove extends BaseCommand {
+ private static final Logger log =
+ LoggerFactory.getLogger(StagingApprove.class);
private class MergeException extends Exception {
private static final long serialVersionUID = 1L;
@@ -131,6 +138,12 @@ public class StagingApprove extends BaseCommand {
@Inject
private TopicFunctionState.Factory topicFunctionStateFactory;
+ @Inject
+ private BuildApprovedSender.Factory buildApprovedFactory;
+
+ @Inject
+ private BuildRejectedSender.Factory buildRejectedFactory;
+
@Option(name = "--project", aliases = {"-p"},
required = true, usage = "project name")
private String project;
@@ -365,8 +378,18 @@ public class StagingApprove extends BaseCommand {
case FAST_FORWARD:
hooks.doRefUpdatedHook(destination, branchUpdate,
currentUser.getAccount());
+ try {
+ sendBuildApprovedMails();
+ } catch (Exception e) {
+ log.error("Failed to send change merged e-mails", e);
+ }
break;
default:
+ try {
+ sendBuildRejectedMails();
+ } catch (Exception e) {
+ log.error("Failed to send change merged e-mails", e);
+ }
throw new MergeException("Could not fast-forward build to destination branch");
}
} finally {
@@ -455,4 +478,30 @@ public class StagingApprove extends BaseCommand {
throw new MergeException("fatal: Failed to rebuild staging branch after failed fast-forward", e);
}
}
+
+ private void sendBuildApprovedMails() throws OrmException, EmailException {
+ for (PatchSet patchSet : toApprove) {
+ final PatchSet.Id patchSetId = patchSet.getId();
+ final Change.Id changeId = patchSetId.getParentKey();
+ final Change change = db.changes().get(changeId);
+
+ final BuildApprovedSender sender = buildApprovedFactory.create(change);
+ sender.setFrom(currentUser.getAccountId());
+ sender.setPatchSet(patchSet);
+ sender.send();
+ }
+ }
+
+ private void sendBuildRejectedMails() throws OrmException, EmailException {
+ for (PatchSet patchSet : toApprove) {
+ final PatchSet.Id patchSetId = patchSet.getId();
+ final Change.Id changeId = patchSetId.getParentKey();
+ final Change change = db.changes().get(changeId);
+
+ final BuildRejectedSender sender = buildRejectedFactory.create(change);
+ sender.setFrom(currentUser.getAccountId());
+ sender.setPatchSet(patchSet);
+ sender.send();
+ }
+ }
}