Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-26128] Added withEnv step.
Originally-Committed-As: cd30c066b3d21b735a6c76b6e43e555dc2930077
  • Loading branch information
jglick committed Mar 27, 2015
1 parent 2504017 commit 31b8af7
Show file tree
Hide file tree
Showing 3 changed files with 237 additions and 0 deletions.
@@ -0,0 +1,81 @@
/*
* The MIT License
*
* Copyright 2015 Jesse Glick.
*
* 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 org.jenkinsci.plugins.workflow.steps;

import org.jenkinsci.plugins.workflow.BuildWatcher;
import org.jenkinsci.plugins.workflow.JenkinsRuleExt;
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import org.junit.Test;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.runners.model.Statement;
import org.jvnet.hudson.test.RestartableJenkinsRule;

public class EnvStepTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public RestartableJenkinsRule story = new RestartableJenkinsRule();

// TODO test overriding of variables defined above, or in build, or in node

@Test public void restarting() {
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
WorkflowJob p = story.j.jenkins.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition(
"def show(which) {\n" +
" echo \"groovy ${which} ${env.TESTVAR}:\"\n" +
" sh \"echo shell ${which} \\$TESTVAR:\"\n" +
"}\n" +
"node {\n" +
" withEnv('TESTVAR=val') {\n" +
" show 'before'\n" +
" semaphore 'restarting'\n" +
" show 'after'\n" +
" }\n" +
" show 'outside'\n" +
"}"));
WorkflowRun b = p.scheduleBuild2(0).getStartCondition().get();
SemaphoreStep.waitForStart("restarting/1", b);
}
});
story.addStep(new Statement() {
@Override public void evaluate() throws Throwable {
SemaphoreStep.success("restarting/1", null);
WorkflowRun b = story.j.assertBuildStatusSuccess(JenkinsRuleExt.waitForCompletion(story.j.jenkins.getItemByFullName("p", WorkflowJob.class).getLastBuild()));
story.j.assertLogContains("groovy before val:", b);
story.j.assertLogContains("shell before val:", b);
story.j.assertLogContains("groovy after val:", b);
story.j.assertLogContains("shell after val:", b);
story.j.assertLogContains("groovy outside null:", b);
story.j.assertLogContains("shell outside :", b);
}
});
}

}
@@ -0,0 +1,113 @@
/*
* The MIT License
*
* Copyright 2015 Jesse Glick.
*
* 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 org.jenkinsci.plugins.workflow.steps;

import com.google.inject.Inject;
import hudson.EnvVars;
import hudson.Extension;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.kohsuke.stapler.DataBoundConstructor;

public class EnvStep extends AbstractStepImpl {

/**
* Environment variable overrides.
* The format is <pre>{@code VAR1=val1
* VAR2=val2}</pre> (pairs separated by newlines).
* Logically this should be a {@code Map<String,String>} but there is no standard control for that.
* Ditto for {@code List<String>} or {@code String[]}.
* Cf. JENKINS-26143 regarding ChoiceParameterDefinition.
*/
private final String overrides;

@DataBoundConstructor public EnvStep(String overrides) {
this.overrides = overrides;
}

public String getOverrides() {
return overrides;
}

public static class Execution extends AbstractStepExecutionImpl {

@Inject(optional=true) private transient EnvStep step;

@Override public boolean start() throws Exception {
getContext().newBodyInvoker().
withContext(new ExpanderImpl(step.overrides)).
withCallback(BodyExecutionCallback.wrap(getContext())).
start();
return false;
}

@Override public void stop(Throwable cause) throws Exception {
// should be no need to do anything special (but verify in JENKINS-26148)
}

}

private static final class ExpanderImpl extends EnvironmentExpander {
private final Map<String,String> overrides;
private ExpanderImpl(String overrides) {
this.overrides = new HashMap<String,String>();
for (String line : overrides.split("\r?\n")) {
line = line.trim();
if (!line.isEmpty()) {
int split = line.indexOf('=');
if (split == -1) {
continue; // ?
}
this.overrides.put(line.substring(0, split), line.substring(split + 1));
}
}
}
@Override public void expand(EnvVars env) throws IOException, InterruptedException {
env.overrideAll(overrides);
}
}

@Extension public static class DescriptorImpl extends AbstractStepDescriptorImpl {

public DescriptorImpl() {
super(Execution.class);
}

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

@Override public String getDisplayName() {
return "Set environment variables";
}

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

}

}
@@ -0,0 +1,43 @@
/*
* The MIT License
*
* Copyright 2015 Jesse Glick.
*
* 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 org.jenkinsci.plugins.workflow.steps;

import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.jvnet.hudson.test.JenkinsRule;

public class EnvStepTest {

@Rule public JenkinsRule r = new JenkinsRule();

// Uninteresting now, but would be if overrides were of a non-String type.
@Test public void configRoundTrip() throws Exception {
assertEquals("", new StepConfigTester(r).configRoundTrip(new EnvStep("")).getOverrides());
assertEquals("VAR1=val1", new StepConfigTester(r).configRoundTrip(new EnvStep("VAR1=val1")).getOverrides());
assertEquals("VAR1=val1\nVAR2=val2", new StepConfigTester(r).configRoundTrip(new EnvStep("VAR1=val1\nVAR2=val2")).getOverrides());
}

}

0 comments on commit 31b8af7

Please sign in to comment.