Skip to content

Commit

Permalink
[JENKINS-44721] Trigger downstream pipelines depending on the generat…
Browse files Browse the repository at this point in the history
…ed artifacts
  • Loading branch information
Cyrille Le Clerc committed Jun 28, 2017
1 parent 5753544 commit 5889de3
Show file tree
Hide file tree
Showing 11 changed files with 275 additions and 65 deletions.
70 changes: 49 additions & 21 deletions jenkins-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
</developers>

<properties>
<jenkins.version>2.7.4</jenkins.version>
<jenkins.version>2.46.3</jenkins.version>
<scm-api-plugin.version>2.1.1</scm-api-plugin.version>
<git-plugin.version>3.3.0</git-plugin.version>
</properties>
Expand All @@ -91,13 +91,13 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.9</version>
<version>2.11</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-multibranch</artifactId>
<version>2.9</version>
<version>2.14</version>
<optional>true</optional>
</dependency>
<dependency>
Expand All @@ -120,12 +120,22 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-api</artifactId>
<version>2.10</version>
<version>2.13</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>config-file-provider</artifactId>
<version>2.15.7</version>
<version>2.16.0</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>credentials</artifactId>
<version>2.1.13</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>cloudbees-folder</artifactId>
<version>6.0.4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
Expand Down Expand Up @@ -169,22 +179,16 @@
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>cloudbees-folder</artifactId>
<version>5.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.23</version>
<version>2.30</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.5</version>
<version>2.11</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -196,14 +200,14 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>2.11</version>
<version>2.14</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.5</version>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
Expand Down Expand Up @@ -235,12 +239,7 @@
<version>2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
<version>${scm-api-plugin.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
Expand Down Expand Up @@ -268,6 +267,35 @@
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
<version>2.14</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>mailer</artifactId>
<version>1.20</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>script-security</artifactId>
<version>1.26</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>scm-api</artifactId>
<version>${scm-api-plugin.version}</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>ssh-credentials</artifactId>
<version>1.13</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public PipelineMavenPluginH2Dao(File rootDir) {
rootDir.getClass(); // check non null

File databaseFile = new File(rootDir, "jenkins-jobs");
String jdbcUrl = "jdbc:h2:file:" + databaseFile.getAbsolutePath() + ";AUTO_SERVER=TRUE";
String jdbcUrl = "jdbc:h2:file:" + databaseFile.getAbsolutePath() + ";AUTO_SERVER=TRUE;MULTI_THREADED=1";
jdbcConnectionPool = JdbcConnectionPool.create(jdbcUrl, "sa", "sa");
LOGGER.log(Level.FINE, "Open database {0}", jdbcUrl);

Expand Down Expand Up @@ -384,7 +384,8 @@ public List<String> listDownstreamJobs(@Nonnull String jobFullName, int buildNum
" INNER JOIN JENKINS_BUILD AS DOWNSTREAM_BUILD ON DOWNSTREAM_JOB.ID = DOWNSTREAM_BUILD.JOB_ID " +
" INNER JOIN MAVEN_DEPENDENCY ON DOWNSTREAM_BUILD.ID = MAVEN_DEPENDENCY.BUILD_ID" +
" WHERE " +
" MAVEN_DEPENDENCY.ARTIFACT_ID IN (" + generatedArtifactsSql + ") " +
" MAVEN_DEPENDENCY.ARTIFACT_ID IN (" + generatedArtifactsSql + ") AND " +
" DOWNSTREAM_BUILD.NUMBER in (SELECT MAX(JENKINS_BUILD.NUMBER) FROM JENKINS_BUILD WHERE DOWNSTREAM_JOB.ID = JENKINS_BUILD.JOB_ID)" +
" ORDER BY DOWNSTREAM_JOB.FULL_NAME";

List<String> downstreamJobsFullNames = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
import java.util.logging.Logger;

/**
* Maintains the database in sync with the jobs and builds.
*
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
@Extension
public class PipelineMavenPluginItemListener extends ItemListener {
private final static Logger LOGGER = Logger.getLogger(PipelineMavenPluginItemListener.class.getName());
public class DatabaseSyncItemListener extends ItemListener {
private final static Logger LOGGER = Logger.getLogger(DatabaseSyncItemListener.class.getName());

@Override
public void onDeleted(Item item) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.jenkinsci.plugins.pipeline.maven.listeners;

import hudson.Extension;
import hudson.model.listeners.RunListener;
import org.jenkinsci.plugins.pipeline.maven.GlobalPipelineMavenConfig;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;

/**
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
@Extension
public class DatabaseSyncRunListener extends RunListener<WorkflowRun> {

@Override
public void onDeleted(WorkflowRun run) {
GlobalPipelineMavenConfig.getDao().deleteBuild(run.getParent().getFullName(), run.getNumber());
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
package org.jenkinsci.plugins.pipeline.maven.listeners;

import com.cloudbees.hudson.plugins.folder.computed.ComputedFolder;
import hudson.Extension;
import hudson.console.ModelHyperlinkNote;
import hudson.model.Action;
import hudson.model.Cause;
import hudson.model.CauseAction;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Queue;
import hudson.model.TaskListener;
import hudson.model.listeners.RunListener;
import hudson.model.queue.QueueTaskFuture;
import hudson.model.queue.Tasks;
import hudson.security.ACL;
import hudson.triggers.Trigger;
import hudson.triggers.TriggerDescriptor;
import jenkins.branch.MultiBranchProject;
import jenkins.model.Jenkins;
import jenkins.model.ParameterizedJobMixIn;
import jenkins.security.QueueItemAuthenticatorConfiguration;
Expand All @@ -27,8 +25,8 @@
import org.jenkinsci.plugins.pipeline.maven.trigger.WorkflowJobDependencyTrigger;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
Expand All @@ -38,19 +36,23 @@
import javax.annotation.Nullable;

/**
* Trigger downstream pipelines.
*
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
@Extension
public class PipelineMavenPluginRunListener extends RunListener<WorkflowRun> {
public class DownstreamPipelineTriggerRunListener extends RunListener<WorkflowRun> {

private final static Logger LOGGER = Logger.getLogger(PipelineMavenPluginRunListener.class.getName());
private final static Logger LOGGER = Logger.getLogger(DownstreamPipelineTriggerRunListener.class.getName());

@Override
public void onCompleted(WorkflowRun upstreamBuild, @Nonnull TaskListener listener) {
LOGGER.log(Level.FINE, "onCompleted({0})", new Object[]{upstreamBuild});

if (!GlobalPipelineMavenConfig.getTriggerDownstreamBuildsCriteria().contains(upstreamBuild.getResult())) {
LOGGER.log(Level.FINE, "Ignore non successful build {0}", upstreamBuild);
LOGGER.log(Level.FINE, "Skip downstream job triggering for upstream build with ignored result status {0}: {1}",
new Object[]{upstreamBuild, upstreamBuild.getResult()});
return;
}

WorkflowJob upstreamPipeline = upstreamBuild.getParent();
Expand All @@ -69,13 +71,13 @@ public void onCompleted(WorkflowRun upstreamBuild, @Nonnull TaskListener listene
}

if (isParameterizedPipeline(downstreamPipeline)) {
LOGGER.log(Level.FINE, "Don't trigger parameterized job {0} from upstream build (1}", new Object[]{downstreamPipeline, upstreamBuild});
LOGGER.log(Level.FINE, "Skip triggering of parameterized downstream pipeline {0} from upstream build (1}", new Object[]{downstreamPipeline, upstreamBuild});
continue;
}

WorkflowJobDependencyTrigger downstreamPipelineTrigger = getWorkflowJobDependencyTrigger(downstreamPipeline);
if (downstreamPipelineTrigger == null) {
LOGGER.log(Level.FINE, "Skip triggering of downstream pipeline {0} linked to upstream build {1}: dependency trigger not configured", new Object[]{downstreamPipeline, upstreamBuild});
LOGGER.log(Level.FINE, "Skip triggering of downstream pipeline {0} from upstream build {1}: dependency trigger not configured", new Object[]{downstreamPipeline, upstreamBuild});
continue;
}

Expand All @@ -86,9 +88,8 @@ public void onCompleted(WorkflowRun upstreamBuild, @Nonnull TaskListener listene
// downstream job not visible from upstream job, don't display message
}

// FIXME trigger downstream build
// see https://github.com/jenkinsci/pipeline-build-step-plugin/blob/master/src/main/java/org/jenkinsci/plugins/workflow/support/steps/build/BuildTriggerStepExecution.java#L60

// FIXME don't display upstream pipeline as the cause if permissions don't match
downstreamPipeline.scheduleBuild(new Cause.UpstreamCause(upstreamBuild));
}

Expand All @@ -112,6 +113,28 @@ protected WorkflowJobDependencyTrigger getWorkflowJobDependencyTrigger(@Nonnull
return (WorkflowJobDependencyTrigger) trigger;
}
}

if (parameterizedJob.getParent() instanceof WorkflowMultiBranchProject) {
// search for the triggers of MultiBranch pipelines
WorkflowMultiBranchProject multiBranchProject = (WorkflowMultiBranchProject) parameterizedJob.getParent();
for (Trigger trigger : multiBranchProject.getTriggers().values()) {
if (trigger instanceof WorkflowJobDependencyTrigger) {
return (WorkflowJobDependencyTrigger) trigger;
}
}

if (multiBranchProject.getParent() instanceof ComputedFolder) {
// search for the triggers of GitHubOrg folders / Bitbucket folders
ComputedFolder grandParent = (ComputedFolder) multiBranchProject.getParent();
Map<TriggerDescriptor,Trigger<?>> grandParentTriggers = grandParent.getTriggers();
for(Trigger trigger : grandParentTriggers.values()){
if (trigger instanceof WorkflowJobDependencyTrigger) {
return (WorkflowJobDependencyTrigger) trigger;
}
}
}

}
return null;
}

Expand Down Expand Up @@ -148,8 +171,4 @@ protected boolean isDownstreamPipelineVisibleByUpstreamPipeline(@Nonnull Workflo
}
}

@Override
public void onDeleted(WorkflowRun run) {
GlobalPipelineMavenConfig.getDao().deleteBuild(run.getParent().getFullName(), run.getNumber());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
import hudson.Extension;
import hudson.model.Cause;
import hudson.model.Item;
import hudson.model.Job;
import hudson.triggers.Trigger;
import hudson.triggers.TriggerDescriptor;
import jenkins.branch.MultiBranchProject;
import jenkins.branch.OrganizationFolder;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* @author <a href="mailto:cleclerc@cloudbees.com">Cyrille Le Clerc</a>
*/
public class WorkflowJobDependencyTrigger extends Trigger<WorkflowJob> {
public class WorkflowJobDependencyTrigger extends Trigger<Job<?, ?>> {

@DataBoundConstructor
public WorkflowJobDependencyTrigger(){
Expand All @@ -22,11 +25,11 @@ public WorkflowJobDependencyTrigger(){
public static class DescriptorImpl extends TriggerDescriptor {
@Override
public boolean isApplicable(Item item) {
return item instanceof WorkflowJob;
return item instanceof WorkflowJob || item instanceof MultiBranchProject || item instanceof OrganizationFolder;
}

public String getDisplayName() {
return "Pipeline Dependency Trigger";
return "Build whenever a SNAPSHOT dependency is built";
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<div>
Trigger the build of this pipeline when a Maven SNAPSHOT dependency is being built by this Jenkins instance.

Jenkins discovers all the dependencies of the Maven builds of this pipeline invoked in a <code>withMaven(){...}</code> wrapping step and
will trigger the build if one of these dependencies is being built (typically a SNAPSHOT version).

This is convenient for automatically performing continuous integration. Jenkins will check the snapshot dependencies from the <code>&lt;dependency&gt;</code> element in the POM.

</div>
9 changes: 9 additions & 0 deletions jenkins-plugin/src/main/resources/sql/h2/02_migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// support maven artifact types such as "_maven_plugin"
ALTER TABLE MAVEN_ARTIFACT ALTER COLUMN TYPE varchar(64);

UPDATE VERSION SET VERSION = 2;





Loading

0 comments on commit 5889de3

Please sign in to comment.