Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-15759] don't use AntIntegrator that
won't support jenkins remoting :
- distinct filesystem path between master and slave, 
- CIOption not serializable
- expect clover.jar to be present on build node
  • Loading branch information
ndeloof committed Nov 8, 2012
1 parent 7ed015b commit 3d46c71
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 39 deletions.
78 changes: 46 additions & 32 deletions src/main/java/hudson/plugins/clover/CloverBuildWrapper.java
@@ -1,5 +1,7 @@
package hudson.plugins.clover;

import com.cenqua.clover.util.ClassPathUtil;
import hudson.remoting.Callable;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.Launcher;
Expand Down Expand Up @@ -62,7 +64,7 @@ public Environment setUp(AbstractBuild build, Launcher launcher, BuildListener l

private void addCloverPublisher(AbstractBuild build, BuildListener listener) throws IOException {
DescribableList publishers = build.getProject().getPublishersList();
if (!publishers.contains(CloverPublisher.DESCRIPTOR)) {
if (!publishers.contains(getDescriptor())) {
final String reportDir = "clover";
listener.getLogger().println("Adding Clover Publisher with reportDir: " + reportDir);
build.getProject().getPublishersList().add(new CloverPublisher(reportDir, null));
Expand Down Expand Up @@ -91,12 +93,9 @@ public Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildLi
fullClean(true);

final Launcher outer = launcher;
return new CloverDecoratingLauncher(outer, options, license);
return new CloverDecoratingLauncher(this, outer, options, license);
}

public static final Descriptor<BuildWrapper> DESCRIPTOR = new DescriptorImpl();


/**
* Descriptor for {@link CloverPublisher}. Used as a singleton. The class is marked as public so that it can be
* accessed from views.
Expand Down Expand Up @@ -149,9 +148,11 @@ public static class CloverDecoratingLauncher extends Launcher {
private final Launcher outer;
private final CIOptions.Builder options;
private final String license;
private final CloverBuildWrapper wrapper;

public CloverDecoratingLauncher(Launcher outer, CIOptions.Builder options, String license) {
public CloverDecoratingLauncher(CloverBuildWrapper cloverBuildWrapper, Launcher outer, CIOptions.Builder options, String license) {
super(outer);
this.wrapper = cloverBuildWrapper;
this.outer = outer;
this.options = options;
this.license = license;
Expand All @@ -171,7 +172,7 @@ public Proc launch(ProcStarter starter) throws IOException {

public void decorateArgs(ProcStarter starter) throws IOException {

List<String> userArgs = new LinkedList<String>();
final List<String> userArgs = new LinkedList<String>();
List<String> preSystemArgs = new LinkedList<String>();
List<String> postSystemArgs = new LinkedList<String>();

Expand Down Expand Up @@ -223,16 +224,47 @@ public void decorateArgs(ProcStarter starter) throws IOException {

if (!userArgs.isEmpty())
{
// We can't use clover AntDecorator as this one isn't serializable on jenkins remoting
// and expect to be loaded from clover.jar, not remoting classloader

// TODO: full clean needs to be an option. see http://jira.atlassian.com/browse/CLOV-736
options.fullClean(true);
userArgs.add(0, "clover.fullclean");

setupLicense(starter);
// As decompiled from com.atlassian.clover.ci.AntIntegrator;
if(!wrapper.json) {
userArgs.add("-Dclover.skip.json=true");
}

Integrator integrator = Integrator.Factory.newAntIntegrator(options.build());

integrator.decorateArguments(userArgs);
starter.cmds(new ArrayList<String>());
if(!wrapper.historical) {
userArgs.add("-Dclover.skip.report=true");
} else {
userArgs.add("-Dclover.skip.current=true");
}

FilePath cloverJar = new FilePath( new FilePath(starter.pwd(), ".clover"), "clover.jar");
try {
String cloverJarLocation = ClassPathUtil.getCloverJarPath();
cloverJar.copyFrom(new FilePath(new File(cloverJarLocation)));
userArgs.add("-lib");
userArgs.add("\"" + cloverJar.getRemote() + "\"");
} catch (InterruptedException e) {
listener.getLogger().print("Could not create clover library file at: " + cloverJar + ". Please supply '-lib /path/to/clover.jar'.");
listener.getLogger().print(e.getMessage());
}

FilePath licenseFile = new FilePath( new FilePath(starter.pwd(), ".clover"), "clover.license");
try {
if (license == null) {
listener.getLogger().println("No Clover license configured. Please download a free 30 day license from http://my.atlassian.com.");
return;
}
licenseFile.write(license, "UTF-8");
userArgs.add("-Dclover.license.path=\"" + licenseFile.getRemote() + "\"");
} catch (InterruptedException e) {
listener.getLogger().print("Could not create license file at: " + licenseFile + ". Setting as a system property.");
listener.getLogger().print(e.getMessage());
userArgs.add("-Dclover.license.cert=\"" + license + "\"");
}

// re-assemble all commands
List<String> allCommands = new ArrayList<String>();
Expand All @@ -250,25 +282,6 @@ public void decorateArgs(ProcStarter starter) throws IOException {
}
}

private void setupLicense(ProcStarter starter) throws IOException {

if (license == null) {
listener.getLogger().println("No Clover license configured. Please download a free 30 day license from http://my.atlassian.com.");
return;
}

// create a tmp license file.
FilePath licenseFile = new FilePath(starter.pwd(), ".clover/clover.license");
try {
licenseFile.write(license, "UTF-8");
options.license(new File(licenseFile.toURI()));
} catch (InterruptedException e) {
listener.getLogger().print("Could not create license file at: " + licenseFile + ". Setting as a system property.");
listener.getLogger().print(e.getMessage());
options.licenseCert(license);
}
}

@Override
public Channel launchChannel(String[] cmd, OutputStream out, FilePath workDir, Map<String, String> envVars) throws IOException, InterruptedException {
return outer.launchChannel(cmd, out, workDir, envVars);
Expand All @@ -280,4 +293,5 @@ public void kill(Map<String, String> modelEnvVars) throws IOException, Interrupt
}

}

}
19 changes: 12 additions & 7 deletions src/test/java/hudson/plugins/clover/CloverBuildWrapperTest.java
Expand Up @@ -8,6 +8,7 @@
import hudson.remoting.Channel;
import hudson.model.TaskListener;

import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.Map;
Expand All @@ -25,8 +26,9 @@ public void testDecoratinLauncher() throws IOException
{
TaskListener listener = new LogTaskListener(Logger.getLogger(getName()), Level.ALL);
Launcher outer = new Launcher.LocalLauncher(listener);
CIOptions.Builder options = new CIOptions.Builder();
CloverBuildWrapper.CloverDecoratingLauncher cloverLauncher = new CloverBuildWrapper.CloverDecoratingLauncher(outer, options, "MYLICENSESTRING");
CIOptions.Builder options = new CIOptions.Builder();
CloverBuildWrapper wrapper = new CloverBuildWrapper(true, true, "FOO");
CloverBuildWrapper.CloverDecoratingLauncher cloverLauncher = new CloverBuildWrapper.CloverDecoratingLauncher(wrapper, outer, options, "MYLICENSESTRING");

Launcher.ProcStarter starter = new Launcher(cloverLauncher) {
public Proc launch(ProcStarter starter) throws IOException {
Expand All @@ -43,13 +45,16 @@ public void kill(Map<String, String> modelEnvVars) throws IOException, Interrupt

starter.cmds("cmd.exe", "/C", "\"ant.bat clean test.run && exit %%ERRORLEVEL%%\"");
starter.pwd("target");
starter.masks(new boolean[starter.cmds().size()] );
List<String> cmds = starter.cmds();
starter.masks(new boolean[cmds.size()]);
cloverLauncher.decorateArgs(starter);

cmds = starter.cmds();
int i = 0;
assertEquals("cmd.exe", starter.cmds().get(i++));
assertEquals("/C", starter.cmds().get(i++));
assertEquals("ant.bat", starter.cmds().get(i++));
assertEquals("clover.fullclean", starter.cmds().get(i++));
assertEquals("cmd.exe", cmds.get(i++));
assertEquals("/C", cmds.get(i++));
assertEquals("ant.bat", cmds.get(i++));
assertEquals("clover.fullclean", cmds.get(i++));
}

}

0 comments on commit 3d46c71

Please sign in to comment.