Skip to content
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

Support specification of variable patterns #308

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

rburgst
Copy link

@rburgst rburgst commented Feb 10, 2017

  • this change allows the use of system environment patterns for
    project and branch specification such as

    ${PROJECT_NAME}

  • Example:
    the gerrit host has a configured environment variable defined as

    export PROJECT_NAME=myproject

    now when we push a review commit for "myproject" then the gerrit
    trigger will automatically react

  • one use case for this is to be able to specfiy a generic seed
    job for a jenkins instance which will automatically trigger
    a build on the variable based project

- this change allows the use of system environment patterns for
  project and branch specification such as

  ${PROJECT_NAME}

- Example:
  the gerrit host has a configured environment variable defined as

  export PROJECT_NAME=myproject

  now when we push a review commit for "myproject" then the gerrit
  trigger will automatically react

- one use case for this is to be able to specfiy a generic seed
  job for a jenkins instance which will automatically trigger
  a build on the variable based project
Copy link
Member

@rsandell rsandell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR looks incomplete, did you forget to add some files to the commit?

@@ -56,7 +59,7 @@
* Compares based on Ant-style paths.
* like <code>my/&#042;&#042;/something&#042;.git</code>
*/
static class AntCompareUtil implements CompareUtil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove the static declaration?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntelliJ improvement suggestion. A static inner class in an interface has no effect.

* Compares just like plain comparison, however, patterns are expanded using the
* given system environment settings.
*/
class PlainVarCompareUtil implements CompareUtil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to skip this one and add the functionality to the existing Plain comparer, deprecate the old matches method and introduce a new one that also takes an EnvVars as parameter.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to mess too much with the existing code, but this would definitely be a good improvement. I can do that.

@@ -88,7 +94,7 @@ public static CompareType findByOperator(char operator) {
return PLAIN;
}

private CompareUtil util;
CompareUtil util;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be no need for this.

Copy link
Author

Choose a reason for hiding this comment

The 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.

@@ -8,7 +8,9 @@
You can specify the name pattern in three different ways, as provided by the &quot;Type&quot; drop-down menu.
</p>
<ul>
<li><strong>Plain:</strong> The exact name in Gerrit, case sensitive equality.</li>
<li><strong>Plain:</strong> The exact name in Gerrit, case insensitive equality.</li>
<li><strong>PlainVar:</strong> The exact name in Gerrit, case insensitive equality, allows usage of system environment
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt it is on the gerrit host? You me4an the Jenkins master right? Hard to say since this PR seems incomplete.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the variables have to exist on the Jenkins host.

@rsandell
Copy link
Member

Just tickling the PR builder

@rsandell rsandell closed this Feb 17, 2017
@rsandell rsandell reopened this Feb 17, 2017
@rburgst
Copy link
Author

rburgst commented Feb 17, 2017

My git workspace is clean, what files do you think are missing?

@rsandell
Copy link
Member

Well, there should be a call to inject other than the test, where else would the environment come from?

private final EnvVars systemEnvVars;

public PlainVarCompareUtil() {
systemEnvVars = new EnvVars(EnvVars.masterEnvVars);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I had missed the use of EnvVars.masterEnvVars. I don't think it's a good choice to put it here since you would then only pick up whatever is set when Jenkins starts up and not what is changed during runtime.
We need to find a way to provide it as close to the call to matches as possible, without having to create a new instance and copy over all values from EnvVars.masterEnvVars for every job check, since that could cause some performance issues.

int newSystemEnvVarsHash = EnvVars.masterEnvVars.hashCode();
int newGlobalEnvVarsHash = globalEnvVars.hashCode();
if (newSystemEnvVarsHash != systemEnvVarsHash || newGlobalEnvVarsHash != globalHashVarsHash) {
this.envVars.clear();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is EnvVars thread safe? There are multiple threads accessing this code, so you risk them overwriting eachother.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very good point. It extends TreeMap so unfortunately its not. Is there a performance penalty to consider or is it enough to make it synchronized?

* @return true if the string matches the pattern.
*/
boolean matches(String pattern, String str);
boolean matches(String pattern, String str, EnvVars envVars);
Copy link
Member

@rsandell rsandell Feb 28, 2017

Choose a reason for hiding this comment

The 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.
Since it is a public interface we can't easily tell if there are any implementations of this in other plugins and we need to try to keep binary backwards compatibility.

The simplest way I can think of at the moment would be to

  • Add back boolean matches(String pattern, String str); and deprecate it.
  • Add a new class: AbstractCompareUtil (implements CompareUtil) or something and make it an abstract class, implementing the old method signature that only calls the new method boolean matches(String pattern, String str, EnvVars envVars); with null for envVars.
  • Make AntCompareUtil et.al. extend AbstractCompareUtil instead of implements CompareUtil. They also needs to stay in this class so they keep their old names.
  • Then make all references to CompareUtil in this plugin reference AbstractCompareUtil instead.

Copy link
Author

Choose a reason for hiding this comment

The 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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry. The "darn it" was on me not on you :)
This plugin has been around for quite a long time so it's really hard to tell what public methods can be changed and not, not just other plugins but whatever groovy scripts that admins has laying around etc. So we try to keep binary compatibility as much as possible and only make breaking changes when absolutely nessesary.

public boolean matches(String pattern, String str) {
return str.matches(pattern);
public boolean matches(String pattern, String str, EnvVars envVars) {
String expandedPattern = envVars.expand(pattern);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs null check on envVars

* @return true is the rules match.
*/
public boolean isInteresting(String project, String branch, String topic, List<String> files) {
if (compareType.matches(pattern, project)) {
public boolean isInteresting(String project, String branch, String topic, List<String> files, EnvVars envVars) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This is a public api and needs to keep backwards compatibility as much as possible.

Keep the old signature, deprecate it and have it call the new signature with null to the new parameter.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My old comment is still valid. Old method signatures needs to be kept and deprecated.

Copy link
Member

@rsandell rsandell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change breaks backwards binary compatibility

- now we synchronize access to the global EnvVars in order to be
  thread safe
- keep original public API and deprecate it
@rburgst
Copy link
Author

rburgst commented Mar 1, 2017

please let me know if the general direction of the patch is fine, then I will proceed and see about the build failures.

* @return true if the string matches the pattern.
*/
public boolean matches(String pattern, String str) {
Copy link
Member

Choose a reason for hiding this comment

The 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

/**
* Compares based on Ant-style paths.
* like <code>my/&#042;&#042;/something&#042;.git</code>
*/
static class AntCompareUtil implements CompareUtil {
class AntCompareUtil extends AbstractCompareUtil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static class

@@ -37,10 +40,20 @@
* @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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a @Deprecated annotation as well so tools has an easier time figuring it out.

// 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to do this before the \ to / replacement in case any of the used env vars contains platform specific paths.

* @return true is the rules match.
*/
public boolean isInteresting(String project, String branch, String topic, List<String> files) {
if (compareType.matches(pattern, project)) {
public boolean isInteresting(String project, String branch, String topic, List<String> files, EnvVars envVars) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My old comment is still valid. Old method signatures needs to be kept and deprecated.

@@ -178,6 +183,9 @@
private List<PluginGerritEvent> triggerOnEvents;
private boolean dynamicTriggerConfiguration;
private String triggerConfigURL;
private final EnvVars envVars;
Copy link
Member

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 ThreadLocal LoadingCache or something is better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants