diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml
new file mode 100644
index 0000000..94863e6
--- /dev/null
+++ b/.mvn/extensions.xml
@@ -0,0 +1,7 @@
+
+
+ io.jenkins.tools.incrementals
+ git-changelist-maven-extension
+ 1.0-beta-7
+
+
diff --git a/.mvn/maven.config b/.mvn/maven.config
new file mode 100644
index 0000000..2a0299c
--- /dev/null
+++ b/.mvn/maven.config
@@ -0,0 +1,2 @@
+-Pconsume-incrementals
+-Pmight-produce-incrementals
diff --git a/pom.xml b/pom.xml
index 0754490..bd3f945 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,12 +3,12 @@
org.jenkins-ci.plugins
plugin
- 2.31
+ 3.25
ant
- 1.9-SNAPSHOT
+ ${revision}${changelist}
hpi
Ant Plugin
Adds Apache Ant support to Jenkins
@@ -24,18 +24,21 @@
scm:git:git://github.com/jenkinsci/${project.artifactId}-plugin.git
scm:git:git@github.com:jenkinsci/${project.artifactId}-plugin.git
- HEAD
+ ${scmTag}
- 1.651.3
+ 1.9
+ -SNAPSHOT
+ 2.121.2
+ 8
org.jenkins-ci.plugins
structs
- 1.6
+ 1.17
org.jenkins-ci.main
@@ -52,13 +55,13 @@
org.jenkins-ci.plugins.workflow
workflow-cps
- 2.32
+ 2.58
test
org.jenkins-ci.plugins.workflow
workflow-job
- 2.9
+ 2.26
test
@@ -70,7 +73,13 @@
org.jenkins-ci.plugins.workflow
workflow-durable-task-step
- 2.5
+ 2.26-rc791.37915aaf7f4d
+ test
+
+
+ org.jenkins-ci.plugins
+ durable-task
+ 1.27-rc374.ea1d4ad27dd9
test
diff --git a/src/main/java/hudson/tasks/Ant.java b/src/main/java/hudson/tasks/Ant.java
index 3ab7d3b..375d481 100644
--- a/src/main/java/hudson/tasks/Ant.java
+++ b/src/main/java/hudson/tasks/Ant.java
@@ -58,6 +58,7 @@
import org.kohsuke.stapler.QueryParameter;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import hudson.remoting.VirtualChannel;
import java.io.File;
import java.io.IOException;
@@ -395,22 +396,27 @@ public void buildEnvVars(EnvVars env) {
* Gets the executable path of this Ant on the given target system.
*/
public String getExecutable(Launcher launcher) throws IOException, InterruptedException {
- return launcher.getChannel().call(new MasterToSlaveCallable() {
- private static final long serialVersionUID = 906341330603832653L;
- public String call() throws IOException {
- File exe = getExeFile();
- if(exe.exists())
- return exe.getPath();
- return null;
- }
- });
+ VirtualChannel channel = launcher.getChannel();
+ if (channel == null) {
+ throw new IOException("offline?");
+ }
+ return channel.call(new GetExecutable(getHome()));
}
-
- private File getExeFile() {
- String execName = Functions.isWindows() ? "ant.bat" : "ant";
- String home = Util.replaceMacro(getHome(), EnvVars.masterEnvVars);
-
- return new File(home,"bin/"+execName);
+ private static class GetExecutable extends MasterToSlaveCallable {
+ private static final long serialVersionUID = 906341330603832653L;
+ private final String rawHome;
+ GetExecutable(String rawHome) {
+ this.rawHome = rawHome;
+ }
+ @Override public String call() throws IOException {
+ String execName = Functions.isWindows() ? "ant.bat" : "ant";
+ String home = Util.replaceMacro(rawHome, EnvVars.masterEnvVars);
+ File exe = new File(home, "bin/" + execName);
+ if (exe.exists()) {
+ return exe.getPath();
+ }
+ return null;
+ }
}
/**
diff --git a/src/main/java/hudson/tasks/_ant/AntConsoleAnnotator.java b/src/main/java/hudson/tasks/_ant/AntConsoleAnnotator.java
index 996ca4a..a0383dc 100644
--- a/src/main/java/hudson/tasks/_ant/AntConsoleAnnotator.java
+++ b/src/main/java/hudson/tasks/_ant/AntConsoleAnnotator.java
@@ -27,12 +27,14 @@
import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.Run;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
+import jenkins.util.JenkinsJVM;
/**
* Filter {@link OutputStream} that places an annotation that marks Ant target execution.
@@ -43,12 +45,32 @@
public class AntConsoleAnnotator extends LineTransformationOutputStream {
private final OutputStream out;
private final Charset charset;
+ /** Serialized, signed, and Base64-encoded forms of {@link AntTargetNote} and {@link AntOutcomeNote} respectively. */
+ private final byte[][] antNotes;
private boolean seenEmptyLine;
public AntConsoleAnnotator(OutputStream out, Charset charset) {
+ this(out, charset, createAntNotes());
+ }
+
+ private AntConsoleAnnotator(OutputStream out, Charset charset, byte[][] antNotes) {
this.out = out;
this.charset = charset;
+ this.antNotes = antNotes;
+ }
+
+ private static byte[][] createAntNotes() {
+ JenkinsJVM.checkJenkinsJVM();
+ try {
+ ByteArrayOutputStream targetNote = new ByteArrayOutputStream();
+ new AntTargetNote().encodeTo(targetNote);
+ ByteArrayOutputStream outcomeNote = new ByteArrayOutputStream();
+ new AntOutcomeNote().encodeTo(outcomeNote);
+ return new byte[][] {targetNote.toByteArray(), outcomeNote.toByteArray()};
+ } catch (IOException x) { // should be impossible
+ throw new RuntimeException(x);
+ }
}
@Override
@@ -60,10 +82,10 @@ protected void eol(byte[] b, int len) throws IOException {
if (seenEmptyLine && endsWith(line,':') && line.indexOf(' ')<0)
// put the annotation
- new AntTargetNote().encodeTo(out);
+ out.write(antNotes[0]);
if (line.equals("BUILD SUCCESSFUL") || line.equals("BUILD FAILED"))
- new AntOutcomeNote().encodeTo(out);
+ out.write(antNotes[1]);
seenEmptyLine = line.length()==0;
out.write(b,0,len);
@@ -74,6 +96,11 @@ private boolean endsWith(String line, char c) {
return len>0 && line.charAt(len-1)==c;
}
+ @Override
+ public void flush() throws IOException {
+ out.flush();
+ }
+
@Override
public void close() throws IOException {
super.close();
@@ -85,8 +112,15 @@ public static ConsoleLogFilter asConsoleLogFilter() {
}
private static class ConsoleLogFilterImpl extends ConsoleLogFilter implements Serializable {
private static final long serialVersionUID = 1;
+ private byte[][] antNotes = createAntNotes();
+ private Object readResolve() {
+ if (antNotes == null) { // old program.dat
+ antNotes = createAntNotes();
+ }
+ return this;
+ }
@Override public OutputStream decorateLogger(Run build, OutputStream logger) throws IOException, InterruptedException {
- return new AntConsoleAnnotator(logger, Charsets.UTF_8);
+ return new AntConsoleAnnotator(logger, Charsets.UTF_8, antNotes);
}
}
diff --git a/src/test/java/hudson/tasks/AntWrapperTest.java b/src/test/java/hudson/tasks/AntWrapperTest.java
index 234c621..684121f 100644
--- a/src/test/java/hudson/tasks/AntWrapperTest.java
+++ b/src/test/java/hudson/tasks/AntWrapperTest.java
@@ -26,7 +26,10 @@
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
+import hudson.console.ConsoleNote;
import hudson.model.FreeStyleProject;
+import hudson.slaves.DumbSlave;
+import java.util.logging.Level;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
@@ -38,6 +41,7 @@
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.LoggerRule;
import org.jvnet.hudson.test.RestartableJenkinsRule;
import org.jvnet.hudson.test.ToolInstallations;
@@ -46,6 +50,7 @@ public class AntWrapperTest {
@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public RestartableJenkinsRule r = new RestartableJenkinsRule();
@Rule public TemporaryFolder tmp = new TemporaryFolder();
+ @Rule public LoggerRule logging = new LoggerRule();
@Test public void configRoundTrip() throws Exception {
r.addStep(new Statement() {
@@ -70,12 +75,13 @@ public class AntWrapperTest {
r.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
ToolInstallations.configureDefaultAnt(tmp); // TODO could instead use DockerRule to run against a specified JDK location
+ DumbSlave s = r.j.createOnlineSlave();
+ logging.recordPackage(ConsoleNote.class, Level.FINE);
WorkflowJob p = r.j.createProject(WorkflowJob.class, "p");
- r.j.jenkins.getWorkspaceFor(p).child("build.xml").copyFrom(AntWrapperTest.class.getResource("_ant/simple-build.xml"));
- p.setDefinition(new CpsFlowDefinition("node {withAnt(installation: 'default') {if (isUnix()) {sh 'ant foo'} else {bat 'ant foo'}}}", true));
+ s.getWorkspaceFor(p).child("build.xml").copyFrom(AntWrapperTest.class.getResource("_ant/simple-build.xml"));
+ p.setDefinition(new CpsFlowDefinition("node('!master') {withAnt(installation: 'default') {if (isUnix()) {sh 'ant foo'} else {bat 'ant foo'}}}", true));
WorkflowRun b = r.j.buildAndAssertSuccess(p);
- // TODO passes locally, fails in jenkins.ci: AntConsoleAnnotator processes AntOutcomeNote but not AntTargetNote
- // (perhaps because it seems to have set ANT_HOME=/opt/ant/latest? yet the output looks right)
+ b.getLogText().writeRawLogTo(0, System.err);
AntTest.assertHtmlLogContains(b, "foo");
AntTest.assertHtmlLogContains(b, "bar");
JenkinsRule.WebClient wc = r.j.createWebClient();