Skip to content

Commit

Permalink
Merge pull request #22 from jglick/pipeline-JENKINS-26056
Browse files Browse the repository at this point in the history
[JENKINS-26056] Pipeline-compatible Ant build wrapper
  • Loading branch information
jglick committed Aug 8, 2017
2 parents a210ecc + 3320d57 commit 798cf27
Show file tree
Hide file tree
Showing 10 changed files with 374 additions and 13 deletions.
45 changes: 34 additions & 11 deletions pom.xml
Expand Up @@ -3,7 +3,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>2.28</version>
<version>2.31</version>
<relativePath />
</parent>

Expand All @@ -28,21 +28,14 @@
</scm>

<properties>
<jenkins.version>1.609.3</jenkins.version>
<java.level>6</java.level>
<jenkins.version>1.642.3</jenkins.version>
</properties>

<dependencies>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>structs</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
<version>1.7</version>
<scope>test</scope>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
Expand All @@ -56,6 +49,36 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.32</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-basic-steps</artifactId>
<version>2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-durable-task-step</artifactId>
<version>2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>matrix-project</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
Expand All @@ -68,7 +91,7 @@
<licenses>
<license>
<name>The MIT license</name>
<url>https://opensource.org/licenses/mit-license.php</url>
<url>https://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>
Expand Down
140 changes: 140 additions & 0 deletions src/main/java/hudson/tasks/AntWrapper.java
@@ -0,0 +1,140 @@
/*
* The MIT License
*
* Copyright 2017 CloudBees, Inc.
*
* 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 hudson.tasks;

import hudson.AbortException;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.console.ConsoleLogFilter;
import hudson.model.AbstractProject;
import hudson.model.Computer;
import hudson.model.EnvironmentSpecific;
import hudson.model.JDK;
import hudson.model.Node;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.slaves.NodeSpecific;
import hudson.tasks._ant.AntConsoleAnnotator;
import hudson.tools.ToolInstallation;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Nonnull;
import jenkins.model.Jenkins;
import jenkins.tasks.SimpleBuildWrapper;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

public class AntWrapper extends SimpleBuildWrapper {

private String installation;
private String jdk;

@DataBoundConstructor
public AntWrapper() {}

public String getInstallation() {
return installation;
}

@DataBoundSetter
public void setInstallation(String installation) {
this.installation = Util.fixEmpty(installation);
}

public String getJdk() {
return jdk;
}

@DataBoundSetter
public void setJdk(String jdk) {
this.jdk = Util.fixEmpty(jdk);
}

@Override
public void setUp(Context context, Run<?, ?> build, FilePath workspace, Launcher launcher, TaskListener listener, EnvVars initialEnvironment) throws IOException, InterruptedException {
if (installation != null) {
toolEnv(context, installation, Jenkins.getActiveInstance().getDescriptorByType(Ant.DescriptorImpl.class).getInstallations(), workspace, listener, initialEnvironment);
}
if (jdk != null) {
toolEnv(context, jdk, Jenkins.getActiveInstance().getDescriptorByType(JDK.DescriptorImpl.class).getInstallations(), workspace, listener, initialEnvironment);
}
}

// TODO this is pretty generic and could perhaps be added to SimpleBuildWrapper?
private static void toolEnv(Context context, @Nonnull String tool, ToolInstallation[] tools, FilePath workspace, TaskListener listener, EnvVars initialEnvironment) throws IOException, InterruptedException {
ToolInstallation inst = null;
for (ToolInstallation _inst : tools) {
if (_inst.getName().equals(tool)) {
inst = _inst;
break;
}
}
if (inst == null) {
throw new AbortException("no such tool ‘" + tool + "’");
}
if (inst instanceof NodeSpecific) {
Computer computer = workspace.toComputer();
if (computer != null) {
Node node = computer.getNode();
if (node != null) {
inst = (ToolInstallation) ((NodeSpecific) inst).forNode(node, listener);
}
}
}
if (inst instanceof EnvironmentSpecific) {
inst = (ToolInstallation) ((EnvironmentSpecific) inst).forEnvironment(initialEnvironment);
}
EnvVars modified = new EnvVars();
inst.buildEnvVars(modified);
for (Map.Entry<String, String> entry : modified.entrySet()) {
context.env(entry.getKey(), entry.getValue());
}
}

@Override
public ConsoleLogFilter createLoggerDecorator(Run<?, ?> build) {
return AntConsoleAnnotator.asConsoleLogFilter();
}

@Extension @Symbol("withAnt")
public static class DescriptorImpl extends BuildWrapperDescriptor {

@Override
public String getDisplayName() {
return "With Ant";
}

@Override
public boolean isApplicable(AbstractProject<?, ?> item) {
return true;
}

}

}
14 changes: 14 additions & 0 deletions src/main/java/hudson/tasks/_ant/AntConsoleAnnotator.java
Expand Up @@ -23,10 +23,14 @@
*/
package hudson.tasks._ant;

