Send event to stream and execute hook when merge fails

When a change is submitted but fails to merge, execute the
`merge-failed` hook and send the `merge-failed` event to the
event stream.

Bug: Issue 1237
Change-Id: Iab988b3cfc29f22450a8f25148a53ea131e184a7
This commit is contained in:
David Pursehouse 2012-09-28 19:58:59 +09:00
parent 05acbe4c0a
commit f9f3b27509
8 changed files with 117 additions and 5 deletions

View File

@ -44,7 +44,8 @@ The JSON messages consist of nested objects referencing the *change*,
*patchSet*, *account* involved, and other attributes as appropriate.
The currently supported message types are *patchset-created*,
*draft-published*, *change-abandoned*, *change-restored*,
*change-merged*, *comment-added*, *ref-updated* and *reviewer-added*.
*change-merged*, *merge-failed*, *comment-added*, *ref-updated* and
*reviewer-added*.
Note that any field may be missing in the JSON messages, so consumers of
this JSON stream should deal with that appropriately.
@ -105,6 +106,18 @@ patchSet:: link:json.html#patchSet[patchSet attribute]
submitter:: link:json.html#account[account attribute]
Merge Failed
^^^^^^^^^^^^
type:: "merge-failed"
change:: link:json.html#change[change attribute]
patchSet:: link:json.html#patchSet[patchSet attribute]
submitter:: link:json.html#account[account attribute]
reason:: Reason that the merge failed.
Comment Added
^^^^^^^^^^^^^
type:: "comment-added"

View File

@ -1275,6 +1275,11 @@ Optional filename for the comment added hook, if not specified then
Optional filename for the change merged hook, if not specified then
`change-merged` will be used.
[[hooks.mergeFailedHook]]hooks.mergeFailedHook::
+
Optional filename for the merge failed hook, if not specified then
`merge-failed` will be used.
[[hooks.changeAbandonedHook]]hooks.changeAbandonedHook::
+
Optional filename for the change abandoned hook, if not specified then

View File

@ -57,6 +57,15 @@ Called whenever a change has been merged.
change-merged --change <change id> --change-url <change url> --project <project name> --branch <branch> --topic <topic> --submitter <submitter> --commit <sha1>
====
merge-failed
~~~~~~~~~~~~
Called whenever a change has failed to merge.
====
merge-failed --change <change id> --change-url <change url> --project <project name> --branch <branch> --topic <topic> --submitter <submitter> --commit <sha1> --reason <reason>
====
change-abandoned
~~~~~~~~~~~~~~~~

View File

@ -39,6 +39,7 @@ import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
import com.google.gerrit.server.events.DraftPublishedEvent;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.events.MergeFailedEvent;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.events.ReviewerAddedEvent;
@ -109,6 +110,9 @@ public class ChangeHookRunner implements ChangeHooks {
/** Filename of the change merged hook. */
private final File changeMergedHook;
/** Filename of the merge failed hook. */
private final File mergeFailedHook;
/** Filename of the change abandoned hook. */
private final File changeAbandonedHook;
@ -174,6 +178,7 @@ public class ChangeHookRunner implements ChangeHooks {
draftPublishedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "draftPublishedHook", "draft-published")).getPath());
commentAddedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "commentAddedHook", "comment-added")).getPath());
changeMergedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeMergedHook", "change-merged")).getPath());
mergeFailedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "mergeFailed", "merge-failed")).getPath());
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());
@ -329,6 +334,30 @@ public class ChangeHookRunner implements ChangeHooks {
runHook(change.getProject(), changeMergedHook, args);
}
public void doMergeFailedHook(final Change change, final Account account,
final PatchSet patchSet, final String reason,
final ReviewDb db) throws OrmException {
final MergeFailedEvent event = new MergeFailedEvent();
event.change = eventFactory.asChangeAttribute(change);
event.submitter = eventFactory.asAccountAttribute(account);
event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
event.reason = reason;
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, "--topic", event.change.topic);
addArg(args, "--submitter", getDisplayName(account));
addArg(args, "--commit", event.patchSet.revision);
addArg(args, "--reason", reason == null ? "" : reason);
runHook(change.getProject(), mergeFailedHook, args);
}
public void doChangeAbandonedHook(final Change change, final Account account,
final String reason, final ReviewDb db) throws OrmException {
final ChangeAbandonedEvent event = new ChangeAbandonedEvent();

View File

@ -82,6 +82,18 @@ public interface ChangeHooks {
public void doChangeMergedHook(Change change, Account account,
PatchSet patchSet, ReviewDb db) throws OrmException;
/**
* Fire the Merge Failed Hook.
*
* @param change The change itself.
* @param account The gerrit user who attempted to submit the change.
* @param patchSet The patchset that failed to merge.
* @param reason The reason that the change failed to merge.
* @throws OrmException
*/
public void doMergeFailedHook(Change change, Account account,
PatchSet patchSet, String reason, ReviewDb db) throws OrmException;
/**
* Fire the Change Abandoned Hook.
*

View File

@ -45,6 +45,11 @@ public final class DisabledChangeHooks implements ChangeHooks {
PatchSet patchSet, ReviewDb db) {
}
@Override
public void doMergeFailedHook(Change change, Account account,
PatchSet patchSet, String reason, ReviewDb db) {
}
@Override
public void doChangeRestoredHook(Change change, Account account,
String reason, ReviewDb db) {

View File

@ -0,0 +1,23 @@
// 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 MergeFailedEvent extends ChangeEvent {
public final String type = "merge-failed";
public ChangeAttribute change;
public PatchSetAttribute patchSet;
public AccountAttribute submitter;
public String reason;
}

View File

@ -1053,17 +1053,23 @@ public class MergeOp {
}
}
PatchSetApproval submitter = null;
try {
submitter = getSubmitter(db, c.currentPatchSetId());
} catch (Exception e) {
log.error("Cannot get submitter", e);
}
final PatchSetApproval from = submitter;
workQueue.getDefaultQueue()
.submit(requestScopePropagator.wrap(new Runnable() {
@Override
public void run() {
PatchSet patchSet;
PatchSetApproval submitter;
try {
ReviewDb reviewDb = schemaFactory.open();
try {
patchSet = reviewDb.patchSets().get(c.currentPatchSetId());
submitter = getSubmitter(reviewDb, c.currentPatchSetId());
} finally {
reviewDb.close();
}
@ -1074,8 +1080,8 @@ public class MergeOp {
try {
final MergeFailSender cm = mergeFailSenderFactory.create(c);
if (submitter != null) {
cm.setFrom(submitter.getAccountId());
if (from != null) {
cm.setFrom(from.getAccountId());
}
cm.setPatchSet(patchSet);
cm.setChangeMessage(msg);
@ -1090,5 +1096,15 @@ public class MergeOp {
return "send-email merge-failed";
}
}));
if (submitter != null) {
try {
hooks.doMergeFailedHook(c,
accountCache.get(submitter.getAccountId()).getAccount(),
db.patchSets().get(c.currentPatchSetId()), msg.getMessage(), db);
} catch (OrmException ex) {
log.error("Cannot run hook for merge failed " + c.getId(), ex);
}
}
}
}