package hudson.plugins.seleniumGrails;
import hudson.tasks.Builder;
import hudson.model.Result;
import hudson.model.Descriptor;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Proc;
import org.kohsuke.stapler.DataBoundConstructor;
import java.util.Map;
import java.io.IOException;
import java.io.File;
public class SeleniumGrailsBuilder extends Builder {
private String browser;
private String grailsHome;
private String baseDir;
private String projectName;
private String deployString;
private String port;
private String resultPath;
public String getBrowser(){return browser;}
public void setBrowser(String browser){this.browser = browser;}
public String getGrailsHome(){return grailsHome;}
public void setGrailsHome(String grailsHome){this.grailsHome = grailsHome;}
public String getBaseDir(){return baseDir;}
public void setBaseDir(String baseDir){this.baseDir = baseDir;}
public String getProjectName(){return projectName;}
public void setProjectName(String projectName){this.projectName = projectName;}
public String getDeployString(){return deployString;}
public void setDeployString(String deployString){this.deployString = deployString;}
public String getPort(){return port;}
public void setPort(String port){this.port = port;}
public String getResultPath(){ return resultPath;}
public void setResultPath(String resultPath){this.resultPath = resultPath;}
@DataBoundConstructor
public SeleniumGrailsBuilder(String browser, String baseDir, String grailsHome, String projectName, String deployString, String port, String resultPath){
this.browser = browser;
this.baseDir = baseDir;
this.grailsHome = grailsHome;
this.projectName = projectName;
this.deployString = deployString;
this.port = port;
this.resultPath = resultPath;
}
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener)
throws IOException, InterruptedException {
if (browser == null || browser.length() == 0) {
listener.error("Build config : browser field is mandatory");
build.setResult(Result.FAILURE);
return false;
}
if(baseDir == null || baseDir.length() == 0){
listener.getLogger().println("Base Dir not set, defaulting to \".\"");
baseDir = ".";
}
if(grailsHome == null || grailsHome.length() == 0){
listener.error("Build config : GRAILS_HOME field is mandatory");
build.setResult(Result.FAILURE);
return false;
}
if(projectName == null || projectName.length() == 0){
listener.error("Build config : Project name field is mandatory");
build.setResult(Result.FAILURE);
return false;
}
if(deployString.length() == 0){
deployString = null;
}
if(port.length() == 0){
port = "64381"; //default port, chosen slightly at random
}
//Map<String, String> env = build.getEnvVars();
//env.put("GRAILS_HOME", grailsHome);
FilePath resultFile = null;
if(resultPath == null){
resultFile = new FilePath(new FilePath(build.getModuleRoot(), baseDir), "seleniumTestResult.xml");
} else {
resultFile = new FilePath(new File(resultPath));
}
listener.error("resultPath: "+resultPath);
if(resultFile.exists()) resultFile.delete();
Proc grailsServer = startGrails(deployString, grailsHome, port, build, launcher, listener);
//String url = "http://localhost:"+port+"/"+projectName+"/selenium/core/TestRunner.html?test=..%2F..%2Fselenium/suite&auto=on&close=on&resultsUrl=..%2FpostResults%3Ffile%3DseleniumTestResult.xml";
String url = "http://localhost:"+port+"/"+projectName+"/selenium/core/TestRunner.html?test=..%2F..%2Fselenium/suite&auto=on&close=on&resultsUrl=..%2FpostResults%3Ffile%3DseleniumTestResult.xml";
Proc browserProc = launcher.launch().cmds(browser, url).envs(build.getEnvironment(listener)).stdout(listener).pwd(new FilePath(build.getModuleRoot(), baseDir)).start();
while(!resultFile.exists()){ Thread.sleep(1000); } //wait for the result file to be written
browserProc.kill();
if(grailsServer != null) grailsServer.kill();
if(resultPath != null){
//put the results somewhere where the publisher can find it
System.out.println("moving "+resultPath+"to: "+new FilePath(new FilePath(build.getModuleRoot(), baseDir), "seleniumTestResult.xml"));
new FilePath(new File(resultPath)).copyTo(new FilePath(new FilePath(build.getModuleRoot(), baseDir), "seleniumTestResult.xml"));
}
return true;
}
private Proc startGrails(String deployString, String grailsHome, String port, AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
Map<String, String> env = build.getEnvironment(listener);
env.put("GRAILS_HOME", grailsHome);
if(deployString == null){
Proc grailsServer = launcher.launch().cmds(grailsHome + "/bin/grails", "-Dserver.port=" + port, "run-app").envs(env).stdout(listener).pwd(new FilePath(build.getModuleRoot(), baseDir)).start();
Thread.sleep(60000);//give hte grails server some time to start up
return grailsServer;
} else {
Proc buildWar = launcher.launch().cmds(grailsHome + "/bin/grails", "war").envs(env).stdout(listener).pwd(new FilePath(build.getModuleRoot(), baseDir)).start();
buildWar.join();
//XXX do we need to split deployString into cmd/args?
Proc deploy = launcher.launch().cmds(deployString).envs(env).stdout(listener).pwd(new FilePath(build.getModuleRoot(), baseDir)).start();
deploy.join();
return null;
}
}
@Extension
public static final class DescriptorImpl extends Descriptor<Builder> {
public DescriptorImpl() {
super(SeleniumGrailsBuilder.class);
}
public String getDisplayName() {
return "Selenium grails";
}
}
}