Merge branch 'stable-2.15' * stable-2.15: HookQueue: Rename constructor 'queue' argument to avoid confusion Add submit hook Module: Bind listeners in alphabetical order Annotate RefUpdate and CommitReceived as Singleton Reword documentation of ref-update and commit-received hooks Improve hooks documentation structure Change-Id: I163ca67fb412b098e0556f4374d54bde65affc00
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/CommitReceived.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/CommitReceived.java index 06b664b..74a0817 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/hooks/CommitReceived.java +++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/CommitReceived.java
@@ -20,10 +20,12 @@ import com.google.gerrit.server.git.validators.CommitValidationListener; import com.google.gerrit.server.git.validators.CommitValidationMessage; import com.google.inject.Inject; +import com.google.inject.Singleton; import java.util.Collections; import java.util.List; import org.eclipse.jgit.lib.ObjectId; +@Singleton public class CommitReceived implements CommitValidationListener { private final Hook hook; private final HookFactory hookFactory;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/HookQueue.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/HookQueue.java index fb3c5a8..1b2a307 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/hooks/HookQueue.java +++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/HookQueue.java
@@ -31,8 +31,8 @@ private ScheduledExecutorService queue; @Inject - HookQueue(WorkQueue queue) { - workQueue = queue; + HookQueue(WorkQueue workQueue) { + this.workQueue = workQueue; } void submit(Path hook, HookArgs args) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/Module.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/Module.java index df16d15..aeea41e 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/hooks/Module.java +++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/Module.java
@@ -30,6 +30,7 @@ import com.google.gerrit.extensions.events.TopicEditedListener; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.server.git.validators.CommitValidationListener; +import com.google.gerrit.server.git.validators.MergeValidationListener; import com.google.gerrit.server.git.validators.RefOperationValidationListener; import com.google.inject.Scopes; import com.google.inject.internal.UniqueAnnotations; @@ -49,15 +50,15 @@ DynamicSet.bind(binder(), ChangeMergedListener.class).to(ChangeMerged.class); DynamicSet.bind(binder(), ChangeRestoredListener.class).to(ChangeRestored.class); DynamicSet.bind(binder(), CommentAddedListener.class).to(CommentAdded.class); + DynamicSet.bind(binder(), CommitValidationListener.class).to(CommitReceived.class); DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(GitReferenceUpdated.class); DynamicSet.bind(binder(), HashtagsEditedListener.class).to(HashtagsEdited.class); + DynamicSet.bind(binder(), MergeValidationListener.class).to(Submit.class); DynamicSet.bind(binder(), NewProjectCreatedListener.class).to(NewProjectCreated.class); DynamicSet.bind(binder(), RefOperationValidationListener.class).to(RefUpdate.class); DynamicSet.bind(binder(), ReviewerAddedListener.class).to(ReviewerAdded.class); DynamicSet.bind(binder(), ReviewerDeletedListener.class).to(ReviewerDeleted.class); DynamicSet.bind(binder(), RevisionCreatedListener.class).to(RevisionCreated.class); DynamicSet.bind(binder(), TopicEditedListener.class).to(TopicEdited.class); - - DynamicSet.bind(binder(), CommitValidationListener.class).to(CommitReceived.class); } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/RefUpdate.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/RefUpdate.java index 36ab171..90a1b93 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/hooks/RefUpdate.java +++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/RefUpdate.java
@@ -21,10 +21,12 @@ import com.google.gerrit.server.git.validators.ValidationMessage; import com.google.gerrit.server.validators.ValidationException; import com.google.inject.Inject; +import com.google.inject.Singleton; import java.util.Collections; import java.util.List; import org.eclipse.jgit.lib.ObjectId; +@Singleton public class RefUpdate implements RefOperationValidationListener { private final Hook hook; private final HookFactory hookFactory;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/hooks/Submit.java b/src/main/java/com/googlesource/gerrit/plugins/hooks/Submit.java new file mode 100644 index 0000000..7474553 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/hooks/Submit.java
@@ -0,0 +1,63 @@ +// Copyright (C) 2018 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.googlesource.gerrit.plugins.hooks; + +import com.google.gerrit.reviewdb.client.Branch; +import com.google.gerrit.reviewdb.client.PatchSet; +import com.google.gerrit.server.IdentifiedUser; +import com.google.gerrit.server.git.CodeReviewCommit; +import com.google.gerrit.server.git.validators.MergeValidationException; +import com.google.gerrit.server.git.validators.MergeValidationListener; +import com.google.gerrit.server.project.ProjectState; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.eclipse.jgit.lib.Repository; + +@Singleton +public class Submit implements MergeValidationListener { + private final Hook hook; + private final HookFactory hookFactory; + + @Inject + Submit(HookFactory hookFactory) { + this.hook = hookFactory.createSync("submitHook", "submit"); + this.hookFactory = hookFactory; + } + + @Override + public void onPreMerge( + Repository repo, + CodeReviewCommit commit, + ProjectState destProject, + Branch.NameKey destBranch, + PatchSet.Id patchSetId, + IdentifiedUser caller) + throws MergeValidationException { + String projectName = destProject.getProject().getName(); + + HookArgs args = hookFactory.createArgs(); + args.add("--project", projectName); + args.add("--branch", destBranch.get()); + args.add("--submitter", caller.getNameEmail()); + args.add("--submitter-username", caller.getUserName().get()); + args.add("--patchset", patchSetId.get()); + args.add("--commit", commit.getId().name()); + + HookResult result = hook.execute(projectName, args); + if (result != null && result.getExitValue() != 0) { + throw new MergeValidationException(result.toString()); + } + } +}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index e3aa1b9..7a1cbd2 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -78,6 +78,9 @@ hooks.reviewerDeletedHook : Filename for the reviewer update hook. If not set, defaults to `reviewer-deleted`. +hooks.submitHook +: Filename for the submit hook. If not set, defaults to `submit`. + hooks.topicChangedHook : Filename for the topic changed hook. If not set, defaults to `topic-changed`.
diff --git a/src/main/resources/Documentation/hooks.md b/src/main/resources/Documentation/hooks.md index 09a7c25..fd92b63 100644 --- a/src/main/resources/Documentation/hooks.md +++ b/src/main/resources/Documentation/hooks.md
@@ -1,41 +1,56 @@ -Supported Hooks -=============== +# Supported Hooks -ref-update ----------- +[TOC] -This is called when a ref update request is received by Gerrit. It allows a -request to be rejected before it is committed to the Gerrit repository. If -the script exits with non-zero return code the update will be rejected. Any -output from the script will be returned to the user, regardless of the return -code. +## Synchronous Hooks -This hook is called synchronously so it is recommended that it not block. A -default timeout on the hook is set to 30 seconds to avoid "runaway" hooks using -up server threads. See [`hooks.syncHookTimeout`][1] for configuration details. +These hooks are invoked synchronously so it is recommended that they not block. + +A default timeout on the hook is set to 30 seconds to avoid "runaway" hooks using +up server threads. The timeout can be changed by setting [`hooks.syncHookTimeout`][1]. + +### ref-update + +This is called when a ref update request (direct push, non-fastforward update, or +ref deletion) is received by Gerrit. It allows a request to be rejected before it +is committed to the Gerrit repository. + +If the hook exits with non-zero return code the update will be rejected. Any output +from the hook will be returned to the user, regardless of the return code. ``` ref-update --project <project name> --refname <refname> --uploader <uploader> --uploader-username <username> --oldrev <sha1> --newrev <sha1> ``` -commit-received ---------------- +### commit-received -This is called when a push request is received by Gerrit. It allows a push to be -rejected before it is committed to the Gerrit repository. If the script exits -with non-zero return code the push will be rejected. Any output from the script -will be returned to the user, regardless of the return code. +This is called when a commit is received for review by Gerrit. It allows a push to +be rejected before the review is created. -This hook is called synchronously so it is recommended that it not block. A -default timeout on the hook is set to 30 seconds to avoid "runaway" hooks using -up server threads. See [`hooks.syncHookTimeout`][1] for configuration details. +If the hook exits with non-zero return code the push will be rejected. Any output +from the hook will be returned to the user, regardless of the return code. ``` commit-received --project <project name> --refname <refname> --uploader <uploader> --uploader-username <username> --oldrev <sha1> --newrev <sha1> --cmdref <refname> ``` -patchset-created ----------------- +### submit + +This is called when a user attempts to submit a change. It allows the submit to +be rejected. + +If the hook exits with non-zero return code the submit will be rejected and the +ouput from the hook will be returned to the user. + +``` + submit --project <project name> --branch <branch> --submitter <submitter> --patchset <patchset id> --commit <sha1> +``` + +## Asynchronous Hooks + +These hooks are invoked asynchronously on a background thread. + +### patchset-created Called whenever a patchset is created (this includes new changes). @@ -46,8 +61,7 @@ The `--kind` parameter represents the kind of change uploaded. See documentation of [`patchSet`][2] for details. -comment-added -------------- +### comment-added Called whenever a comment is added to a change. @@ -55,8 +69,7 @@ comment-added --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --topic <topic> --author <comment author> --author-username <username> --commit <commit> --comment <comment> [--<approval category id> <score> --<approval category id> <score> --<approval category id>-oldValue <score> ...] ``` -change-merged -------------- +### change-merged Called whenever a change has been merged. @@ -64,8 +77,7 @@ change-merged --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --topic <topic> --submitter <submitter> --submitter-username <username> --commit <sha1> --newrev <sha1> ``` -change-abandoned ----------------- +### change-abandoned Called whenever a change has been abandoned. @@ -73,8 +85,7 @@ change-abandoned --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --topic <topic> --abandoner <abandoner> --abandoner-username <username> --commit <sha1> --reason <reason> ``` -change-restored ---------------- +### change-restored Called whenever a change has been restored. @@ -82,8 +93,7 @@ change-restored --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --topic <topic> --restorer <restorer> --restorer-username <username> --commit <sha1> --reason <reason> ``` -ref-updated ------------ +### ref-updated Called whenever a ref has been updated. @@ -91,8 +101,7 @@ ref-updated --oldrev <old rev> --newrev <new rev> --refname <ref name> --project <project name> --submitter <submitter> --submitter-username <username> ``` -project-created ---------------- +### project-created Called whenever a project has been created. @@ -100,8 +109,7 @@ project-created --project <project name> --head <head name> ``` -reviewer-added --------------- +### reviewer-added Called whenever a reviewer is added to a change. @@ -109,8 +117,7 @@ reviewer-added --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --reviewer <reviewer> --reviewer-username <username> ``` -reviewer-deleted ----------------- +### reviewer-deleted Called whenever a reviewer (with a vote) is removed from a change. @@ -118,8 +125,7 @@ reviewer-deleted --change <change id> --change-url <change url> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --reviewer <reviewer> [--<approval category id> <score> --<approval category id> <score> ...] ``` -topic-changed -------------- +### topic-changed Called whenever a change's topic is changed from the Web UI or via the REST API. @@ -127,8 +133,7 @@ topic-changed --change <change id> --change-owner <change owner> --change-owner-username <username> --project <project name> --branch <branch> --changer <changer> --changer-username <username> --old-topic <old topic> --new-topic <new topic> ``` -hashtags-changed ----------------- +### hashtags-changed Called whenever hashtags are added to or removed from a change from the Web UI or via the REST API. @@ -147,8 +152,7 @@ hashtag remaining on the change after the add or remove operation has been performed. -cla-signed ----------- +### cla-signed Called whenever a user signs a contributor license agreement.