Add notify section in project.config

The notify section allows project owners to include emails to users
directly from project.config. This removes the need to create fake
user accounts to always BCC a group mailing list. For example:

  [notify "dev-group"]
    email = dev-team <dev-team@example.com>
    filter = branch:master visibleto:dev

Internal groups may also be used as a mailing list, automatically
BCCing any user that is a member of the group if the group can see
the change:

  [access "refs/heads/*"]
    read = group Developers
  [notify "reviewers"]
    email = group Developers

Change-Id: I02bd05b562e420a4742ff27ffacad8f20648e4f0
This commit is contained in:
Shawn O. Pearce
2012-04-26 16:24:12 -07:00
parent 68e49477c4
commit 57bec12129
17 changed files with 597 additions and 98 deletions

View File

@@ -15,74 +15,65 @@
package com.google.gerrit.server.mail;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.AccountGroupMember;
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.AccountProjectWatch.NotifyType;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Notify interested parties of a brand new change. */
public class CreateChangeSender extends NewChangeSender {
private static final Logger log =
LoggerFactory.getLogger(CreateChangeSender.class);
public static interface Factory {
public CreateChangeSender create(Change change);
}
private final GroupCache groupCache;
@Inject
public CreateChangeSender(EmailArguments ea,
@AnonymousCowardName String anonymousCowardName, SshInfo sshInfo,
GroupCache groupCache, @Assisted Change c) {
@Assisted Change c) {
super(ea, anonymousCowardName, sshInfo, c);
this.groupCache = groupCache;
}
@Override
protected void init() throws EmailException {
super.init();
bccWatchers();
}
private void bccWatchers() {
try {
// BCC anyone who has interest in this project's changes
// Try to mark interested owners with a TO and not a BCC line.
//
final Set<Account.Id> owners = new HashSet<Account.Id>();
for (AccountGroup.UUID uuid : getProjectOwners()) {
AccountGroup group = groupCache.get(uuid);
if (group != null) {
for (AccountGroupMember m : args.db.get().accountGroupMembers()
.byGroup(group.getId())) {
owners.add(m.getAccountId());
}
Watchers matching = getWatches(NotifyType.NEW_CHANGES);
for (Account.Id user : matching.accounts) {
if (isOwnerOfProjectOrBranch(user)) {
add(RecipientType.TO, user);
} else {
add(RecipientType.BCC, user);
}
}
// BCC anyone who has interest in this project's changes
//
for (final AccountProjectWatch w : getWatches()) {
if (w.isNotify(NotifyType.NEW_CHANGES)) {
if (owners.contains(w.getAccountId())) {
add(RecipientType.TO, w.getAccountId());
} else {
add(RecipientType.BCC, w.getAccountId());
}
}
for (Address addr : matching.emails) {
add(RecipientType.BCC, addr);
}
} 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.
log.warn("Cannot BCC watchers for new change", err);
}
}
private boolean isOwnerOfProjectOrBranch(Account.Id user) {
return projectState != null
&& change != null
&& projectState.controlFor(args.identifiedUserFactory.create(user))
.controlForRef(change.getDest())
.isOwner();
}
}