Permalink
Browse files

[FIXED JENKINS-42338] Install root-level tools on stage agents.

Override the root-level tools with any stage-level tool definitions of
the same type.
  • Loading branch information...
abayer committed Jul 6, 2017
1 parent 2c0b4d6 commit fc0ebf67d0635041689b49ab5456c0d85950c87b
@@ -29,6 +29,7 @@ import hudson.tools.ToolDescriptor
import org.jenkinsci.Symbol
import org.jenkinsci.plugins.pipeline.modeldefinition.Utils

import javax.annotation.CheckForNull
import javax.annotation.Nonnull

/**
@@ -56,6 +57,23 @@ public class Tools extends MappedClosure<String,Tools> implements Serializable {
}
}

/**
* Merges the tool entries from another instance into this one, defaulting to the current instance's values.
*
* @return A list of type/name tuples
*/
public List<List<Object>> mergeToolEntries(@CheckForNull Tools other) {
if (other == null) {
return getToolEntries()
} else {
Map<String,Object> mergedMap = new TreeMap<>()
mergedMap.putAll(other.getMap())
mergedMap.putAll(getMap())

return mergedMap.collect { k, v -> return [k, v] }
}
}

/**
* Get a map of allowed tool type keys to their actual type ID. If a {@link Symbol} is on the descriptor for a given
* tool, use that as the key. Otherwise, use the class name.
@@ -96,7 +96,7 @@ public class ModelInterpreter implements Serializable {
if (evaluateWhen(thisStage.when)) {
withCredentialsBlock(thisStage.environment, root.environment) {
withEnvBlock(thisStage.getEnvVars(root, script)) {
toolsBlock(thisStage.agent ?: root.agent, thisStage.tools) {
toolsBlock(thisStage.agent ?: root.agent, thisStage.tools, root) {
// Execute the actual stage and potential post-stage actions
executeSingleStage(root, thisStage)
}
@@ -306,14 +306,20 @@ public class ModelInterpreter implements Serializable {
* Executes a given closure in a "withEnv" block after installing the specified tools
* @param agent The agent context we're running in
* @param tools The tools configuration we're using
* @param root The root level configuration, if we're called within a stage. Can be null.
* @param body The closure to execute
* @return The return of the resulting executed closure
*/
def toolsBlock(Agent agent, Tools tools, Closure body) {
def toolsBlock(Agent agent, Tools tools, Root root = null, Closure body) {
def toolsList = []
if (tools != null) {
toolsList = tools.mergeToolEntries(root?.tools)
} else if (root?.tools != null) {
toolsList = root.tools.getToolEntries()
}
// If there's no agent, don't install tools in the first place.
if (agent.hasAgent() && tools != null) {
if (agent.hasAgent() && !toolsList.isEmpty()) {
def toolEnv = []
def toolsList = tools.getToolEntries()
if (!Utils.withinAStage()) {
script.stage(SyntheticStageNames.toolInstall()) {
toolEnv = actualToolsInstall(toolsList)
@@ -31,6 +31,7 @@
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.junit.BeforeClass;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;

import static org.junit.Assert.assertNotNull;
@@ -63,6 +64,14 @@ public void toolsInStage() throws Exception {
.go();
}

@Issue("JENKINS-42338")
@Test
public void toolsAndAgentNone() throws Exception {
expect("toolsAndAgentNone")
.logContains("[Pipeline] { (foo)", "Apache Maven 3.0.1")
.go();
}

@Test
public void buildPluginParentPOM() throws Exception {

@@ -0,0 +1,43 @@
/*
* 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.
*/

pipeline {
agent none
tools {
maven "apache-maven-3.0.1"
}
stages {
stage("foo") {
agent {
label "some-label"
}
steps {
sh 'mvn --version'
}
}
}
}



0 comments on commit fc0ebf6

Please sign in to comment.