import com.google.common.base.Charsets;
import hudson.console.ConsoleLogFilter;
import hudson.console.LineTransformationOutputStream;
import hudson.model.Run;

import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

Expand Down Expand Up @@ -76,4 +80,14 @@ public void close() throws IOException {
out.close();
}

public static ConsoleLogFilter asConsoleLogFilter() {
return new ConsoleLogFilterImpl();
}
private static class ConsoleLogFilterImpl extends ConsoleLogFilter implements Serializable {
private static final long serialVersionUID = 1;
@Override public OutputStream decorateLogger(Run build, OutputStream logger) throws IOException, InterruptedException {
return new AntConsoleAnnotator(logger, Charsets.UTF_8);
}
}

}
49 changes: 49 additions & 0 deletions src/main/resources/hudson/tasks/AntWrapper/config.groovy
@@ -0,0 +1,49 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* 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 hudson.tasks.AntWrapper;
f=namespace(lib.FormTagLib)

def installations = app.getDescriptorByType(hudson.tasks.Ant.DescriptorImpl).installations
if (installations.length != 0) {
f.entry(title: _('Ant Version')) {
select(class: 'setting-input', name: 'ant.installation') {
option(value: '', _('Default'))
installations.each {
f.option(selected: it.name == instance?.installation, value: it.name, it.name)
}
}
}
}

def jdks = app.getDescriptorByType(hudson.model.JDK.DescriptorImpl).installations
if (jdks.length != 0) {
f.entry(title: _('JDK')) {
select(class: 'setting-input', name: 'ant.jdk') {
option(value: '', _('Default'))
jdks.each {
f.option(selected: it.name == instance?.jdk, value: it.name, it.name)
}
}
}
}
@@ -0,0 +1,3 @@
<p>
Name of an Ant installation to use so that <code>ant</code> will be in the path.
</p>
3 changes: 3 additions & 0 deletions src/main/resources/hudson/tasks/AntWrapper/help-jdk.html
@@ -0,0 +1,3 @@
<p>
Name of an Java installation to use when running Ant.
</p>
5 changes: 5 additions & 0 deletions src/main/resources/hudson/tasks/AntWrapper/help.html
@@ -0,0 +1,5 @@
<div>
Prepares an environment for Jenkins to run builds using Apache Ant.
Annotates Ant-specific output to display executed targets.
Optionally sets up an Ant and/or JDK installation.
</div>
4 changes: 2 additions & 2 deletions src/test/java/hudson/tasks/AntTest.java
Expand Up @@ -416,10 +416,10 @@ private static String getHtmlLog(Run<?, ?> build) throws IOException {
build.getLogText().writeHtmlTo(0, w);
return w.toString();
}
private static void assertHtmlLogContains(Run<?, ?> build, String text) throws IOException {
static void assertHtmlLogContains(Run<?, ?> build, String text) throws IOException {
assertThat(getHtmlLog(build), containsString(text));
}
private static void assertHtmlLogNotContains(Run<?, ?> build, String text) throws IOException {
static void assertHtmlLogNotContains(Run<?, ?> build, String text) throws IOException {
assertThat(getHtmlLog(build), not(containsString(text)));
}

Expand Down

0 comments on commit 798cf27

Please sign in to comment.