Skip to content

Commit

Permalink
[JENKINS-14494] Supports MatrixAggregator.
Browse files Browse the repository at this point in the history
  • Loading branch information
ikedam committed Aug 21, 2013
1 parent b1f7464 commit 3fbb375
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 5 deletions.
@@ -0,0 +1,80 @@
/*
* The MIT License
*
* Copyright (c) 2013 IKEDA Yasuyuki
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jenkins_ci.plugins.flexible_publish;

import java.io.IOException;

import hudson.Launcher;
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixRun;
import hudson.model.BuildListener;
import hudson.tasks.Publisher;

/**
* Wraps {@link MatrixAggregator} for the wrapped {@link Publisher}.
* Evaluates the condition, and call wrapped {@link MatrixAggregator} if satisfied.
*/
public class ConditionalMatrixAggregator extends MatrixAggregator {
private ConditionalPublisher conditionalPublisher;
private MatrixAggregator baseAggregator;

protected ConditionalMatrixAggregator(MatrixBuild build, Launcher launcher,
BuildListener listener, ConditionalPublisher conditionalPublisher,
MatrixAggregator baseAggregator) {
super(build, launcher, listener);
this.conditionalPublisher = conditionalPublisher;
this.baseAggregator = baseAggregator;
}

@Override
public boolean startBuild() throws InterruptedException, IOException {
return baseAggregator.startBuild();
}

@Override
public boolean endRun(MatrixRun run)
throws InterruptedException, IOException {
MarkPerformedBuilder mpb = new MarkPerformedBuilder();
boolean isSuccess = conditionalPublisher.getRunner().perform(
conditionalPublisher.getCondition(),
mpb,
run, // watch out! not parent build.
launcher,
listener
);

if(!isSuccess || !mpb.isPerformed()) {
return true;
}

return baseAggregator.endRun(run);
}

@Override
public boolean endBuild() throws InterruptedException, IOException {
return baseAggregator.endBuild();
}
}
Expand Up @@ -27,6 +27,7 @@
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.Launcher;
import hudson.matrix.MatrixProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
Expand All @@ -40,6 +41,7 @@
import org.jenkins_ci.plugins.run_condition.RunCondition;
import org.jenkins_ci.plugins.run_condition.core.AlwaysRun;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.Stapler;

