Skip to content
Permalink
Browse files

[FIXED JENKINS-39244, FIXED JENKINS-39245] Add env and tools to stages

Adds support for tools and environment sections inside individual stages.
  • Loading branch information...
abayer committed Oct 25, 2016
1 parent d78fa19 commit 7d3724c6a1cb6491565bfd94799ad86c890e459f
@@ -18,6 +18,8 @@
private ModelASTAgent agent;
private List<ModelASTBranch> branches = new ArrayList<ModelASTBranch>();
private ModelASTPostStage post;
private ModelASTTools tools;
private ModelASTEnvironment environment;

public ModelASTStage(Object sourceLocation) {
super(sourceLocation);
@@ -40,6 +42,14 @@ public JSONObject toJSON() {
o.accumulate("post", post.toJSON());
}

if (tools != null) {
o.accumulate("tools", tools.toJSON());
}

if (environment != null) {
o.accumulate("environment", environment.toJSON());
}

return o;
}

@@ -55,6 +65,12 @@ public void validate(final ModelValidator validator) {
if (post != null) {
post.validate(validator);
}
if (tools != null) {
tools.validate(validator);
}
if (environment != null) {
environment.validate(validator);
}
}

@Override
@@ -65,7 +81,12 @@ public String toGroovy() {
if (agent != null) {
result.append(agent.toGroovy());
}

if (tools != null) {
result.append(tools.toGroovy());
}
if (environment != null) {
result.append(environment.toGroovy());
}
result.append("steps {\n");
if (branches.size() > 1) {
result.append("parallel(");
@@ -107,6 +128,12 @@ public void removeSourceLocation() {
if (post != null) {
post.removeSourceLocation();
}
if (tools != null) {
tools.removeSourceLocation();
}
if (environment != null) {
environment.removeSourceLocation();
}
}

public String getName() {
@@ -141,13 +168,31 @@ public void setPost(ModelASTPostStage post) {
this.post = post;
}

public ModelASTTools getTools() {
return tools;
}

public void setTools(ModelASTTools tools) {
this.tools = tools;
}

public ModelASTEnvironment getEnvironment() {
return environment;
}

public void setEnvironment(ModelASTEnvironment environment) {
this.environment = environment;
}

@Override
public String toString() {
return "ModelASTStage{" +
"name='" + name + '\'' +
", agent=" + agent +
", branches=" + branches +
", post=" + post +
", tools=" + tools +
", environment=" + environment +
"}";
}

@@ -174,6 +219,12 @@ public boolean equals(Object o) {
if (getPost() != null ? !getPost().equals(that.getPost()) : that.getPost() != null) {
return false;
}
if (getTools() != null ? !getTools().equals(that.getTools()) : that.getTools() != null) {
return false;
}
if (getEnvironment() != null ? !getEnvironment().equals(that.getEnvironment()) : that.getEnvironment() != null) {
return false;
}
return getBranches() != null ? getBranches().equals(that.getBranches()) : that.getBranches() == null;

}
@@ -184,6 +235,9 @@ public int hashCode() {
result = 31 * result + (getName() != null ? getName().hashCode() : 0);
result = 31 * result + (getAgent() != null ? getAgent().hashCode() : 0);
result = 31 * result + (getBranches() != null ? getBranches().hashCode() : 0);
result = 31 * result + (getPost() != null ? getPost().hashCode() : 0);
result = 31 * result + (getTools() != null ? getTools().hashCode() : 0);
result = 31 * result + (getEnvironment() != null ? getEnvironment().hashCode() : 0);
return result;
}
}
@@ -50,6 +50,10 @@ public class Stage implements NestedModel, Serializable {
@Whitelisted
PostStage post

Tools tools

Environment environment

@Whitelisted
Stage name(String n) {
this.name = n
@@ -80,6 +84,29 @@ public class Stage implements NestedModel, Serializable {
return this
}

Stage tools(Tools tools) {
this.tools = tools
return this
}

Stage environment(Environment environment) {
this.environment = environment
return this
}

/**
* Helper method for translating the key/value pairs in the {@link Environment} into a list of "key=value" strings
* suitable for use with the withEnv step.
*
* @return a list of "key=value" strings.
*/
List<String> getEnvVars() {
return environment.collect { k, v ->
"${k}=${v}"
}
}


@Override
@Whitelisted
public void modelFromMap(Map<String,Object> m) {
@@ -180,18 +180,25 @@ class JSONParser {
stage.branches.add(parseBranch(o))
}

if (j.has("environment")) {
stage.environment = parseEnvironment(j.getJSONArray("environment"))
}

if (j.has("tools")) {
stage.tools = parseTools(j.getJSONArray("tools"))
}

if (j.has("post")) {
def object = j.getJSONObject("post")
if (!object.isNullObject()) {
stage.post = parsePostStage(object)
}
}

return stage

}



public @CheckForNull ModelASTBranch parseBranch(JSONObject j) {
ModelASTBranch branch = new ModelASTBranch(j)
branch.name = j.getString("name")
@@ -329,6 +329,12 @@ class ModelParser {
case 'post':
stage.post = parsePostStage(s)
break;
case 'tools':
stage.tools = parseTools(s)
break
case 'environment':
stage.environment = parseEnvironment(s)
break
default:
errorCollector.error(stage, "Unknown stage section '${name}'")
}
@@ -322,6 +322,12 @@
"post": {
"$ref": "#/definitions/notifications"
},
"tools": {
"$ref": "#/definitions/tools"
},
"environment": {
"$ref": "#/definitions/environment"
},
"branches": {
"type": "array",
"items": {
@@ -28,6 +28,7 @@ import hudson.FilePath
import hudson.Launcher
import hudson.model.Result
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Agent
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Environment
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Root
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Stage
import org.jenkinsci.plugins.pipeline.modeldefinition.model.Tools
@@ -76,7 +77,7 @@ public class ModelInterpreter implements Serializable {
}

// Entire build, including notifications, runs in the withEnv.
script.withEnv(root.getEnvVars()) {
withEnvBlock(root.getEnvVars()) {
// Stage execution and post-build actions run in try/catch blocks, so we still run post-build actions
// even if the build fails, and we still send notifications if the build and/or post-build actions fail.
// We save the caught error, if any, for throwing at the end of the build.
@@ -91,41 +92,46 @@ public class ModelInterpreter implements Serializable {
Stage thisStage = root.stages.getStages().get(i)

script.stage(thisStage.name) {
if (firstError == null) {
nodeOrDockerOrNone(thisStage.agent) {
try {
catchRequiredContextForNode(root.agent) {
setUpDelegate(thisStage.steps.closure).call()
}.call()
} catch (Exception e) {
script.echo "Error in stages execution: ${e.getMessage()}"
script.getProperty("currentBuild").result = Result.FAILURE
if (firstError == null) {
firstError = e
}
} finally {
// And finally, run the post stage steps.
List<Closure> postClosures = thisStage.satisfiedPostStageConditions(root, script.getProperty("currentBuild"))
withEnvBlock(thisStage.getEnvVars()) {
if (firstError == null) {
nodeOrDockerOrNone(thisStage.agent) {
toolsBlock(thisStage.agent ?: root.agent, thisStage.tools) {
try {
catchRequiredContextForNode(root.agent) {
setUpDelegate(thisStage.steps.closure).call()
}.call()
} catch (Exception e) {
script.echo "Error in stages execution: ${e.getMessage()}"
script.getProperty("currentBuild").result = Result.FAILURE
if (firstError == null) {
firstError = e
}
} finally {
// And finally, run the post stage steps.
List<Closure> postClosures = thisStage.satisfiedPostStageConditions(root, script.getProperty("currentBuild"))

catchRequiredContextForNode(thisStage.agent != null ? thisStage.agent : root.agent, false) {
if (postClosures.size() > 0) {
script.echo("Post stage") //TODO should this be a nested stage instead?
try {
for (int ni = 0; ni < postClosures.size(); ni++) {
setUpDelegate(postClosures.get(ni)).call()
}
} catch (Exception e) {
script.echo "Error in stage post: ${e.getMessage()}"
script.getProperty("currentBuild").result = Result.FAILURE
if (firstError == null) {
firstError = e
catchRequiredContextForNode(thisStage.agent != null ? thisStage.agent : root.agent, false) {
if (postClosures.size() > 0) {
script.echo("Post stage")
//TODO should this be a nested stage instead?
try {
for (int ni = 0; ni < postClosures.size(); ni++) {
setUpDelegate(postClosures.get(ni)).call()
}
} catch (Exception e) {
script.echo "Error in stage post: ${e.getMessage()}"
script.getProperty("currentBuild").result = Result.FAILURE
if (firstError == null) {
firstError = e
}
}
}
}
}.call()
}
}.call()
}
}.call()
}
}.call()
}
}.call()
}
}

@@ -170,7 +176,7 @@ public class ModelInterpreter implements Serializable {
firstError = e
}
}
}
}.call()
if (firstError != null) {
throw firstError
}
@@ -204,6 +210,21 @@ public class ModelInterpreter implements Serializable {
}
}

def withEnvBlock(List<String> envVars, Closure body) {
System.err.println("IN WITHENV BLOCK WITH ${envVars}")
if (envVars != null && !envVars.isEmpty()) {
return {
script.withEnv(envVars) {
body.call()
}
}
} else {
return {
body.call()
}
}
}

def toolsBlock(Agent agent, Tools tools, Closure body) {
// If there's no agent, don't install tools in the first place.
if (agent.hasAgent() && tools != null) {
@@ -118,6 +118,8 @@ public void setUp() throws Exception {
"simpleJobProperties",
"simpleTriggers",
"simpleParameters",
"toolsInStage",
"environmentInStage",
"stringsNeedingEscapeLogic"
);

@@ -54,6 +54,16 @@ public void simpleEnvironment() throws Exception {
j.assertLogContains("FOO is BAR", b);
}

@Test
public void environmentInStage() throws Exception {
prepRepoWithJenkinsfile("environmentInStage");

WorkflowRun b = getAndStartBuild();
j.assertBuildStatusSuccess(j.waitForCompletion(b));
j.assertLogContains("[Pipeline] { (foo)", b);
j.assertLogContains("FOO is BAR", b);
}

@Test
public void nonLiteralEnvironment() throws Exception {
prepRepoWithJenkinsfile("nonLiteralEnvironment");
@@ -60,6 +60,16 @@ public void simpleTools() throws Exception {
j.assertLogContains("Apache Maven 3.0.1", b);
}

@Test
public void toolsInStage() throws Exception {
prepRepoWithJenkinsfile("toolsInStage");

WorkflowRun b = getAndStartBuild();
j.assertBuildStatusSuccess(j.waitForCompletion(b));
j.assertLogContains("[Pipeline] { (foo)", b);
j.assertLogContains("Apache Maven 3.0.1", b);
}

@Test
public void buildPluginParentPOM() throws Exception {
prepRepoWithJenkinsfile("buildPluginParentPOM");
Oops, something went wrong.

0 comments on commit 7d3724c

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.