-
Notifications
You must be signed in to change notification settings - Fork 285
Support specification of variable patterns #308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,7 @@ | |
| import com.sonymobile.tools.gerrit.gerritevents.dto.events.RefUpdated; | ||
| import com.sonymobile.tools.gerrit.gerritevents.dto.rest.Notify; | ||
|
|
||
| import hudson.EnvVars; | ||
| import hudson.Extension; | ||
| import hudson.ExtensionList; | ||
| import hudson.Util; | ||
|
|
@@ -85,8 +86,12 @@ | |
| import hudson.model.Queue; | ||
| import hudson.model.Run; | ||
| import hudson.model.Result; | ||
| import hudson.slaves.EnvironmentVariablesNodeProperty; | ||
| import hudson.slaves.NodeProperty; | ||
| import hudson.slaves.NodePropertyDescriptor; | ||
| import hudson.triggers.Trigger; | ||
| import hudson.triggers.TriggerDescriptor; | ||
| import hudson.util.DescribableList; | ||
| import hudson.util.FormValidation; | ||
| import hudson.util.ListBoxModel; | ||
| import hudson.util.ListBoxModel.Option; | ||
|
|
@@ -178,6 +183,9 @@ public class GerritTrigger extends Trigger<Job> { | |
| private List<PluginGerritEvent> triggerOnEvents; | ||
| private boolean dynamicTriggerConfiguration; | ||
| private String triggerConfigURL; | ||
| private final EnvVars envVars; | ||
| private int globalHashVarsHash; | ||
| private int systemEnvVarsHash; | ||
|
|
||
| private GerritTriggerTimerTask gerritTriggerTimerTask; | ||
| private GerritTriggerInformationAction triggerInformationAction; | ||
|
|
@@ -194,8 +202,10 @@ public GerritTrigger(List<GerritProject> gerritProjects) { | |
| this.skipVote = new SkipVote(false, false, false, false); | ||
| this.escapeQuotes = true; | ||
| this.serverName = ANY_SERVER; | ||
| this.envVars = initEnvVars(); | ||
|
|
||
| try { | ||
| DescriptorImpl descriptor = (DescriptorImpl)getDescriptor(); | ||
| DescriptorImpl descriptor = (DescriptorImpl) getDescriptor(); | ||
| if (descriptor != null) { | ||
| ListBoxModel options = descriptor.doFillNotificationLevelItems(this.serverName); | ||
| if (!options.isEmpty()) { | ||
|
|
@@ -334,6 +344,23 @@ public GerritTrigger(List<GerritProject> gerritProjects, SkipVote skipVote, Inte | |
| this.gerritTriggerTimerTask = null; | ||
| this.triggerInformationAction = new GerritTriggerInformationAction(); | ||
| this.notificationLevel = notificationLevel; | ||
| this.envVars = initEnvVars(); | ||
| } | ||
|
|
||
| /** | ||
| * Initializes the environment variables used for expansion. | ||
| */ | ||
| private EnvVars initEnvVars() { | ||
| EnvVars result = new EnvVars(EnvVars.masterEnvVars); | ||
| DescribableList<NodeProperty<?>, NodePropertyDescriptor> globalProps = | ||
| Jenkins.getActiveInstance().getGlobalNodeProperties(); | ||
| EnvironmentVariablesNodeProperty envVarsProp = globalProps.get(EnvironmentVariablesNodeProperty.class); | ||
| EnvVars globalEnvVars = envVarsProp.getEnvVars(); | ||
| result.putAll(globalEnvVars); | ||
|
|
||
| systemEnvVarsHash = EnvVars.masterEnvVars.hashCode(); | ||
| globalHashVarsHash = globalEnvVars.hashCode(); | ||
| return result; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -960,26 +987,27 @@ public boolean equals(Object obj) { | |
| } | ||
| logger.trace("entering isInteresting projects configured: {} the event: {}", allGerritProjects.size(), event); | ||
|
|
||
| updateEnvVarsIfNecessary(); | ||
| for (GerritProject p : allGerritProjects) { | ||
| try { | ||
| if (event instanceof ChangeBasedEvent) { | ||
| ChangeBasedEvent changeBasedEvent = (ChangeBasedEvent)event; | ||
| if (isServerInteresting(event) | ||
| && p.isInteresting(changeBasedEvent.getChange().getProject(), | ||
| changeBasedEvent.getChange().getBranch(), | ||
| changeBasedEvent.getChange().getTopic())) { | ||
| && p.isInteresting(changeBasedEvent.getChange().getProject(), | ||
| changeBasedEvent.getChange().getBranch(), | ||
| changeBasedEvent.getChange().getTopic(), envVars)) { | ||
|
|
||
| boolean containsFilePathsOrForbiddenFilePaths = | ||
| ((p.getFilePaths() != null && p.getFilePaths().size() > 0) | ||
| || (p.getForbiddenFilePaths() != null && p.getForbiddenFilePaths().size() > 0)); | ||
|
|
||
| if (isFileTriggerEnabled() && containsFilePathsOrForbiddenFilePaths) { | ||
| if (isServerInteresting(event) | ||
| && p.isInteresting(changeBasedEvent.getChange().getProject(), | ||
| changeBasedEvent.getChange().getBranch(), | ||
| changeBasedEvent.getChange().getTopic(), | ||
| changeBasedEvent.getFiles( | ||
| new GerritQueryHandler(getServerConfig(event))))) { | ||
| && p.isInteresting(changeBasedEvent.getChange().getProject(), | ||
| changeBasedEvent.getChange().getBranch(), | ||
| changeBasedEvent.getChange().getTopic(), | ||
| changeBasedEvent.getFiles( | ||
| new GerritQueryHandler(getServerConfig(event))), envVars)) { | ||
| logger.trace("According to {} the event is interesting.", p); | ||
| return true; | ||
| } | ||
|
|
@@ -991,20 +1019,39 @@ public boolean equals(Object obj) { | |
| } else if (event instanceof RefUpdated) { | ||
| RefUpdated refUpdated = (RefUpdated)event; | ||
| if (isServerInteresting(event) && p.isInteresting(refUpdated.getRefUpdate().getProject(), | ||
| refUpdated.getRefUpdate().getRefName(), null)) { | ||
| refUpdated.getRefUpdate().getRefName(), null, envVars)) { | ||
| logger.trace("According to {} the event is interesting.", p); | ||
| return true; | ||
| } | ||
| } | ||
| } catch (PatternSyntaxException pse) { | ||
| logger.error(MessageFormat.format("Exception caught for project {0} and pattern {1}, message: {2}", | ||
| new Object[]{job.getName(), p.getPattern(), pse.getMessage()})); | ||
| new Object[]{job.getName(), p.getPattern(), pse.getMessage()})); | ||
| } | ||
| } | ||
| logger.trace("Nothing interesting here, move along folks!"); | ||
| return false; | ||
| } | ||
|
|
||
| /** | ||
| * Checks if the current system env vars are still the same and updates our local copy if necessary | ||
| */ | ||
| private synchronized void updateEnvVarsIfNecessary() { | ||
| EnvironmentVariablesNodeProperty envVarsProp = | ||
| Jenkins.getActiveInstance().getGlobalNodeProperties().get(EnvironmentVariablesNodeProperty.class); | ||
| EnvVars globalEnvVars = envVarsProp.getEnvVars(); | ||
| int newSystemEnvVarsHash = EnvVars.masterEnvVars.hashCode(); | ||
| int newGlobalEnvVarsHash = globalEnvVars.hashCode(); | ||
|
|
||
| if (newSystemEnvVarsHash != systemEnvVarsHash || newGlobalEnvVarsHash != globalHashVarsHash) { | ||
| this.envVars.clear(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. very good point. It extends |
||
| this.envVars.putAll(EnvVars.masterEnvVars); | ||
| this.envVars.putAll(globalEnvVars); | ||
| systemEnvVarsHash = newSystemEnvVarsHash; | ||
| globalHashVarsHash = newGlobalEnvVarsHash; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Check whether the event provider contains the same server name as the serverName field. | ||
| * | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,8 @@ | |
| import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.CompareUtil.AntCompareUtil; | ||
| import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.CompareUtil.PlainCompareUtil; | ||
| import com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data.CompareUtil.RegExpCompareUtil; | ||
| import hudson.EnvVars; | ||
|
|
||
| import java.util.LinkedList; | ||
| import java.util.List; | ||
|
|
||
|
|
@@ -88,7 +90,7 @@ public static CompareType findByOperator(char operator) { | |
| return PLAIN; | ||
| } | ||
|
|
||
| private CompareUtil util; | ||
| CompareUtil util; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be no need for this.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. with the existing setup it was necessary for the test. With your suggestion it won't be any more. Correct. |
||
|
|
||
| /** | ||
| * Private Constructor. | ||
|
|
@@ -102,10 +104,11 @@ private CompareType(CompareUtil util) { | |
| * Tells if the given string matches the given pattern based on the algorithm of this CompareType instance. | ||
| * @param pattern the pattern | ||
| * @param str the string | ||
| * @param envVars the environment variables exisiting on the jenkins host. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The old signature needs to be kept and deprecated for backwards binary compatibility |
||
| * @return true if the string matches the pattern. | ||
| */ | ||
| public boolean matches(String pattern, String str) { | ||
| return util.matches(pattern, str); | ||
| public boolean matches(String pattern, String str, EnvVars envVars) { | ||
| return util.matches(pattern, str, envVars); | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,11 +23,14 @@ | |
| */ | ||
| package com.sonyericsson.hudson.plugins.gerrit.trigger.hudsontrigger.data; | ||
|
|
||
| import java.io.File; | ||
| import hudson.EnvVars; | ||
| import org.apache.tools.ant.types.selectors.SelectorUtils; | ||
|
|
||
| import java.io.File; | ||
|
|
||
| /** | ||
| * Base interface for the compare-algorithms. | ||
| * | ||
| * @author Robert Sandell <[email protected]> | ||
| */ | ||
| public interface CompareUtil { | ||
|
|
@@ -37,9 +40,19 @@ public interface CompareUtil { | |
| * @param pattern the pattern to use. | ||
| * @param str the string to match on. | ||
| * @return true if the string matches the pattern. | ||
| * @deprecated use {@link #matches(String, String, EnvVars)} instead. | ||
| */ | ||
| boolean matches(String pattern, String str); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a |
||
|
|
||
| /** | ||
| * Tells if the given pattern matches the string according to the implemented comparer/algorithm. | ||
| * @param pattern the pattern to use. | ||
| * @param str the string to match on. | ||
| * @param envVars the environment variables exisiting on the jenkins host. Can be {@code null}. | ||
| * @return true if the string matches the pattern. | ||
| */ | ||
| boolean matches(String pattern, String str, EnvVars envVars); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Darn it, I didn't see that this was an interface when I recommended the change to the signatures, but I did say deprecate the old signature and add a new one. The simplest way I can think of at the moment would be to
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't realise that this code might be used by other plugins, I guess there isn't really a way to figure this out?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, sorry. The "darn it" was on me not on you :) |
||
|
|
||
| /** | ||
| * Returns the human-readable name of the util. | ||
| * @return the name. | ||
|
|
@@ -52,20 +65,42 @@ public interface CompareUtil { | |
| */ | ||
| char getOperator(); | ||
|
|
||
| abstract class AbstractCompareUtil implements CompareUtil { | ||
| @Override | ||
| public boolean matches(String pattern, String str) { | ||
| return matches(pattern, str, null); | ||
| } | ||
|
|
||
| /** | ||
| * Expands the pattern in case it contains tokens that can be resolved with the given envVars. | ||
| * @param pattern the pattern to expand. | ||
| * @param envVars the envVars to use for expansion, if {@code null} then the unmodified pattern will be returned | ||
| * @return the expanded string, if no envVars were provided will return the initial unmodified pattern | ||
| */ | ||
| protected String expandWithEnvVarsIfPossible(String pattern, EnvVars envVars) { | ||
| if (envVars != null) { | ||
| return envVars.expand(pattern); | ||
| } else { | ||
| return pattern; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Compares based on Ant-style paths. | ||
| * like <code>my/**/something*.git</code> | ||
| */ | ||
| static class AntCompareUtil implements CompareUtil { | ||
| class AntCompareUtil extends AbstractCompareUtil { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| @Override | ||
| public boolean matches(String pattern, String str) { | ||
| public boolean matches(String pattern, String str, EnvVars envVars) { | ||
| // Replace the Git directory separator character (always '/') | ||
| // with the platform specific directory separator before | ||
| // invoking Ant's platform specific path matching. | ||
| String safePattern = pattern.replace('/', File.separatorChar); | ||
| String expandedPattern = expandWithEnvVarsIfPossible(safePattern, envVars); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is better to do this before the |
||
| String safeStr = str.replace('/', File.separatorChar); | ||
| return SelectorUtils.matchPath(safePattern, safeStr); | ||
| return SelectorUtils.matchPath(expandedPattern, safeStr); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -80,13 +115,15 @@ public char getOperator() { | |
| } | ||
|
|
||
| /** | ||
| * Compares with pattern.equals(str). | ||
| * Compares with pattern.equalsIgnoreCase(str). | ||
| */ | ||
| static class PlainCompareUtil implements CompareUtil { | ||
| class PlainCompareUtil extends AbstractCompareUtil { | ||
|
|
||
| @Override | ||
| public boolean matches(String pattern, String str) { | ||
| return pattern.equalsIgnoreCase(str); | ||
| public boolean matches(String pattern, String str, EnvVars envVars) { | ||
| String expandedPattern = expandWithEnvVarsIfPossible(pattern, envVars); | ||
|
|
||
| return expandedPattern.equalsIgnoreCase(str); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -105,11 +142,12 @@ public char getOperator() { | |
| * string.matches(pattern) | ||
| * @see java.util.regex.Pattern | ||
| */ | ||
| static class RegExpCompareUtil implements CompareUtil { | ||
| class RegExpCompareUtil extends AbstractCompareUtil { | ||
|
|
||
| @Override | ||
| public boolean matches(String pattern, String str) { | ||
| return str.matches(pattern); | ||
| public boolean matches(String pattern, String str, EnvVars envVars) { | ||
| String expandedPattern = expandWithEnvVarsIfPossible(pattern, envVars); | ||
| return str.matches(expandedPattern); | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is no good, when the project is saved these fields will be serialized with the trigger and take up unnecessary disk space.
I think a
ThreadLocalLoadingCacheor something is better.