It would be nice, in at least the 'build step' part of the parameterized-trigger plugin, to have the option to build conditionally based on SCM polling.

          [JENKINS-10147] Add 'poll SCM' option to build step

          G. Ann Campbell created issue -

          Andy Bigos added a comment -

          I'd like to see this feature also. There is short description of my use case here. Basically I'd like to be able to use the 'trigger build only if downstream job has SCM changes' functionality from the Downstream Ext plugin to be available when triggering downstream jobs with parameters.

          If possible I'd like to raise the priority of this request (rather than creating a duplicate with the higher priority) as it's quite important for our use case.

          Ta
          Andy

          Andy Bigos added a comment - I'd like to see this feature also. There is short description of my use case here . Basically I'd like to be able to use the 'trigger build only if downstream job has SCM changes' functionality from the Downstream Ext plugin to be available when triggering downstream jobs with parameters. If possible I'd like to raise the priority of this request (rather than creating a duplicate with the higher priority) as it's quite important for our use case. Ta Andy
          kutzi made changes -
          Link New: This issue is related to JENKINS-11455 [ JENKINS-11455 ]

          Thomas Fields added a comment -

          I'd also like to see this feature added. The parameterized-trigger is extremely useful for my setup but the fact it's lacking SCM polling really limits what I can do with it. If huybrechts is not able to fix this could it be assigned to someone else or give any pointers as to how I'd add the feature myself?

          Regards,
          Tom.

          Thomas Fields added a comment - I'd also like to see this feature added. The parameterized-trigger is extremely useful for my setup but the fact it's lacking SCM polling really limits what I can do with it. If huybrechts is not able to fix this could it be assigned to someone else or give any pointers as to how I'd add the feature myself? Regards, Tom.

          This message just to second the need of this option.

          Julien-Pierre Avérous added a comment - This message just to second the need of this option.

          I fixed the problem with a very-temporary hack in the code, waiting for an official patch.

          I have added this code :

          SCM scm = project.getScm();
          
          if (scm != null)
          {
          	// Check that we don't have change in SCM
          	PollingResult res = project.poll(LogTaskListener.NULL);
          
          	if (res == NO_CHANGES)
          	{
          		// Check that we have a sucessfull build
          		Run success = project.getLastSuccessfulBuild();
              					    
          		if (success != null)
          		{
          			listener.getLogger().println("Skipping " + HyperlinkNote.encodeTo('/'+ project.getUrl(), project.getFullDisplayName()) + ". No change happen since last build.");
          			continue;
          		}
          	}
          }
          

          just before

          futures.add(schedule(build, project, list));
          

          in 'perform' method of 'BuildTriggerConfig.java'

          and just before

          futures.put(project, schedule(build, project, list));
          

          in 'perform2' method of 'BuildTriggerConfig.java'

          This import should be added too in this file :

          import hudson.console.HyperlinkNote;
          import hudson.scm.SCM;
          import hudson.scm.PollingResult;
          import hudson.util.LogTaskListener;
          import hudson.model.Run;
          import static hudson.scm.PollingResult.*;
          

          This seem to work well for me.

          Caveats :

          • The line 'if (futures.isEmpty())' condition in TriggerBuilder.java print a bad log in the console when all project in the trigger list doesn't need to be rebuild. Not a problem, but not beautiful.
          • If the configuration of a project change but not the SCM, the build is not re-triggered.
          • Probably some others things.

          Julien-Pierre Avérous added a comment - I fixed the problem with a very-temporary hack in the code, waiting for an official patch. I have added this code : SCM scm = project.getScm(); if (scm != null ) { // Check that we don't have change in SCM PollingResult res = project.poll(LogTaskListener.NULL); if (res == NO_CHANGES) { // Check that we have a sucessfull build Run success = project.getLastSuccessfulBuild(); if (success != null ) { listener.getLogger().println( "Skipping " + HyperlinkNote.encodeTo( '/' + project.getUrl(), project.getFullDisplayName()) + ". No change happen since last build." ); continue ; } } } just before futures.add(schedule(build, project, list)); in 'perform' method of 'BuildTriggerConfig.java' and just before futures.put(project, schedule(build, project, list)); in 'perform2' method of 'BuildTriggerConfig.java' This import should be added too in this file : import hudson.console.HyperlinkNote; import hudson.scm.SCM; import hudson.scm.PollingResult; import hudson.util.LogTaskListener; import hudson.model.Run; import static hudson.scm.PollingResult.*; This seem to work well for me. Caveats : The line 'if (futures.isEmpty())' condition in TriggerBuilder.java print a bad log in the console when all project in the trigger list doesn't need to be rebuild. Not a problem, but not beautiful. If the configuration of a project change but not the SCM, the build is not re-triggered. Probably some others things.

          Caveats (2):

          • There is no option in the UI to activate / deactivate this hack.

          Julien-Pierre Avérous added a comment - Caveats (2): There is no option in the UI to activate / deactivate this hack.

          Here a git diff with a little bit cleaner implementation, with a check box in the UI to activate / deactivate this functionality.

          diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java
          index d955f4c..304337d 100644
          --- a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java
          +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java
          @@ -12,6 +12,11 @@ import hudson.model.Node;
           import hudson.model.Run;
           import org.kohsuke.stapler.DataBoundConstructor;
           
          +import hudson.scm.SCM;
          +import hudson.scm.PollingResult;
          +import hudson.util.LogTaskListener;
          +import static hudson.scm.PollingResult.*;
          +
           import com.google.common.collect.ArrayListMultimap;
           import com.google.common.collect.ListMultimap;
           
          @@ -27,22 +32,56 @@ import java.util.concurrent.Future;
            */
           public class BlockableBuildTriggerConfig extends BuildTriggerConfig {
               private final BlockingBehaviour block;
          +    private final boolean           buildScm;
          +    
               public boolean buildAllNodesWithLabel;
           
          -    public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, List<AbstractBuildParameters> configs) {
          +    public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, boolean buildScm, List<AbstractBuildParameters> configs) {
                   super(projects, ResultCondition.ALWAYS, false, configs);
                   this.block = block;
          +        this.buildScm = buildScm;
               }
           
               @DataBoundConstructor
          -    public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, List<AbstractBuildParameterFactory> configFactories,List<AbstractBuildParameters> configs) {
          +    public BlockableBuildTriggerConfig(String projects, BlockingBehaviour block, boolean buildScm, List<AbstractBuildParameterFactory> configFactories,List<AbstractBuildParameters> configs) {
                   super(projects, ResultCondition.ALWAYS, false, configFactories, configs);
                   this.block = block;
          +        this.buildScm = buildScm;
               }
           
               public BlockingBehaviour getBlock() {
                   return block;
               }
          +    
          +    public boolean getBuildScm() {
          +        return buildScm;
          +    }
          +    
          +    @Override
          +    public boolean needRebuild(AbstractProject project)
          +	{	   
          +        if (getBuildScm() == false)
          +            return true;	
          +	
          +        SCM scm = project.getScm();
          +
          +        if (scm != null)
          +        {
          +            // Check that we don't have change in SCM
          +            PollingResult res = project.poll(LogTaskListener.NULL);
          +
          +            if (res == NO_CHANGES)
          +            {
          +                // Check that we have a sucessfull build
          +                Run success = project.getLastSuccessfulBuild();
          +                
          +                if (success != null)
          +                    return false;
          +            }
          +        }
          +        
          +        return true;
          +	}
           
               @Override
               public List<Future<AbstractBuild>> perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
          diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java
          index d5144a7..c6f52be 100644
          --- a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java
          +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java
          @@ -31,6 +31,8 @@ import hudson.plugins.parameterizedtrigger.AbstractBuildParameters.DontTriggerEx
           import hudson.tasks.Messages;
           import hudson.util.FormValidation;
           
          +import hudson.console.HyperlinkNote;
          +
           import jenkins.model.Jenkins;
           import org.apache.commons.lang.StringUtils;
           import org.kohsuke.stapler.AncestorInPath;
          @@ -201,6 +203,11 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> {
           		}
           		return actions;
           	}
          +	
          +	public boolean needRebuild(AbstractProject project)
          +	{
          +        return true;
          +	}
           
           	/**
                * Note that with Hudson 1.341, trigger should be using
          @@ -222,7 +229,10 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> {
                               for (AbstractProject project : getProjectList(build.getProject().getParent(),env)) {
                                   List<Action> list = getBuildActions(actions, project);
           
          -                        futures.add(schedule(build, project, list));
          +                        if (needRebuild(project))
          +                            futures.add(schedule(build, project, list));
          +                        else
          +                            listener.getLogger().println("Skipping " + HyperlinkNote.encodeTo('/'+ project.getUrl(), project.getFullDisplayName()) + ". Don't need to rebuild.");
                               }
                           }
           
          @@ -247,7 +257,10 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> {
                               for (AbstractProject project : getProjectList(build.getProject().getParent(),env)) {
                                   List<Action> list = getBuildActions(actions, project);
                                   
          -                        futures.put(project, schedule(build, project, list));
          +                        if (needRebuild(project))
          +                            futures.put(project, schedule(build, project, list));
          +                        else
          +                            listener.getLogger().println("Skipping " + HyperlinkNote.encodeTo('/'+ project.getUrl(), project.getFullDisplayName()) + ". Don't need to rebuild.");
                               }
                           }
                           return futures;
          diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java
          index b5b4262..fb6b100 100644
          --- a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java
          +++ b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java
          @@ -99,7 +99,7 @@ public class TriggerBuilder extends Builder implements DependecyDeclarer {
                           if(!projectList.isEmpty()){
                               //handle non-blocking configs
                               if(futures.isEmpty()){
          -                        listener.getLogger().println("Triggering projects: " + getProjectListAsString(projectList));
          +                        listener.getLogger().println("Triggering or skipped projects: " + getProjectListAsString(projectList));
                                   continue;
                               }
                               //handle blocking configs
          diff --git a/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly b/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly
          index 1c49bbd..a279ef5 100644
          --- a/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly
          +++ b/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly
          @@ -22,9 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
           THE SOFTWARE.
           -->
           <j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
          +
             <f:entry title="${%Projects to build}" field="projects">
               <f:textbox />
             </f:entry>
          +  
          +  <f:block>
          +    <f:checkbox title="${%Build triggered projects only if there is SCM changes}" field="buildScm" checked="${instance.buildScm==true}" />
          +  </f:block>
          +
             <!-- TODO: replace with <f:optionalProperty> -->
             <f:optionalBlock field="block" title="${%Block until the triggered projects finish their builds}" checked="${instance.block!=null}">
               <j:set var="descriptor" value="${app.getDescriptorOrDie(descriptor.getPropertyType(field).clazz)}" />
          

          Julien-Pierre Avérous added a comment - Here a git diff with a little bit cleaner implementation, with a check box in the UI to activate / deactivate this functionality. diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java index d955f4c..304337d 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig.java @@ -12,6 +12,11 @@ import hudson.model.Node; import hudson.model.Run; import org.kohsuke.stapler.DataBoundConstructor; + import hudson.scm.SCM; + import hudson.scm.PollingResult; + import hudson.util.LogTaskListener; + import static hudson.scm.PollingResult.*; + import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ListMultimap; @@ -27,22 +32,56 @@ import java.util.concurrent.Future; */ public class BlockableBuildTriggerConfig extends BuildTriggerConfig { private final BlockingBehaviour block; + private final boolean buildScm; + public boolean buildAllNodesWithLabel; - public BlockableBuildTriggerConfig( String projects, BlockingBehaviour block, List<AbstractBuildParameters> configs) { + public BlockableBuildTriggerConfig( String projects, BlockingBehaviour block, boolean buildScm, List<AbstractBuildParameters> configs) { super (projects, ResultCondition.ALWAYS, false , configs); this .block = block; + this .buildScm = buildScm; } @DataBoundConstructor - public BlockableBuildTriggerConfig( String projects, BlockingBehaviour block, List<AbstractBuildParameterFactory> configFactories,List<AbstractBuildParameters> configs) { + public BlockableBuildTriggerConfig( String projects, BlockingBehaviour block, boolean buildScm, List<AbstractBuildParameterFactory> configFactories,List<AbstractBuildParameters> configs) { super (projects, ResultCondition.ALWAYS, false , configFactories, configs); this .block = block; + this .buildScm = buildScm; } public BlockingBehaviour getBlock() { return block; } + + public boolean getBuildScm() { + return buildScm; + } + + @Override + public boolean needRebuild(AbstractProject project) + { + if (getBuildScm() == false ) + return true ; + + SCM scm = project.getScm(); + + if (scm != null ) + { + // Check that we don't have change in SCM + PollingResult res = project.poll(LogTaskListener.NULL); + + if (res == NO_CHANGES) + { + // Check that we have a sucessfull build + Run success = project.getLastSuccessfulBuild(); + + if (success != null ) + return false ; + } + } + + return true ; + } @Override public List<Future<AbstractBuild>> perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java index d5144a7..c6f52be 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/BuildTriggerConfig.java @@ -31,6 +31,8 @@ import hudson.plugins.parameterizedtrigger.AbstractBuildParameters.DontTriggerEx import hudson.tasks.Messages; import hudson.util.FormValidation; + import hudson.console.HyperlinkNote; + import jenkins.model.Jenkins; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.AncestorInPath; @@ -201,6 +203,11 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> { } return actions; } + + public boolean needRebuild(AbstractProject project) + { + return true ; + } /** * Note that with Hudson 1.341, trigger should be using @@ -222,7 +229,10 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> { for (AbstractProject project : getProjectList(build.getProject().getParent(),env)) { List<Action> list = getBuildActions(actions, project); - futures.add(schedule(build, project, list)); + if (needRebuild(project)) + futures.add(schedule(build, project, list)); + else + listener.getLogger().println( "Skipping " + HyperlinkNote.encodeTo( '/' + project.getUrl(), project.getFullDisplayName()) + ". Don't need to rebuild." ); } } @@ -247,7 +257,10 @@ public class BuildTriggerConfig implements Describable<BuildTriggerConfig> { for (AbstractProject project : getProjectList(build.getProject().getParent(),env)) { List<Action> list = getBuildActions(actions, project); - futures.put(project, schedule(build, project, list)); + if (needRebuild(project)) + futures.put(project, schedule(build, project, list)); + else + listener.getLogger().println( "Skipping " + HyperlinkNote.encodeTo( '/' + project.getUrl(), project.getFullDisplayName()) + ". Don't need to rebuild." ); } } return futures; diff --git a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java index b5b4262..fb6b100 100644 --- a/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java +++ b/src/main/java/hudson/plugins/parameterizedtrigger/TriggerBuilder.java @@ -99,7 +99,7 @@ public class TriggerBuilder extends Builder implements DependecyDeclarer { if (!projectList.isEmpty()){ //handle non-blocking configs if (futures.isEmpty()){ - listener.getLogger().println( "Triggering projects: " + getProjectListAsString(projectList)); + listener.getLogger().println( "Triggering or skipped projects: " + getProjectListAsString(projectList)); continue ; } //handle blocking configs diff --git a/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly b/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly index 1c49bbd..a279ef5 100644 --- a/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly +++ b/src/main/resources/hudson/plugins/parameterizedtrigger/BlockableBuildTriggerConfig/config.jelly @@ -22,9 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> <j:jelly xmlns:j= "jelly:core" xmlns:st= "jelly:stapler" xmlns:d= "jelly:define" xmlns:l= "/lib/layout" xmlns:t= "/lib/hudson" xmlns:f= "/lib/form" > + <f:entry title= "${%Projects to build}" field= "projects" > <f:textbox /> </f:entry> + + <f:block> + <f:checkbox title= "${%Build triggered projects only if there is SCM changes}" field= "buildScm" checked= "${instance.buildScm== true }" /> + </f:block> + <!-- TODO: replace with <f:optionalProperty> --> <f:optionalBlock field= "block" title= "${%Block until the triggered projects finish their builds}" checked= "${instance.block!= null }" > <j:set var = "descriptor" value= "${app.getDescriptorOrDie(descriptor.getPropertyType(field).clazz)}" />

          Atef GHOULEM added a comment -

          Hello,
          Does this bug is planned for a next version?

          Atef GHOULEM added a comment - Hello, Does this bug is planned for a next version?

          Thomas Fields added a comment -

          Hi,

          This bug is assigned to huybrechts yet that user seems inactive in the Jenkins community. Can the issue be reassigned and the above patch integrated into the next release?

          Tom

          Thomas Fields added a comment - Hi, This bug is assigned to huybrechts yet that user seems inactive in the Jenkins community. Can the issue be reassigned and the above patch integrated into the next release? Tom

            cjo9900 cjo9900
            ganncamp G. Ann Campbell
            Votes:
            10 Vote for this issue
            Watchers:
            14 Start watching this issue

              Created:
              Updated: