Send event to stream when draft change is published
When a change is uploaded as a draft, a `patchset-created` event is sent to the event stream, but since drafts are private to the owner, the event is not publicly visible. Furthermore, when the draft is later published, no publicly visible event is sent. The result of this is that external tools that rely on the event stream to detect new changes will not receive events for any changes that are first uploaded as draft. This patch adds a new event, `draft-published`, which is sent to the event stream when a draft change is published. The content of this event is the same as `patchset-created`. Bug: Issue 1437 Change-Id: I72f6dde99a82253ba796c1c13226a8b33f0e82bf
This commit is contained in:

committed by
Shawn O. Pearce

parent
e11af58719
commit
d556c19fbd
@@ -43,8 +43,8 @@ SCHEMA
|
||||
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*,
|
||||
*change-abandoned*, *change-restored*, *change-merged*,
|
||||
*comment-added* and *ref-updated*.
|
||||
*draft-published*, *change-abandoned*, *change-restored*,
|
||||
*change-merged*, *comment-added* and *ref-updated*.
|
||||
|
||||
Note that any field may be missing in the JSON messages, so consumers of
|
||||
this JSON stream should deal with that appropriately.
|
||||
@@ -61,6 +61,16 @@ patchSet:: link:json.html#patchSet[patchSet attribute]
|
||||
|
||||
uploader:: link:json.html#account[account attribute]
|
||||
|
||||
Draft Published
|
||||
^^^^^^^^^^^^^^^
|
||||
type:: "draft-published"
|
||||
|
||||
change:: link:json.html#change[change attribute]
|
||||
|
||||
patchset:: link:json.html#patchset[patchset attribute]
|
||||
|
||||
uploader:: link:json.html#account[account attribute]
|
||||
|
||||
Change Abandoned
|
||||
^^^^^^^^^^^^^^^^
|
||||
type:: "change-abandoned"
|
||||
|
@@ -1180,6 +1180,11 @@ Optional path to hooks, if not specified then `'$site_path'/hooks` will be used.
|
||||
Optional filename for the patchset created hook, if not specified then
|
||||
`patchset-created` will be used.
|
||||
|
||||
[[hooks.draftPublishedHook]]hooks.draftPublishedHook::
|
||||
+
|
||||
Optional filename for the draft published hook, if not specified then
|
||||
`draft-published` will be used.
|
||||
|
||||
[[hooks.commentAddedHook]]hooks.commentAddedHook::
|
||||
+
|
||||
Optional filename for the comment added hook, if not specified then
|
||||
|
@@ -24,12 +24,21 @@ patchset-created
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
This is called whenever a patchset is created (this includes new
|
||||
changes).
|
||||
changes and drafts).
|
||||
|
||||
====
|
||||
patchset-created --change <change id> --change-url <change url> --project <project name> --branch <branch> --uploader <uploader> --commit <sha1> --patchset <patchset id>
|
||||
====
|
||||
|
||||
draft-published
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
This is called whenever a draft change is published.
|
||||
|
||||
====
|
||||
draft-published --change <change id> --change-url <change url> --project <project name> --branch <branch> --uploader <uploader> --commit <sha1> --patchset <patchset id>
|
||||
====
|
||||
|
||||
comment-added
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
@@ -94,8 +103,9 @@ filenames it looks for, by adding a [hooks] section in gerrit.config.
|
||||
Gerrit will use the value of hooks.path for the hooks directory.
|
||||
|
||||
For the hook filenames, Gerrit will use the values of hooks.patchsetCreatedHook,
|
||||
hooks.commentAddedHook, hooks.changeMergedHook, hooks.changeAbandonedHook,
|
||||
hooks.changeRestoredHook, hooks.refUpdatedHook and hooks.claSignedHook.
|
||||
hooks.draftPublishedHook, hooks.commentAddedHook, hooks.changeMergedHook,
|
||||
hooks.changeAbandonedHook, hooks.changeRestoredHook, hooks.refUpdatedHook and
|
||||
hooks.claSignedHook.
|
||||
|
||||
Missing Change URLs
|
||||
-------------------
|
||||
|
@@ -37,6 +37,7 @@ import com.google.gerrit.server.events.ChangeEvent;
|
||||
import com.google.gerrit.server.events.ChangeMergedEvent;
|
||||
import com.google.gerrit.server.events.ChangeRestoreEvent;
|
||||
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.PatchSetCreatedEvent;
|
||||
import com.google.gerrit.server.events.RefUpdatedEvent;
|
||||
@@ -98,6 +99,9 @@ public class ChangeHookRunner implements ChangeHooks {
|
||||
/** Filename of the new patchset hook. */
|
||||
private final File patchsetCreatedHook;
|
||||
|
||||
/** Filename of the draft published hook. */
|
||||
private final File draftPublishedHook;
|
||||
|
||||
/** Filename of the new comments hook. */
|
||||
private final File commentAddedHook;
|
||||
|
||||
@@ -163,6 +167,7 @@ public class ChangeHookRunner implements ChangeHooks {
|
||||
final File hooksPath = sitePath.resolve(getValue(config, "hooks", "path", sitePath.hooks_dir.getAbsolutePath()));
|
||||
|
||||
patchsetCreatedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "patchsetCreatedHook", "patchset-created")).getPath());
|
||||
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());
|
||||
changeAbandonedHook = sitePath.resolve(new File(hooksPath, getValue(config, "hooks", "changeAbandonedHook", "change-abandoned")).getPath());
|
||||
@@ -237,6 +242,28 @@ public class ChangeHookRunner implements ChangeHooks {
|
||||
runHook(change.getProject(), patchsetCreatedHook, args);
|
||||
}
|
||||
|
||||
public void doDraftPublishedHook(final Change change, final PatchSet patchSet,
|
||||
final ReviewDb db) throws OrmException {
|
||||
final DraftPublishedEvent event = new DraftPublishedEvent();
|
||||
final AccountState uploader = accountCache.get(patchSet.getUploader());
|
||||
|
||||
event.change = eventFactory.asChangeAttribute(change);
|
||||
event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
|
||||
event.uploader = eventFactory.asAccountAttribute(uploader.getAccount());
|
||||
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, "--uploader", getDisplayName(uploader.getAccount()));
|
||||
addArg(args, "--commit", event.patchSet.revision);
|
||||
addArg(args, "--patchset", event.patchSet.number);
|
||||
|
||||
runHook(change.getProject(), draftPublishedHook, args);
|
||||
}
|
||||
|
||||
public void doCommentAddedHook(final Change change, final Account account,
|
||||
final PatchSet patchSet, final String comment, final Map<ApprovalCategory.Id,
|
||||
ApprovalCategoryValue.Id> approvals, final ReviewDb db) throws OrmException {
|
||||
|
@@ -46,6 +46,16 @@ public interface ChangeHooks {
|
||||
public void doPatchsetCreatedHook(Change change, PatchSet patchSet,
|
||||
ReviewDb db) throws OrmException;
|
||||
|
||||
/**
|
||||
* Fire the Draft Published Hook.
|
||||
*
|
||||
* @param change The change itself.
|
||||
* @param patchSet The Patchset that was created.
|
||||
* @throws OrmException
|
||||
*/
|
||||
public void doDraftPublishedHook(Change change, PatchSet patchSet,
|
||||
ReviewDb db) throws OrmException;
|
||||
|
||||
/**
|
||||
* Fire the Comment Added Hook.
|
||||
*
|
||||
|
@@ -65,6 +65,11 @@ public final class DisabledChangeHooks implements ChangeHooks {
|
||||
ReviewDb db) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDraftPublishedHook(Change change, PatchSet patchSet,
|
||||
ReviewDb db) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRefUpdatedHook(NameKey refName, RefUpdate refUpdate,
|
||||
Account account) {
|
||||
|
@@ -15,6 +15,7 @@
|
||||
|
||||
package com.google.gerrit.server.changedetail;
|
||||
|
||||
import com.google.gerrit.common.ChangeHooks;
|
||||
import com.google.gerrit.common.data.ReviewResult;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
@@ -37,14 +38,17 @@ public class PublishDraft implements Callable<ReviewResult> {
|
||||
|
||||
private final ChangeControl.Factory changeControlFactory;
|
||||
private final ReviewDb db;
|
||||
private final ChangeHooks hooks;
|
||||
|
||||
private final PatchSet.Id patchSetId;
|
||||
|
||||
@Inject
|
||||
PublishDraft(ChangeControl.Factory changeControlFactory,
|
||||
ReviewDb db, @Assisted final PatchSet.Id patchSetId) {
|
||||
ReviewDb db, @Assisted final PatchSet.Id patchSetId,
|
||||
final ChangeHooks hooks) {
|
||||
this.changeControlFactory = changeControlFactory;
|
||||
this.db = db;
|
||||
this.hooks = hooks;
|
||||
|
||||
this.patchSetId = patchSetId;
|
||||
}
|
||||
@@ -70,19 +74,26 @@ public class PublishDraft implements Callable<ReviewResult> {
|
||||
result.addError(new ReviewResult.Error(
|
||||
ReviewResult.Error.Type.PUBLISH_NOT_PERMITTED));
|
||||
} else {
|
||||
db.patchSets().atomicUpdate(patchSetId, new AtomicUpdate<PatchSet>() {
|
||||
boolean published = false;
|
||||
final PatchSet updatedPatch = db.patchSets().atomicUpdate(patchSetId,
|
||||
new AtomicUpdate<PatchSet>() {
|
||||
@Override
|
||||
public PatchSet update(PatchSet patchset) {
|
||||
if (patchset.isDraft()) {
|
||||
patchset.setDraft(false);
|
||||
return patchset;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if ((updatedPatch != null) && (!updatedPatch.isDraft())) {
|
||||
published = true;
|
||||
}
|
||||
|
||||
final Change change = db.changes().get(changeId);
|
||||
if (change.getStatus() == Change.Status.DRAFT) {
|
||||
db.changes().atomicUpdate(changeId,
|
||||
final Change updatedChange = db.changes().atomicUpdate(changeId,
|
||||
new AtomicUpdate<Change>() {
|
||||
@Override
|
||||
public Change update(Change change) {
|
||||
@@ -95,6 +106,15 @@ public class PublishDraft implements Callable<ReviewResult> {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ((updatedChange != null) &&
|
||||
(updatedChange.getStatus() == Change.Status.NEW)) {
|
||||
published = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (published) {
|
||||
hooks.doDraftPublishedHook(change, patch, db);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 DraftPublishedEvent extends ChangeEvent {
|
||||
public final String type = "draft-published";
|
||||
public ChangeAttribute change;
|
||||
public PatchSetAttribute patchSet;
|
||||
public AccountAttribute uploader;
|
||||
}
|
Reference in New Issue
Block a user