import java.io.IOException;
import java.util.Collection;
Expand All @@ -51,12 +53,25 @@ public class ConditionalPublisher implements Describable<ConditionalPublisher> {
private final RunCondition condition;
private final BuildStep publisher;
private BuildStepRunner runner;

// used for multiconfiguration projects with MatrixAggregatable.
// if null, used condition and publlisher.
private final RunCondition aggregationCondition;
private final BuildStepRunner aggregationRunner;

@DataBoundConstructor
public ConditionalPublisher(final RunCondition condition, final BuildStep publisher, final BuildStepRunner runner) {
public ConditionalPublisher(final RunCondition condition, final BuildStep publisher, final BuildStepRunner runner,
boolean configuredAggregation, final RunCondition aggregationCondition, final BuildStepRunner aggregationRunner) {
this.condition = condition;
this.publisher = publisher;
this.runner = runner;
if (configuredAggregation) {
this.aggregationCondition = aggregationCondition;
this.aggregationRunner = aggregationRunner;
} else {
this.aggregationCondition = null;
this.aggregationRunner = null;
}
}

public RunCondition getCondition() {
Expand All @@ -71,6 +86,18 @@ public BuildStepRunner getRunner() {
return runner;
}

public RunCondition getAggregationCondition() {
return aggregationCondition;
}

public BuildStepRunner getAggregationRunner() {
return aggregationRunner;
}

public boolean isConfiguredAggregation() {
return getAggregationCondition() != null;
}

public ConditionalPublisherDescriptor getDescriptor() {
return Hudson.getInstance().getDescriptorByType(ConditionalPublisherDescriptor.class);
}
Expand Down Expand Up @@ -129,6 +156,11 @@ public Descriptor<? extends BuildStep> getDefaultPublisher() {
return Hudson.getInstance().getDescriptorByType(ArtifactArchiver.DescriptorImpl.class);
}

public boolean isMatrixProject() {
// Determine the configuring project from the request url.
AbstractProject<?,?> project = Stapler.getCurrentRequest().findAncestorObject(AbstractProject.class);
return (project instanceof MatrixProject);
}
}

}
@@ -0,0 +1,106 @@
/*
* The MIT License
*
* Copyright (c) 2013 IKEDA Yasuyuki
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jenkins_ci.plugins.flexible_publish;

import java.io.IOException;
import java.util.List;

import hudson.Launcher;
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixRun;
import hudson.model.BuildListener;

/**
* {@link MatrixAggregator} for {@link FlexiblePublisher}.
*
* Just calls {@link ConditionalMatrixAggregator} for each {@link ConditionalPublisher}s.
*/
public class FlexibleMatrixAggregator extends MatrixAggregator {
private List<ConditionalMatrixAggregator> aggregatorList;

protected FlexibleMatrixAggregator(MatrixBuild build,
Launcher launcher, BuildListener listener,
List<ConditionalMatrixAggregator> aggregatorList) {
super(build, launcher, listener);
this.aggregatorList = aggregatorList;
}

/**
* Called when the parent build is started.
*
* @return false to abort the build.s
* @throws InterruptedException
* @throws IOException
*/
@Override
public boolean startBuild() throws InterruptedException, IOException {
for (ConditionalMatrixAggregator cma: aggregatorList) {
if (!cma.startBuild()) {
return false;
}
}
return true;
}

/**
* Called when a build with an axe combination is finished.
*
* @param run
* @return false to abort the build.s
* @throws InterruptedException
* @throws IOException
* @see hudson.matrix.MatrixAggregator#endRun(hudson.matrix.MatrixRun)
*/
@Override
public boolean endRun(MatrixRun run) throws InterruptedException,
IOException
{
for (ConditionalMatrixAggregator cma: aggregatorList) {
if (!cma.endRun(run)) {
return false;
}
}
return true;
}

/**
* Called when the parent build is finished.
*
* @return false to abort the build.
* @throws InterruptedException
* @throws IOException
* @see hudson.matrix.MatrixAggregator#endBuild()
*/
@Override
public boolean endBuild() throws InterruptedException, IOException {
for (ConditionalMatrixAggregator cma: aggregatorList) {
if (!cma.endBuild()) {
return false;
}
}
return true;
}
}
Expand Up @@ -27,6 +27,9 @@
import hudson.DescriptorExtensionList;
import hudson.Extension;
import hudson.Launcher;
import hudson.matrix.MatrixAggregatable;
import hudson.matrix.MatrixAggregator;
import hudson.matrix.MatrixBuild;
import hudson.matrix.MatrixProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
Expand All @@ -39,6 +42,9 @@
import hudson.tasks.Publisher;
import hudson.tasks.Recorder;
import net.sf.json.JSONObject;

import org.jenkins_ci.plugins.run_condition.RunCondition;
import org.jenkins_ci.plugins.run_condition.BuildStepRunner;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

Expand All @@ -49,7 +55,7 @@
import java.util.List;
import java.util.Set;

public class FlexiblePublisher extends Recorder {
public class FlexiblePublisher extends Recorder implements MatrixAggregatable{

public static final String PROMOTION_JOB_TYPE = "hudson.plugins.promoted_builds.PromotionProcess";

Expand Down Expand Up @@ -146,9 +152,7 @@ public String getDisplayName() {
}

public boolean isApplicable(final Class<? extends AbstractProject> aClass) {
//@TODO enable for matrix builds - requires aggregation
// return FreeStyleProject.class.equals(aClass);
return !MatrixProject.class.equals(aClass) && !PROMOTION_JOB_TYPE.equals(aClass.getCanonicalName());
return !PROMOTION_JOB_TYPE.equals(aClass.getCanonicalName());
}

public Object readResolve() {
Expand All @@ -159,4 +163,74 @@ public Object readResolve() {

}

/**
* Return an aggregator worked for multi-configuration projects.
*
* {@link Publisher#perform(AbstractBuild, Launcher, BuildListener)} is called
* for each axe combination builds.
*
* For whole the multi-configuration project, {@link MatrixAggregator#endBuild()}
* is called instead.
*
* @param build
* @param launcher
* @param listener
* @return
* @see hudson.matrix.MatrixAggregatable#createAggregator(hudson.matrix.MatrixBuild, hudson.Launcher, hudson.model.BuildListener)
*/
@Override
public MatrixAggregator createAggregator(
MatrixBuild build, Launcher launcher, BuildListener listener
) {
List<ConditionalMatrixAggregator> aggregatorList
= new ArrayList<ConditionalMatrixAggregator>();

for (ConditionalPublisher cp: getPublishers()) {
if (!(cp.getPublisher() instanceof MatrixAggregatable)) {
continue;
}

// First, decide whether the condition is satisfied
// in the parent scope.
RunCondition cond;
BuildStepRunner runner;
if (cp.isConfiguredAggregation()) {
cond = cp.getAggregationCondition();
runner = cp.getAggregationRunner();
} else {
cond = cp.getCondition();
runner = cp.getRunner();
}

MarkPerformedBuilder mpb = new MarkPerformedBuilder();
boolean isSuccess = false;
try {
isSuccess = runner.perform(cond, mpb, build, launcher, listener);
} catch(Exception e) {
e.printStackTrace(listener.getLogger());
}

if (!isSuccess || !mpb.isPerformed()) {
// condition is not satisfied.
continue;
}

MatrixAggregator baseAggregator
= ((MatrixAggregatable)cp.getPublisher()).createAggregator(build, launcher, listener);
if (baseAggregator == null) {
continue;
}
aggregatorList.add(new ConditionalMatrixAggregator(
build, launcher, listener, cp, baseAggregator
));
}

if (aggregatorList.isEmpty()) {
return null;
}

return new FlexibleMatrixAggregator(
build, launcher, listener, aggregatorList
);
}
}

0 comments on commit 3fbb375

Please sign in to comment.