Skip to content

Commit

Permalink
Merge pull request #17 from jimmidyson/run-policy
Browse files Browse the repository at this point in the history
Support build run policies
  • Loading branch information
jimmidyson authored Nov 10, 2016
2 parents b30ee76 + 7004ba6 commit d5026df
Show file tree
Hide file tree
Showing 10 changed files with 228 additions and 101 deletions.
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-scm-step</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-support</artifactId>
Expand Down Expand Up @@ -237,6 +244,9 @@
<io.fabric8>ALL</io.fabric8>
<okhttp3>ALL</okhttp3>
</loggers>
<webApp>
<contextPath>/</contextPath>
</webApp>
</configuration>
</plugin>
<plugin>
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/io/fabric8/jenkins/openshiftsync/BuildCause.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,19 @@ public class BuildCause extends Cause {

private String commit;

public BuildCause(String uid, String namespace, String name, String gitUri, String commit) {
private String buildConfigUid;

public BuildCause(String uid, String namespace, String name, String gitUri, String commit, String buildConfigUid) {
this.uid = uid;
this.namespace = namespace;
this.name = name;
this.gitUri = gitUri;
this.commit = commit;
this.buildConfigUid = buildConfigUid;
}

public BuildCause(Build build) {
public BuildCause(Build build, String buildConfigUid) {
this.buildConfigUid = buildConfigUid;
if (build == null || build.getMetadata() == null) {
return;
}
Expand Down Expand Up @@ -96,4 +100,8 @@ public String getGitUri() {
public String getCommit() {
return commit;
}

public String getBuildConfigUid() {
return buildConfigUid;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import io.fabric8.openshift.api.model.BuildConfig;
import jenkins.model.ParameterizedJobMixIn;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.kohsuke.stapler.DataBoundConstructor;

import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.getOpenShiftClient;
Expand All @@ -31,6 +31,8 @@
* - Namespace
* - Build config name
* - Build config uid
* - Build config resource version
* - Build config run policy
*/
public class BuildConfigProjectProperty extends JobProperty<Job<?, ?>> {

Expand All @@ -43,15 +45,15 @@ public class BuildConfigProjectProperty extends JobProperty<Job<?, ?>> {

private String resourceVersion;

private String contextDir;
private String buildRunPolicy;

@DataBoundConstructor
public BuildConfigProjectProperty(String namespace, String name, String uid, String resourceVersion, String contextDir) {
public BuildConfigProjectProperty(String namespace, String name, String uid, String resourceVersion, String buildRunPolicy) {
this.namespace = namespace;
this.name = name;
this.uid = uid;
this.resourceVersion = resourceVersion;
this.contextDir = contextDir;
this.buildRunPolicy = buildRunPolicy;
}

public BuildConfigProjectProperty(BuildConfig bc) {
Expand All @@ -60,12 +62,7 @@ public BuildConfigProjectProperty(BuildConfig bc) {
bc.getMetadata().getName(),
bc.getMetadata().getUid(),
bc.getMetadata().getResourceVersion(),
bc.getSpec().getSource().getContextDir()
);
}

public String getUid() {
return uid;
bc.getSpec().getRunPolicy());
}

public BuildConfig getBuildConfig() {
Expand All @@ -76,14 +73,30 @@ public BuildConfig getBuildConfig() {
return null;
}

public String getUid() {
return uid;
}

public void setUid(String uid) {
this.uid = uid;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getNamespace() {
return namespace;
}

public void setNamespace(String namespace) {
this.namespace = namespace;
}

public String getResourceVersion() {
return resourceVersion;
}
Expand All @@ -92,14 +105,18 @@ public void setResourceVersion(String resourceVersion) {
this.resourceVersion = resourceVersion;
}

public String getContextDir() {
return contextDir;
public String getBuildRunPolicy() {
return buildRunPolicy;
}

public void setBuildRunPolicy(String buildRunPolicy) {
this.buildRunPolicy = buildRunPolicy;
}

@Extension
public static final class DescriptorImpl extends JobPropertyDescriptor {
public boolean isApplicable(Class<? extends Job> jobType) {
return ParameterizedJobMixIn.ParameterizedJob.class.isAssignableFrom(jobType);
return WorkflowJob.class.isAssignableFrom(jobType);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import org.apache.tools.ant.filters.StringInputStream;
import org.jenkinsci.plugins.workflow.flow.FlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jvnet.hudson.reactor.ReactorException;

import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
Expand All @@ -44,6 +43,8 @@
import java.util.logging.Logger;

import static io.fabric8.jenkins.openshiftsync.BuildConfigToJobMapper.mapBuildConfigToFlow;
import static io.fabric8.jenkins.openshiftsync.BuildRunPolicy.SERIAL;
import static io.fabric8.jenkins.openshiftsync.BuildRunPolicy.SERIAL_LATEST_ONLY;
import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.getOpenShiftClient;
import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.isJenkinsBuildConfig;
import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.parseResourceVersion;
Expand Down Expand Up @@ -81,20 +82,18 @@ public void start(final Callable<Void> completionCallback) {
public void doRun() {
logger.info("Waiting for Jenkins to be started");
while (true) {
Jenkins jenkins = Jenkins.getInstance();
if (jenkins != null) {
Computer[] computers = jenkins.getComputers();
boolean ready = false;
for (Computer c : computers) {
// Jenkins.isAcceptingTasks() results in hudson.model.Node.isAcceptingTasks() getting called, and that always returns true;
// the Computer.isAcceptingTasks actually introspects various Jenkins data structures to determine readiness
if (c.isAcceptingTasks()) {
ready = true;
break;
}
}
if (ready)
break;
Computer[] computers = Jenkins.getActiveInstance().getComputers();
boolean ready = false;
for (Computer c : computers) {
// Jenkins.isAcceptingTasks() results in hudson.model.Node.isAcceptingTasks() getting called, and that always returns true;
// the Computer.isAcceptingTasks actually introspects various Jenkins data structures to determine readiness
if (c.isAcceptingTasks()) {
ready = true;
break;
}
}
if (ready) {
break;
}
try {
Thread.sleep(500);
Expand Down Expand Up @@ -181,19 +180,14 @@ public Void call() throws Exception {
WorkflowJob job = BuildTrigger.getDscp().getJobFromBuildConfigUid(buildConfig.getMetadata().getUid());
boolean newJob = job == null;
if (newJob) {
job = new WorkflowJob(Jenkins.getInstance(), jobName);
job = new WorkflowJob(Jenkins.getActiveInstance(), jobName);
}

FlowDefinition flowFromBuildConfig = mapBuildConfigToFlow(buildConfig);
if (flowFromBuildConfig == null) {
return null;
}

String contextDir = null;
if (buildConfig.getSpec() != null && buildConfig.getSpec().getSource() != null) {
contextDir = buildConfig.getSpec().getSource().getContextDir();
}

job.setDefinition(flowFromBuildConfig);

BuildTrigger trigger = new BuildTrigger();
Expand All @@ -205,28 +199,35 @@ public Void call() throws Exception {
if (buildConfigProjectProperty != null) {
long updatedBCResourceVersion = parseResourceVersion(buildConfig);
long oldBCResourceVersion = parseResourceVersion(buildConfigProjectProperty.getResourceVersion());
if (oldBCResourceVersion > updatedBCResourceVersion) {
BuildConfigProjectProperty newProperty = new BuildConfigProjectProperty(buildConfig);
if (updatedBCResourceVersion <= oldBCResourceVersion &&
newProperty.getUid().equals(buildConfigProjectProperty.getUid()) &&
newProperty.getNamespace().equals(buildConfigProjectProperty.getNamespace()) &&
newProperty.getName().equals(buildConfigProjectProperty.getName()) &&
newProperty.getBuildRunPolicy().equals(buildConfigProjectProperty.getBuildRunPolicy())
) {
return null;
}
buildConfigProjectProperty.setResourceVersion(buildConfig.getMetadata().getResourceVersion());
buildConfigProjectProperty.setUid(newProperty.getUid());
buildConfigProjectProperty.setNamespace(newProperty.getNamespace());
buildConfigProjectProperty.setName(newProperty.getName());
buildConfigProjectProperty.setResourceVersion(newProperty.getResourceVersion());
buildConfigProjectProperty.setBuildRunPolicy(newProperty.getBuildRunPolicy());
} else {
job.addProperty(
new BuildConfigProjectProperty(
buildConfig.getMetadata().getNamespace(),
buildConfig.getMetadata().getName(),
buildConfig.getMetadata().getUid(),
buildConfig.getMetadata().getResourceVersion(),
contextDir
)
new BuildConfigProjectProperty(buildConfig)
);
}

InputStream jobStream = new StringInputStream(new XStream2().toXML(job));
job.setConcurrentBuild(
!(buildConfig.getSpec().getRunPolicy().equals(SERIAL) ||
buildConfig.getSpec().getRunPolicy().equals(SERIAL_LATEST_ONLY))
);

Jenkins jenkins = Jenkins.getInstance();
InputStream jobStream = new StringInputStream(new XStream2().toXML(job));

if (newJob) {
jenkins.createProjectFromXML(
Jenkins.getActiveInstance().createProjectFromXML(
jobName,
jobStream
).save();
Expand Down Expand Up @@ -260,14 +261,7 @@ private void deleteJob(final BuildConfig buildConfig) throws Exception {
@Override
public Void call() throws Exception {
job.delete();
try {
Jenkins jenkins = Jenkins.getInstance();
if (jenkins != null) {
jenkins.reload();
}
} catch (ReactorException e) {
logger.log(Level.SEVERE, "Failed to reload jenkins job after deleting " + job.getName() + " from BuildConfig " + NamespaceName.create(buildConfig));
}
Jenkins.getActiveInstance().rebuildDependencyGraphAsync();
return null;
}
});
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/io/fabric8/jenkins/openshiftsync/BuildRunPolicy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.fabric8.jenkins.openshiftsync;

public class BuildRunPolicy {

public static final String PARALLEL = "Parallel";

public static final String SERIAL = "Serial";

public static final String SERIAL_LATEST_ONLY = "SerialLatestOnly";

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@
import hudson.triggers.SafeTimerTask;
import io.fabric8.openshift.api.model.Build;
import jenkins.util.Timer;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.kohsuke.stapler.DataBoundConstructor;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.TimeUnit;
Expand All @@ -44,6 +48,7 @@
import static io.fabric8.jenkins.openshiftsync.Constants.ANNOTATION_JENKINS_BUILD_URI;
import static io.fabric8.jenkins.openshiftsync.Constants.ANNOTATION_JENKINS_LOG_URL;
import static io.fabric8.jenkins.openshiftsync.Constants.ANNOTATION_JENKINS_STATUS_JSON;
import static io.fabric8.jenkins.openshiftsync.NewBuildWatcher.buildAdded;
import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.formatTimestamp;
import static io.fabric8.jenkins.openshiftsync.OpenShiftUtils.getOpenShiftClient;

Expand Down Expand Up @@ -142,6 +147,7 @@ public synchronized void onCompleted(Run run, @Nonnull TaskListener listener) {
runsToPoll.remove(run);
pollRun(run);
logger.info("onCompleted " + run.getUrl());
maybeScheduleNext(((WorkflowRun) run).getParent());
}
super.onCompleted(run, listener);
}
Expand All @@ -152,6 +158,7 @@ public synchronized void onDeleted(Run run) {
runsToPoll.remove(run);
pollRun(run);
logger.info("onDeleted " + run.getUrl());
maybeScheduleNext(((WorkflowRun) run).getParent());
}
super.onDeleted(run);
}
Expand Down Expand Up @@ -295,4 +302,30 @@ private String runToBuildPhase(Run run) {
protected boolean shouldPollRun(Run run) {
return run instanceof WorkflowRun && run.getCause(BuildCause.class) != null;
}

private void maybeScheduleNext(WorkflowJob job) {
BuildConfigProjectProperty bcp = job.getProperty(BuildConfigProjectProperty.class);
if (bcp == null) {
return;
}
List<Build> builds = getOpenShiftClient().builds().inNamespace(bcp.getNamespace())
.withField("status", BuildPhases.NEW).withLabel("openshift.io/build-config.name", bcp.getName()).list().getItems();
Collections.sort(builds, new Comparator<Build>() {
@Override
public int compare(Build b1, Build b2) {
return Long.compare(
Long.parseLong(b1.getMetadata().getAnnotations().get("openshift.io/build.number")),
Long.parseLong(b2.getMetadata().getAnnotations().get("openshift.io/build.number"))
);
}
});

for (Build b : builds) {
try {
buildAdded(b);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Loading

0 comments on commit d5026df

Please sign in to comment.