Send event to stream and execute hook when reviewer is added

When a new reviewer is added on a change, the `reviewer-added`
hook is executed, and the `reviewer-added` event is sent to
the event stream.

This will allow users like automated review bots to monitor the
event stream and take action only when they are explicitly added
as reviewer on a change.

Bug: Issue 1200
Change-Id: I26339360d9e1a5eabb8b6938309d5b411d6cd420
This commit is contained in:
David Pursehouse
2012-09-21 12:50:19 +09:00
committed by Gustaf Lundh
parent 320467f829
commit 2336bd8bac
8 changed files with 108 additions and 6 deletions

View File

@@ -41,6 +41,7 @@ import com.google.gerrit.server.events.DraftPublishedEvent;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.events.ReviewerAddedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.project.ProjectCache;
@@ -117,6 +118,9 @@ public class ChangeHookRunner implements ChangeHooks {
/** Filename of the ref updated hook. */
private final File refUpdatedHook;
/** Filename of the reviewer added hook. */
private final File reviewerAddedHook;
/** Filename of the cla signed hook. */
private final File claSignedHook;
@@ -173,6 +177,7 @@ public class ChangeHookRunner implements ChangeHooks {
changeAbandonedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeAbandonedHook", "change-abandoned")).getPath());
changeRestoredHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeRestoredHook", "change-restored")).getPath());
refUpdatedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "refUpdatedHook", "ref-updated")).getPath());
reviewerAddedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "reviewerAddedHook", "reviewer-added")).getPath());
claSignedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "claSignedHook", "cla-signed")).getPath());
}
@@ -391,6 +396,25 @@ public class ChangeHookRunner implements ChangeHooks {
runHook(refName.getParentKey(), refUpdatedHook, args);
}
public void doReviewerAddedHook(final Change change, final Account account,
final PatchSet patchSet, final ReviewDb db) throws OrmException {
final ReviewerAddedEvent event = new ReviewerAddedEvent();
event.change = eventFactory.asChangeAttribute(change);
event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
event.reviewer = eventFactory.asAccountAttribute(account);
fireEvent(change, event, db);
final List<String> args = new ArrayList<String>();
addArg(args, "--change", event.change.id);
addArg(args, "--change-url", event.change.url);
addArg(args, "--project", event.change.project);
addArg(args, "--branch", event.change.branch);
addArg(args, "--reviewer", getDisplayName(account));
runHook(change.getProject(), reviewerAddedHook, args);
}
public void doClaSignupHook(Account account, ContributorAgreement cla) {
if (account != null) {
final List<String> args = new ArrayList<String>();

View File

@@ -50,7 +50,7 @@ public interface ChangeHooks {
* Fire the Draft Published Hook.
*
* @param change The change itself.
* @param patchSet The Patchset that was created.
* @param patchSet The Patchset that was published.
* @throws OrmException
*/
public void doDraftPublishedHook(Change change, PatchSet patchSet,
@@ -125,5 +125,15 @@ public interface ChangeHooks {
public void doRefUpdatedHook(Branch.NameKey refName, ObjectId oldId,
ObjectId newId, Account account);
/**
* Fire the Reviewer Added Hook
*
* @param change The change itself.
* @param patchSet The patchset that the reviewer was added on.
* @param account The gerrit user who was added as reviewer.
*/
public void doReviewerAddedHook(Change change, Account account,
PatchSet patchSet, ReviewDb db) throws OrmException;
public void doClaSignupHook(Account account, ContributorAgreement cla);
}

View File

@@ -80,6 +80,11 @@ public final class DisabledChangeHooks implements ChangeHooks {
Account account) {
}
@Override
public void doReviewerAddedHook(Change change, Account account, PatchSet patchSet,
ReviewDb db) {
}
@Override
public void removeChangeListener(ChangeListener listener) {
}

View File

@@ -0,0 +1,22 @@
// Copyright (C) 2012 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.events;
public class ReviewerAddedEvent extends ChangeEvent {
public final String type = "reviewer-added";
public ChangeAttribute change;
public PatchSetAttribute patchSet;
public AccountAttribute reviewer;
}

View File

@@ -15,6 +15,7 @@
package com.google.gerrit.server.patch;
import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ReviewerResult;
@@ -26,6 +27,7 @@ import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.account.GroupMembers;
@@ -64,6 +66,8 @@ public class AddReviewer implements Callable<ReviewerResult> {
private final IdentifiedUser.GenericFactory identifiedUserFactory;
private final ApprovalCategory.Id addReviewerCategoryId;
private final Config cfg;
private final ChangeHooks hooks;
private final AccountCache accountCache;
private final Change.Id changeId;
private final Collection<String> reviewers;
@@ -76,7 +80,9 @@ public class AddReviewer implements Callable<ReviewerResult> {
final ChangeControl.Factory changeControlFactory, final ReviewDb db,
final IdentifiedUser.GenericFactory identifiedUserFactory,
final IdentifiedUser currentUser, final ApprovalTypes approvalTypes,
final @GerritServerConfig Config cfg, @Assisted final Change.Id changeId,
final @GerritServerConfig Config cfg, final ChangeHooks hooks,
final AccountCache accountCache,
@Assisted final Change.Id changeId,
@Assisted final Collection<String> reviewers,
@Assisted final boolean confirmed) {
this.addReviewerSenderFactory = addReviewerSenderFactory;
@@ -88,6 +94,8 @@ public class AddReviewer implements Callable<ReviewerResult> {
this.identifiedUserFactory = identifiedUserFactory;
this.currentUser = currentUser;
this.cfg = cfg;
this.hooks = hooks;
this.accountCache = accountCache;
final List<ApprovalType> allTypes = approvalTypes.getApprovalTypes();
addReviewerCategoryId =
@@ -197,7 +205,8 @@ public class AddReviewer implements Callable<ReviewerResult> {
//
final Set<Account.Id> added = new HashSet<Account.Id>();
final List<PatchSetApproval> toInsert = new ArrayList<PatchSetApproval>();
final PatchSet.Id psid = control.getChange().currentPatchSetId();
final Change change = control.getChange();
final PatchSet.Id psid = change.currentPatchSetId();
for (final Account.Id reviewer : reviewerIds) {
if (!exists(psid, reviewer)) {
// This reviewer has not entered an approval for this change yet.
@@ -210,6 +219,14 @@ public class AddReviewer implements Callable<ReviewerResult> {
}
db.patchSetApprovals().insert(toInsert);
// Execute hook for added reviewers
//
final PatchSet patchSet = db.patchSets().get(psid);
for (final Account.Id id : added) {
final Account account = accountCache.get(id).getAccount();
hooks.doReviewerAddedHook(change, account, patchSet, db);
}
// Email the reviewers
//
// The user knows they added themselves, don't bother emailing them.