Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-44834] Partial pipeline support #52

Closed
wants to merge 10 commits into from
39 changes: 33 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import java.util.zip.ZipFile

buildscript { // TODO: remove if https://github.com/jenkinsci/gradle-jpi-plugin/pull/87 is merged & released
repositories {
maven {
url('https://repo.jenkins-ci.org/public/')
}
mavenLocal()
}
dependencies {
classpath 'org.jenkins-ci.tools:gradle-jpi-plugin:0.23.0-SNAPSHOT'
}
}

plugins {
id "org.jenkins-ci.jpi" version "0.22.0"
//id "org.jenkins-ci.jpi" version "0.23.0" TODO: uncomment if #87 is merged & released
id 'ru.vyarus.animalsniffer' version '1.3.0'
id 'findbugs'
id 'codenarc'
}

apply plugin: 'org.jenkins-ci.jpi' // TODO: remove if #87 is merged & released

group = "org.jenkins-ci.plugins"
description = "This plugin adds Gradle support to Jenkins"

Expand All @@ -18,7 +32,7 @@ if (ciBuild) {

jenkinsPlugin {
// Version of Jenkins core this plugin depends on.
coreVersion = "1.642.1"
coreVersion = "1.642.3"

// Human-readable name of plugin.
displayName = "Gradle Plugin"
Expand Down Expand Up @@ -48,13 +62,26 @@ sourceCompatibility = '1.7'

dependencies {
compile 'org.jenkins-ci.lib:dry-run-lib:0.1'
compileOnly 'org.jenkins-ci:symbol-annotation:1.3'
jenkinsPlugins 'org.jenkins-ci.plugins:structs:1.3@jar'

compile 'junit:junit:4.12' // TODO: remove. this should be included in jenkins-test-harness
signature 'org.codehaus.mojo.signature:java17:1.0@signature'

testCompile 'org.spockframework:spock-core:0.7-groovy-1.8'
jenkinsTest 'org.jenkins-ci.main:jenkins-test-harness:2.8@jar'
jenkinsTest 'org.jenkins-ci.main:jenkins-test-harness:2.22'
jenkinsTest 'org.jenkins-ci.main:jenkins-test-harness-tools:2.2'

jenkinsPlugins('org.jenkins-ci.plugins:structs:1.7') { transitive = true }
jenkinsPlugins 'org.jenkins-ci.plugins.workflow:workflow-step-api:2.11'
jenkinsTest('org.jenkins-ci.plugins.workflow:workflow-api:2.15') { transitive = true }
jenkinsTest('org.jenkins-ci.plugins.workflow:workflow-cps:2.32') { transitive = true }
jenkinsTest 'org.jenkins-ci.plugins.workflow:workflow-job:2.11'
jenkinsTest 'org.jenkins-ci.plugins.workflow:workflow-basic-steps:2.5'
jenkinsTest 'org.jenkins-ci.plugins.workflow:workflow-scm-step:2.4'
jenkinsTest 'org.jenkins-ci.plugins.workflow:workflow-support:2.14'
jenkinsTest 'org.jenkins-ci.plugins.workflow:workflow-durable-task-step:2.9'

jenkinsTest 'org.jenkins-ci.plugins:scm-api:2.0.7'
jenkinsTest 'org.jenkins-ci.plugins:script-security:1.26'
jenkinsTest 'org.jenkins-ci.plugins:durable-task:1.13'
}

if (project.hasProperty("maxParallelForks")) {
Expand Down
134 changes: 134 additions & 0 deletions src/main/java/hudson/plugins/gradle/WithGradle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* The MIT License
*
* Copyright (c) 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.plugins.gradle;

import com.google.common.collect.ImmutableSet;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;

import hudson.Util;
import hudson.model.JDK;
import hudson.model.Run;
import hudson.model.TaskListener;
import hudson.tools.ToolInstallation;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.workflow.steps.Step;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.jenkinsci.plugins.workflow.steps.StepExecution;
import org.jenkinsci.plugins.workflow.steps.StepDescriptor;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

import java.util.Set;

/**
* The WithGradle pipeline step. For the most part only getters, setters and scaffolding code. The actual logic and
* configuration are in {@link WithGradleExecution}.
*
* @author Alex Johnson
*/
public class WithGradle extends Step {

/** The Gradle installation to use */
private String gradleName;
/** The name of the Java Installation */
private String jdkName;

@DataBoundConstructor
public WithGradle () {

}

/**
* Sets the globally configured gradle installation to set the GRADLE_HOME for
* @param gradleName the name of the installation to use
*/
@DataBoundSetter
public void setGradleName (String gradleName) {
this.gradleName = Util.fixEmpty(gradleName);
}

public String getGradleName () {
return gradleName;
}

/**
* Sets the Java installation to use
* @param jdkName the path of the jdk to use
*/
@DataBoundSetter
public void setJdkName (String jdkName) {
this.jdkName = Util.fixEmpty(jdkName);
}

public String getJdkName () {
return jdkName;
}


@Override
public StepExecution start(StepContext context) throws Exception {
return new WithGradleExecution(context, this);
}

@Extension
public static final class DescriptorImpl extends StepDescriptor {

@Override
public Set<? extends Class<?>> getRequiredContext() {
return ImmutableSet.of(Run.class, FilePath.class, TaskListener.class, EnvVars.class);
}

@Override
public String getFunctionName() {
return "withGradle";
}

@Override
public String getDisplayName() {
return "Sets up a Gradle environment and annotates the console output";
}

@Override
public boolean takesImplicitBlockArgument() {
return true;
}

/**
* Obtains the {@link GradleInstallation.DescriptorImpl} instance.
*/
public GradleInstallation[] getInstallations() {
return ToolInstallation.all().get(GradleInstallation.DescriptorImpl.class).getInstallations();
}

/**
* Obtains the {@link GradleInstallation.DescriptorImpl} instance.
*/
public JDK[] getJdkInstallations() {
return ToolInstallation.all().get(JDK.DescriptorImpl.class).getInstallations();
}
}

}
143 changes: 143 additions & 0 deletions src/main/java/hudson/plugins/gradle/WithGradleExecution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* The MIT License
*
* Copyright (c) 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.plugins.gradle;

import hudson.EnvVars;
import hudson.FilePath;
import hudson.console.ConsoleLogFilter;
import hudson.model.JDK;
import hudson.model.TaskListener;
import hudson.model.Run;
import hudson.tools.ToolInstallation;
import jenkins.model.Jenkins;
import org.jenkinsci.plugins.workflow.steps.BodyExecution;
import org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback;
import org.jenkinsci.plugins.workflow.steps.BodyInvoker;
import org.jenkinsci.plugins.workflow.steps.EnvironmentExpander;
import org.jenkinsci.plugins.workflow.steps.StepContext;
import org.jenkinsci.plugins.workflow.steps.StepExecution;

import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.Charset;

/**
* The execution of the {@link WithGradle} pipeline step. Configures the ConsoleAnnotator for a Gradle build and, if
* specified, configures Gradle and Java for the build.
*
* @author Alex Johnson
*/
public class WithGradleExecution extends StepExecution {

/** The step for the Execution */
private transient WithGradle step;
private BodyExecution block;

public WithGradleExecution(StepContext context, WithGradle step) throws IOException, InterruptedException {
super(context);
this.step = step;
}

/**
* {@inheritDoc}
*/
@Override
public boolean start() throws Exception {
TaskListener listener = getContext().get(TaskListener.class);
EnvVars envVars = getContext().get(EnvVars.class);

listener.getLogger().printf("[WithGradle] Execution begin %n");
String gradleName = step.getGradleName();
if (gradleName != null) {
GradleInstallation gradleInstallation = null;
GradleInstallation[] installations = ToolInstallation.all().get(GradleInstallation.DescriptorImpl.class).getInstallations();
for (GradleInstallation i : installations) {
if (i.getName().equals(gradleName)) {
gradleInstallation = i;
}
}
if (gradleInstallation == null) {
listener.getLogger().printf("[WithGradle] Gradle Installation '%s' not found. Defaulting to system installation. %n", gradleName);
} else {
listener.getLogger().printf("[WithGradle] Gradle Installation found. Using '%s' %n", gradleInstallation.getName());
envVars.put("GRADLE_HOME", gradleInstallation.getHome());
envVars.put("PATH+GRADLE", gradleInstallation.getHome() + "/bin");
}
} else {
listener.getLogger().printf("[WithGradle] Defaulting to system installation of Gradle. %n");
}

String javaName = step.getJdkName();
if (javaName != null) {
JDK javaInstallation = Jenkins.getActiveInstance().getJDK(javaName);
if (javaInstallation == null) {
listener.getLogger().printf("[WithGradle] Java Installation '%s' not found. Defaulting to system installation. %n", javaName);
} else {
listener.getLogger().printf("[WithGradle] Java Installation found. Using '%s' %n", javaInstallation.getName());
envVars.put("JAVA_HOME", javaInstallation.getHome());
}
}

ConsoleLogFilter annotator = BodyInvoker.mergeConsoleLogFilters(getContext().get(ConsoleLogFilter.class), new GradleConsoleFilter());
EnvironmentExpander expander = EnvironmentExpander.merge(getContext().get(EnvironmentExpander.class), EnvironmentExpander.constant(envVars));

block = getContext().newBodyInvoker().withCallback(BodyExecutionCallback.wrap(getContext())).withContexts(annotator, expander).start();

return false;
}

/**
* {@inheritDoc}
*/
@Override
public void stop(@Nonnull Throwable cause) throws Exception {

}

/**
* Wraps {@link GradleConsoleAnnotator} in a {@link ConsoleLogFilter} so it can be merged with the existing
* log filter.
*/
private static class GradleConsoleFilter extends ConsoleLogFilter implements Serializable {

private static final long serialVersionUID = 1;

public GradleConsoleFilter() {
}

/**
* Creates a {@link GradleConsoleAnnotator} for an {@link OutputStream}
*
* @param run this is ignored
* @param out the {@link OutputStream} to annotate
* @return the {@link GradleConsoleAnnotator} for the OutputStream
*/
@Override
public OutputStream decorateLogger(Run run, final OutputStream out) {
return new GradleConsoleAnnotator(out, Charset.forName("UTF-8"));
}
}
}
24 changes: 24 additions & 0 deletions src/main/resources/hudson/plugins/gradle/WithGradle/config.jelly
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core"
xmlns:f="/lib/form">

<f:entry title="${%Gradle Version}" field="gradleName">
<select class="setting-input" name="gradleName">
<option value="">(Default)</option>
<j:forEach var="inst" items="${descriptor.installations}">
<f:option selected="${inst.name==instance.gradle.gradleName}">${inst.name}</f:option>
</j:forEach>
</select>
</f:entry>

<f:advanced>
<f:entry title="${%Jdk Version}" field="jdkName">
<select class="setting-input" name="jdkName">
<option value="">(Default)</option>
<j:forEach var="inst" items="${descriptor.jdkInstallations}">
<f:option selected="${inst.name==instance.gradle.jdkName}">${inst.name}</f:option>
</j:forEach>
</select>
</f:entry>
</f:advanced>
</j:jelly>
Loading