Support to enable the ITS integration only for certain branches To limit the issue tracker system integration to certain branches one or many refs, ref patterns or regular expressions can be specified as plugin.<its-name>.branch in the project.config file. This is similar to how custom labels in Gerrit core can be limited to certain branches. Change-Id: Ia63c4502ade394c414a406c70f8d34b1cbb77435 Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java b/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java index 2a5ba9f..87758d6 100644 --- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java +++ b/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/its/ItsConfig.java
@@ -14,8 +14,10 @@ package com.googlesource.gerrit.plugins.hooks.its; +import com.google.gerrit.common.data.RefConfigSection; import com.google.gerrit.extensions.annotations.PluginName; import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.config.PluginConfig; import com.google.gerrit.server.config.PluginConfigFactory; import com.google.gerrit.server.events.ChangeAbandonedEvent; @@ -27,7 +29,9 @@ import com.google.gerrit.server.events.RefUpdatedEvent; import com.google.gerrit.server.project.ProjectCache; import com.google.gerrit.server.project.ProjectState; +import com.google.gerrit.server.project.RefPatternMatcher; import com.google.inject.Inject; +import com.google.inject.Provider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,35 +42,43 @@ private final String pluginName; private final ProjectCache projectCache; private final PluginConfigFactory pluginCfgFactory; + private final Provider<CurrentUser> self; @Inject public ItsConfig(@PluginName String pluginName, ProjectCache projectCache, - PluginConfigFactory pluginCfgFactory) { + PluginConfigFactory pluginCfgFactory, Provider<CurrentUser> self) { this.pluginName = pluginName; this.projectCache = projectCache; this.pluginCfgFactory = pluginCfgFactory; + this.self = self; } public boolean isEnabled(ChangeEvent event) { if (event instanceof PatchSetCreatedEvent) { - return isEnabled(((PatchSetCreatedEvent) event).change.project); + PatchSetCreatedEvent e = (PatchSetCreatedEvent) event; + return isEnabled(e.change.project, e.change.branch); } else if (event instanceof CommentAddedEvent) { - return isEnabled(((CommentAddedEvent) event).change.project); + CommentAddedEvent e = (CommentAddedEvent) event; + return isEnabled(e.change.project, e.change.branch); } else if (event instanceof ChangeMergedEvent) { - return isEnabled(((ChangeMergedEvent) event).change.project); + ChangeMergedEvent e = (ChangeMergedEvent) event; + return isEnabled(e.change.project, e.change.branch); } else if (event instanceof ChangeAbandonedEvent) { - return isEnabled(((ChangeAbandonedEvent) event).change.project); + ChangeAbandonedEvent e = (ChangeAbandonedEvent) event; + return isEnabled(e.change.project, e.change.branch); } else if (event instanceof ChangeRestoredEvent) { - return isEnabled(((ChangeRestoredEvent) event).change.project); + ChangeRestoredEvent e = (ChangeRestoredEvent) event; + return isEnabled(e.change.project, e.change.branch); } else if (event instanceof RefUpdatedEvent) { - return isEnabled(((RefUpdatedEvent) event).refUpdate.project); + RefUpdatedEvent e = (RefUpdatedEvent) event; + return isEnabled(e.refUpdate.project, e.refUpdate.refName); } else { log.debug("Event " + event + " not recognised and ignored"); return false; } } - public boolean isEnabled(String project) { + public boolean isEnabled(String project, String branch) { ProjectState projectState = projectCache.get(new Project.NameKey(project)); if (projectState == null) { log.error("Failed to check if " + pluginName + " is enabled for project " @@ -77,12 +89,34 @@ for (ProjectState parentState : projectState.treeInOrder()) { PluginConfig parentCfg = pluginCfgFactory.getFromProjectConfig(parentState, pluginName); - if ("enforced".equals(parentCfg.getString("enabled"))) { + if ("enforced".equals(parentCfg.getString("enabled")) + && isEnabledForBranch(parentState, branch)) { return true; } } return pluginCfgFactory.getFromProjectConfigWithInheritance( - projectState, pluginName).getBoolean("enabled", false); + projectState, pluginName).getBoolean("enabled", false) + && isEnabledForBranch(projectState, branch); + } + + private boolean isEnabledForBranch(ProjectState project, String branch) { + String[] refPatterns = + pluginCfgFactory.getFromProjectConfigWithInheritance(project, + pluginName).getStringList("branch"); + if (refPatterns.length == 0) { + return true; + } + for (String refPattern : refPatterns) { + if (RefConfigSection.isValid(refPattern) && match(branch, refPattern)) { + return true; + } + } + return false; + } + + private boolean match(String branch, String refPattern) { + return RefPatternMatcher.getMatcher(refPattern) + .match(branch, self.get().getUserName()); } }
diff --git a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java b/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java index bf00f13..f47889e 100644 --- a/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java +++ b/its-base/src/main/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateComment.java
@@ -154,7 +154,7 @@ @Override public List<CommitValidationMessage> onCommitReceived( CommitReceivedEvent receiveEvent) throws CommitValidationException { - if (itsConfig.isEnabled(receiveEvent.project.getName())) { + if (itsConfig.isEnabled(receiveEvent.project.getName(), receiveEvent.refName)) { return validCommit(receiveEvent.command, receiveEvent.commit); } else { return Collections.emptyList();
diff --git a/its-base/src/main/resources/Documentation/config.md b/its-base/src/main/resources/Documentation/config.md index f0de506..2b50952 100644 --- a/its-base/src/main/resources/Documentation/config.md +++ b/its-base/src/main/resources/Documentation/config.md
@@ -55,6 +55,21 @@ integration for all child projects by setting `plugin.<its-name>.enabled` to `enforced`. +The issue tracker system integration can be limited to specific +branches by setting `plugin.<its-name>.branch`. The branches may be +configured using explicit branch names, ref patterns, or regular +expressions. Multiple branches may be specified. + +E.g. to limit the issue tracker system integration to the `master` +branch and all stable branches the following could be configured: + +``` + [plugin "<its-name>"] + enabled = true + branch = refs/heads/master + branch = ^refs/heads/stable-.* +``` + [[config-rule-base]] Rule base for Actions
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java b/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java index beb4a9a..eee33cc 100644 --- a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java +++ b/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/validation/ItsValidateCommentTest.java
@@ -512,9 +512,9 @@ itsFacade = createMock(ItsFacade.class); bind(ItsFacade.class).toInstance(itsFacade); - bind(ItsConfig.class).toInstance(new ItsConfig(null, null, null) { + bind(ItsConfig.class).toInstance(new ItsConfig(null, null, null, null) { @Override - public boolean isEnabled(String project) { + public boolean isEnabled(String project, String branch) { return true; } });
diff --git a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java b/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java index 7266d81..9668d7d 100644 --- a/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java +++ b/its-base/src/test/java/com/googlesource/gerrit/plugins/hooks/workflow/ActionControllerTest.java
@@ -198,7 +198,7 @@ actionExecutor = createMock(ActionExecutor.class); bind(ActionExecutor.class).toInstance(actionExecutor); - bind(ItsConfig.class).toInstance(new ItsConfig(null, null, null) { + bind(ItsConfig.class).toInstance(new ItsConfig(null, null, null, null) { @Override public boolean isEnabled(ChangeEvent event) { return true;