提交 3370ee3e 编写于 作者: H huybrechts

support for environment variables in native Maven builds

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@15927 71c3de6d-444a-0410-be80-ed276b4c234a
上级 7aea7415
......@@ -91,10 +91,15 @@ public class EnvVars extends TreeMap<String,String> {
put(key,value);
}
public void overrideAll(Map<String,String> all) {
/**
* Overrides all values in the map. See #override
* @return this
*/
public EnvVars overrideAll(Map<String,String> all) {
for (Map.Entry<String, String> e : all.entrySet()) {
override(e.getKey(),e.getValue());
}
return this;
}
/**
......@@ -129,9 +134,9 @@ public class EnvVars extends TreeMap<String,String> {
* @param channel
* Can be null, in which case the map indicating "N/A" will be returned.
*/
public static Map<String,String> getRemote(VirtualChannel channel) throws IOException, InterruptedException {
public static EnvVars getRemote(VirtualChannel channel) throws IOException, InterruptedException {
if(channel==null)
return Collections.singletonMap("N/A","N/A");
return new EnvVars("N/A","N/A");
return new EnvVars(channel.call(new GetEnvVars()));
}
......
......@@ -25,6 +25,7 @@ package hudson.maven;
import hudson.FilePath;
import hudson.Util;
import hudson.EnvVars;
import hudson.maven.agent.AbortException;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
......@@ -454,8 +455,8 @@ public class MavenBuild extends AbstractBuild<MavenModule,MavenBuild> {
if(debug)
listener.getLogger().println("Reporters="+reporters);
Map<String,String> envVars = getEnvVars();
EnvVars envVars = EnvVars.getRemote(launcher.getChannel()).overrideAll(getEnvVars());
ProcessCache.MavenProcess process = mavenProcessCache.get(launcher.getChannel(), listener,
new MavenProcessFactory(getParent().getParent(),launcher,envVars,null));
......
......@@ -470,6 +470,10 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
return rootPOM;
}
public void setRootPOM(String rootPOM) {
this.rootPOM = rootPOM;
}
public AbstractProject<?,?> asProject() {
return this;
}
......@@ -485,6 +489,10 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
return goals;
}
public void setGoals(String goals) {
this.goals = goals;
}
private List<String> getMavenArgument(String shortForm, String longForm) {
List<String> args = new ArrayList<String>();
boolean switchFound=false;
......@@ -549,6 +557,10 @@ public final class MavenModuleSet extends AbstractMavenProject<MavenModuleSet,Ma
return null;
}
public void setMaven(String mavenName) {
this.mavenName = mavenName;
}
/**
* Returns the {@link MavenModule}s that are in the queue.
*/
......
......@@ -27,6 +27,7 @@ import hudson.AbortException;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.EnvVars;
import hudson.FilePath.FileCallable;
import hudson.maven.MavenBuild.ProxyImpl2;
import hudson.maven.reporters.MavenFingerprinter;
......@@ -40,6 +41,7 @@ import hudson.model.Fingerprint;
import hudson.model.Hudson;
import hudson.model.ParametersAction;
import hudson.model.Result;
import hudson.model.Computer;
import hudson.model.Cause.UpstreamCause;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
......@@ -309,7 +311,8 @@ public final class MavenModuleSetBuild extends AbstractBuild<MavenModuleSet,Mave
protected Result doRun(final BuildListener listener) throws Exception {
PrintStream logger = listener.getLogger();
try {
parsePoms(listener, logger);
EnvVars envVars = EnvVars.getRemote(launcher.getChannel());
parsePoms(listener, logger, envVars);
if(!project.isAggregatorStyleBuild()) {
// start module builds
......@@ -341,18 +344,20 @@ public final class MavenModuleSetBuild extends AbstractBuild<MavenModuleSet,Mave
for (MavenModule m : project.sortedActiveModules)
proxies.put(m.getModuleName(),m.newBuild().new ProxyImpl2(MavenModuleSetBuild.this,slistener));
envVars.overrideAll(getEnvVars());
// run the complete build here
// figure out the root POM location.
// choice of module root ('ws' in this method) is somewhat arbitrary
// when multiple CVS/SVN modules are checked out, so also check
// the path against the workspace root if that seems like what the user meant (see issue #1293)
FilePath pom = project.getModuleRoot().child(project.getRootPOM());
FilePath parentLoc = project.getWorkspace().child(project.getRootPOM());
String rootPOM = project.getRootPOM();
FilePath pom = project.getModuleRoot().child(rootPOM);
FilePath parentLoc = project.getWorkspace().child(rootPOM);
if(!pom.exists() && parentLoc.exists())
pom = parentLoc;
Map<String,String> envVars = getEnvVars();
ProcessCache.MavenProcess process = MavenBuild.mavenProcessCache.get(launcher.getChannel(), slistener,
new MavenProcessFactory(project,launcher,envVars,pom.getParent()));
......@@ -360,7 +365,7 @@ public final class MavenModuleSetBuild extends AbstractBuild<MavenModuleSet,Mave
margs.add("-B").add("-f", pom.getRemote());
if(project.usesPrivateRepository())
margs.add("-Dmaven.repo.local="+project.getWorkspace().child(".repository"));
margs.addTokenized(project.getGoals());
margs.addTokenized(envVars.expand(project.getGoals()));
Builder builder = new Builder(slistener, proxies, project.sortedActiveModules, margs.toList(), envVars);
MavenProbeAction mpa=null;
......@@ -407,13 +412,14 @@ public final class MavenModuleSetBuild extends AbstractBuild<MavenModuleSet,Mave
}
}
private void parsePoms(BuildListener listener, PrintStream logger) throws IOException, InterruptedException {
private void parsePoms(BuildListener listener, PrintStream logger, EnvVars envVars) throws IOException, InterruptedException {
logger.println("Parsing POMs");
MavenInstallation mvn = project.getMaven();
if(mvn==null) {
logger.println("A Maven configuration needs to be associated with this project. Please reconfigure this project");
throw new AbortException();
}
mvn = mvn.forEnvironment(envVars).forNode(Computer.currentComputer().getNode());
List<PomInfo> poms;
try {
......
......@@ -27,6 +27,7 @@ import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import hudson.AbortException;
import hudson.EnvVars;
import static hudson.Util.fixNull;
import hudson.maven.agent.Main;
import hudson.model.BuildListener;
......@@ -81,7 +82,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
* Environment variables to be set to the maven process.
* The same variables are exposed to the system property as well.
*/
private final Map<String,String> envVars;
private final EnvVars envVars;
/**
* Optional working directory. Because of the process reuse, we can't always guarantee
......@@ -93,7 +94,7 @@ final class MavenProcessFactory implements ProcessCache.Factory {
*/
private final FilePath workDir;
MavenProcessFactory(MavenModuleSet mms, Launcher launcher, Map<String, String> envVars, FilePath workDir) {
MavenProcessFactory(MavenModuleSet mms, Launcher launcher, EnvVars envVars, FilePath workDir) {
this.mms = mms;
this.launcher = launcher;
this.envVars = envVars;
......@@ -281,11 +282,12 @@ final class MavenProcessFactory implements ProcessCache.Factory {
slaveRoot = getCurrentNode().getRootPath();
ArgumentListBuilder args = new ArgumentListBuilder();
JDK jdk = mms.getJDK();
if(jdk==null)
JDK jdk = getJava();
if(jdk==null) {
args.add("java");
else
args.add(jdk.getJavaHome()+"/bin/java");
} else {
args.add(jdk.getJavaHome()+"/bin/java"); // use JDK.getExecutable() here ?
}
if(debugPort!=0)
args.add("-Xrunjdwp:transport=dt_socket,server=y,address="+debugPort);
......@@ -320,22 +322,20 @@ final class MavenProcessFactory implements ProcessCache.Factory {
}
public String getMavenOpts() {
String opts = mms.getMavenOpts();
if (opts == null)
return null;
for (String key : envVars.keySet())
opts = opts.replace("${" + key + "}", envVars.get(key));
return opts;
return envVars.expand(mms.getMavenOpts());
}
public MavenInstallation getMavenInstallation() {
return mms.getMaven();
MavenInstallation mi = mms.getMaven();
if (mi != null) mi = mi.forNode(getCurrentNode()).forEnvironment(envVars);
return mi;
}
public JDK getJava() {
return mms.getJDK();
JDK jdk = mms.getJDK();
if (jdk != null) jdk = jdk.forNode(getCurrentNode()).forEnvironment(envVars);
return jdk;
}
/**
......
......@@ -27,6 +27,7 @@ import hudson.util.StreamTaskListener;
import hudson.util.NullStream;
import hudson.Launcher;
import hudson.Extension;
import hudson.EnvVars;
import hudson.slaves.NodeSpecific;
import hudson.tools.ToolInstallation;
import hudson.tools.ToolDescriptor;
......@@ -42,7 +43,7 @@ import java.util.List;
*
* @author Kohsuke Kawaguchi
*/
public final class JDK extends ToolInstallation implements NodeSpecific<JDK> {
public final class JDK extends ToolInstallation implements NodeSpecific<JDK>, EnvironmentSpecific<JDK> {
@Deprecated // kept for backward compatibility - use getHome() instead
private String javaHome;
......@@ -104,6 +105,10 @@ public final class JDK extends ToolInstallation implements NodeSpecific<JDK> {
return new JDK(getName(),ToolLocationNodeProperty.getToolHome(node, this));
}
public JDK forEnvironment(EnvVars environment) {
return new JDK(getName(), environment.expand(getHome()));
}
/**
* Checks if "java" is in PATH on the given node.
*
......
......@@ -209,13 +209,11 @@ public class Maven extends Builder {
ArgumentListBuilder args = new ArgumentListBuilder();
MavenInstallation mi = getMaven();
if (mi != null) {
mi = mi.forNode(Computer.currentComputer().getNode());
}
if(mi==null) {
String execName = proj.getWorkspace().act(new DecideDefaultMavenCommand(normalizedTarget));
args.add(execName);
} else {
mi = mi.forNode(Computer.currentComputer().getNode());
mi = mi.forEnvironment(env);
String exec = mi.getExecutable(launcher);
if(exec==null) {
......
......@@ -42,7 +42,8 @@ public class MatrixProjectTest extends HudsonTestCase {
*/
public void testBuildAxisInAnt() throws Exception {
MatrixProject p = createMatrixProject();
p.getBuildersList().add(new Ant("-Dprop=${db} test",null,null,null,null));
Ant.AntInstallation ant = configureDefaultAnt();
p.getBuildersList().add(new Ant("-Dprop=${db} test",ant.getName(),null,null,null));
// we need a dummy build script that echos back our property
p.setScm(new SingleFileSCM("build.xml","<project default='test'><target name='test'><echo>assertion ${prop}=${db}</echo></target></project>"));
......
package hudson.tasks;
import hudson.EnvVars;
import hudson.maven.MavenModuleSet;
import hudson.maven.MavenModuleSetBuild;
import hudson.model.FreeStyleBuild;
import hudson.model.FreeStyleProject;
import hudson.model.JDK;
......@@ -37,18 +39,14 @@ public class EnvVarsInConfigTasksTest extends HudsonTestCase {
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(varMaven);
// Ant with a variable in its path
// TODO: create HudsonTestCase.configureDefaultAnt()
String guessedAntHome = guessAntHome();
if (guessedAntHome != null) {
AntInstallation antInstallation = new AntInstallation("varAnt",
withVariable(guessedAntHome));
hudson.getDescriptorByType(Ant.DescriptorImpl.class).setInstallations(antInstallation);
}
AntInstallation ant = configureDefaultAnt();
AntInstallation antInstallation = new AntInstallation("varAnt",
withVariable(ant.getHome()));
hudson.getDescriptorByType(Ant.DescriptorImpl.class).setInstallations(antInstallation);
// createSlaves
// create slaves
EnvVars additionalEnv = new EnvVars(DUMMY_LOCATION_VARNAME, "");
slaveEnv = createSlave(new Label("slaveEnv"), additionalEnv);
slaveRegular = createSlave(new Label("slaveRegular"));
}
......@@ -172,18 +170,35 @@ public class EnvVarsInConfigTasksTest extends HudsonTestCase {
assertFalse(buildLogEnv.contains(DUMMY_LOCATION_VARNAME));
}
public static String guessAntHome() {
String antHome = EnvVars.masterEnvVars.get("ANT_HOME");
if (antHome != null)
return antHome;
public void testNativeMavenOnSlave() throws Exception {
MavenModuleSet project = createMavenProject();
project.setJDK(hudson.getJDK("varJDK"));
project.setScm(new ExtractResourceSCM(getClass().getResource(
"/simple-projects.zip")));
// will break if PATH variable is not found (e.g. case sensitivity)
String[] sysPath = EnvVars.masterEnvVars.get("PATH").split(
File.pathSeparator);
for (String p : sysPath)
if (new File(p, "ant").isFile() || new File(p, "ant.bat").isFile())
return new File(p).getParent();
project.setMaven("varMaven");
project.setGoals("clean${" + DUMMY_LOCATION_VARNAME + "}");
throw new RuntimeException("cannot find Apache Ant");
}
// test the regular slave - variable not expanded
project.setAssignedLabel(slaveRegular.getSelfLabel());
MavenModuleSetBuild build = project.scheduleBuild2(0).get();
System.out.println(build.getDisplayName() + " completed");
assertBuildStatus(Result.FAILURE, build);
String buildLogRegular = build.getLog();
System.out.println(buildLogRegular);
// test the slave with prepared environment
project.setAssignedLabel(slaveEnv.getSelfLabel());
build = project.scheduleBuild2(0).get();
System.out.println(build.getDisplayName() + " completed");
assertBuildStatusSuccess(build);
// Check variable was expanded
String buildLogEnv = build.getLog();
System.out.println(buildLogEnv);
assertFalse(buildLogEnv.contains(DUMMY_LOCATION_VARNAME));
}
}
......@@ -30,11 +30,25 @@ import hudson.model.JDK;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Result;
import hudson.model.StringParameterDefinition;
import hudson.model.AbstractProject;
import hudson.model.Job;
import hudson.model.AbstractBuild;
import hudson.model.Run;
import hudson.model.Cause;
import hudson.model.Action;
import hudson.model.ParametersAction;
import hudson.model.StringParameterValue;
import hudson.model.Cause.LegacyCodeCause;
import hudson.model.listeners.RunListener;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.EnvironmentVariablesNodeProperty.Entry;
import hudson.tasks.Maven.MavenInstallation;
import hudson.remoting.AsyncFutureImpl;
import java.util.Collections;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import junit.framework.Assert;
......@@ -47,92 +61,90 @@ import com.gargoylesoftware.htmlunit.html.HtmlPage;
* @author Kohsuke Kawaguchi
*/
public class MavenTest extends HudsonTestCase {
/**
* Tests the round-tripping of the configuration.
*/
public void testConfigRoundtrip() throws Exception {
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(); // reset
FreeStyleProject p = createFreeStyleProject();
p.getBuildersList().add(new Maven("a", null, "b.pom", "c=d", "-e"));
WebClient webClient = new WebClient();
HtmlPage page = webClient.getPage(p, "configure");
HtmlForm form = page.getFormByName("config");
submit(form);
Maven m = p.getBuildersList().get(Maven.class);
assertNotNull(m);
assertEquals("a", m.targets);
assertNull("found " + m.mavenName, m.mavenName);
assertEquals("b.pom", m.pom);
assertEquals("c=d", m.properties);
assertEquals("-e", m.jvmOptions);
}
public void testWithNodeProperty() throws Exception {
MavenInstallation maven = configureDefaultMaven();
String mavenHome = maven.getMavenHome();
String mavenHomeVar = "${VAR_MAVEN}" + mavenHome.substring(3);
String mavenVar = mavenHome.substring(0, 3);
MavenInstallation varMaven = new MavenInstallation("varMaven",
mavenHomeVar);
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven);
JDK jdk = hudson.getJDK("default");
String javaHome = jdk.getJavaHome();
String javaHomeVar = "${VAR_JAVA}" + javaHome.substring(3);
String javaVar = javaHome.substring(0, 3);
JDK varJDK = new JDK("varJDK", javaHomeVar);
hudson.getJDKs().add(varJDK);
Hudson.getInstance().getNodeProperties().replaceBy(
Collections.singleton(new EnvironmentVariablesNodeProperty(
new Entry("VAR_MAVEN", mavenVar), new Entry("VAR_JAVA",
javaVar))));
FreeStyleProject project = createFreeStyleProject();
project.getBuildersList().add(new Maven("--help", varMaven.getName()));
project.setJDK(varJDK);
Build<?,?> build = project.scheduleBuild2(0).get();
Assert.assertEquals(Result.SUCCESS, build.getResult());
}
public void testWithParameter() throws Exception {
MavenInstallation maven = configureDefaultMaven();
String mavenHome = maven.getMavenHome();
String mavenHomeVar = "${VAR_MAVEN}" + mavenHome.substring(3);
String mavenVar = mavenHome.substring(0, 3);
MavenInstallation varMaven = new MavenInstallation("varMaven",
mavenHomeVar);
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven);
JDK jdk = hudson.getJDK("default");
String javaHome = jdk.getJavaHome();
String javaHomeVar = "${VAR_JAVA}" + javaHome.substring(3);
String javaVar = javaHome.substring(0, 3);
JDK varJDK = new JDK("varJDK", javaHomeVar);
hudson.getJDKs().add(varJDK);
FreeStyleProject project = createFreeStyleProject();
project.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("VAR_MAVEN", "XXX"),
new StringParameterDefinition("VAR_JAVA", "XXX")));
project.getBuildersList().add(new Maven("--help", varMaven.getName()));
project.setJDK(varJDK);
WebClient webClient = new WebClient();
webClient.getPage(project, "buildWithParameters?VAR_MAVEN=" + mavenVar
+ "&VAR_JAVA=" + javaVar);
Thread.sleep(2000);
Build<?,?> build = project.getLastBuild();
Assert.assertEquals(Result.SUCCESS, build.getResult());
}
/**
* Tests the round-tripping of the configuration.
*/
public void testConfigRoundtrip() throws Exception {
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(); // reset
FreeStyleProject p = createFreeStyleProject();
p.getBuildersList().add(new Maven("a", null, "b.pom", "c=d", "-e"));
WebClient webClient = new WebClient();
HtmlPage page = webClient.getPage(p, "configure");
HtmlForm form = page.getFormByName("config");
submit(form);
Maven m = p.getBuildersList().get(Maven.class);
assertNotNull(m);
assertEquals("a", m.targets);
assertNull("found " + m.mavenName, m.mavenName);
assertEquals("b.pom", m.pom);
assertEquals("c=d", m.properties);
assertEquals("-e", m.jvmOptions);
}
public void testWithNodeProperty() throws Exception {
MavenInstallation maven = configureDefaultMaven();
String mavenHome = maven.getMavenHome();
String mavenHomeVar = "${VAR_MAVEN}" + mavenHome.substring(3);
String mavenVar = mavenHome.substring(0, 3);
MavenInstallation varMaven = new MavenInstallation("varMaven",
mavenHomeVar);
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven);
JDK jdk = hudson.getJDK("default");
String javaHome = jdk.getJavaHome();
String javaHomeVar = "${VAR_JAVA}" + javaHome.substring(3);
String javaVar = javaHome.substring(0, 3);
JDK varJDK = new JDK("varJDK", javaHomeVar);
hudson.getJDKs().add(varJDK);
Hudson.getInstance().getNodeProperties().replaceBy(
Collections.singleton(new EnvironmentVariablesNodeProperty(
new Entry("VAR_MAVEN", mavenVar), new Entry("VAR_JAVA",
javaVar))));
FreeStyleProject project = createFreeStyleProject();
project.getBuildersList().add(new Maven("--help", varMaven.getName()));
project.setJDK(varJDK);
Build<?, ?> build = project.scheduleBuild2(0).get();
Assert.assertEquals(Result.SUCCESS, build.getResult());
}
public void testWithParameter() throws Exception {
MavenInstallation maven = configureDefaultMaven();
String mavenHome = maven.getMavenHome();
String mavenHomeVar = "${VAR_MAVEN}" + mavenHome.substring(3);
String mavenVar = mavenHome.substring(0, 3);
MavenInstallation varMaven = new MavenInstallation("varMaven",
mavenHomeVar);
hudson.getDescriptorByType(Maven.DescriptorImpl.class).setInstallations(maven, varMaven);
JDK jdk = hudson.getJDK("default");
String javaHome = jdk.getJavaHome();
String javaHomeVar = "${VAR_JAVA}" + javaHome.substring(3);
String javaVar = javaHome.substring(0, 3);
JDK varJDK = new JDK("varJDK", javaHomeVar);
hudson.getJDKs().add(varJDK);
FreeStyleProject project = createFreeStyleProject();
project.addProperty(new ParametersDefinitionProperty(
new StringParameterDefinition("VAR_MAVEN", "XXX"),
new StringParameterDefinition("VAR_JAVA", "XXX")));
project.getBuildersList().add(new Maven("--help", varMaven.getName()));
project.setJDK(varJDK);
Build build = project.scheduleBuild2(0, new LegacyCodeCause(),
new ParametersAction(
new StringParameterValue("VAR_MAVEN", mavenVar),
new StringParameterValue("VAR_JAVA", javaVar))).get();
assertBuildStatusSuccess(build);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册