package org.jvnet.hudson.plugins;
import hudson.Launcher;
import hudson.Extension;
import hudson.Util;
import hudson.model.AbstractBuild;
import hudson.util.FormValidation;
import hudson.model.BuildListener;
import hudson.model.AbstractProject;
import hudson.tasks.Builder;
import hudson.model.Result;
import hudson.tasks.BuildStepDescriptor;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.QueryParameter;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.Map;
/**
* Sample {@link Builder}.
*
* <p>
* When the user configures the project and enables this builder,
* {@link DescriptorImpl#newInstance(StaplerRequest)} is invoked
* and a new {@link MozmillBuilder} is created. The created
* instance is persisted to the project configuration XML by using
* XStream, so this allows you to use instance fields (like {@link #name})
* to remember the configuration.
*
* <p>
* When a build is performed, the {@link #perform(AbstractBuild, Launcher, BuildListener)} method
* will be invoked.
*/
public class MozmillBuilder extends Builder {
private final String tests;
private final String wrapper;
private final String logfile;
private final boolean showall;
private final boolean showerrors;
private final String port;
@DataBoundConstructor
public MozmillBuilder(String tests, String wrapper, String logfile, boolean showall, boolean showerrors, String port) {
this.tests = tests;
this.wrapper = wrapper;
this.logfile = logfile;
this.showall = showall;
this.showerrors = showerrors;
this.port = port;
}
/**
* We'll use this from the <tt>config.jelly</tt>.
*/
public String getTests() {
return tests;
}
public String getWrapper() {
return wrapper;
}
public String getLogfile() {
return logfile;
}
public boolean getShowall() {
return showall;
}
public boolean getShowerrors(){
return showerrors;
}
public String getPort(){
return port;
}
public String buildCommand(){
String command = "";
// use the wrapper script instead of mozmill if it exists
if (!this.getWrapper().isEmpty()){
command += this.getWrapper();
} else {
command += "mozmill";
}
// add arguments if they exist
if (!this.getLogfile().isEmpty()){
command += " --logfile " + this.getLogfile();
}
if (!this.getPort().isEmpty()){
command += " --port="+this.getPort();
}
// add the tests
command += " -t " + this.getTests();
if (this.getShowall()){
command += " --showall";
}
if (this.getShowerrors()){
command += " --show-errors";
}
return command;
}
@Override
public boolean perform(AbstractBuild<?,?> build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
// this is where you 'build' the project
// since this is a dummy, we just say 'hello world' and call that a build
int exitCode = 0;
if (this.getTests().equals("")){
listener.error("Mozmill cannot run without any tests specified.");
}
else {
Map<String,String> envVars = build.getEnvironment(listener);
envVars.putAll(build.getBuildVariables());
String cmd = this.buildCommand();
exitCode = launcher.launch().cmds(Util.tokenize(cmd)).envs(envVars).stdout(listener).pwd(build.getWorkspace()).join();
}
if (exitCode != 0){
build.setResult(Result.UNSTABLE);
}
return true;
}
// overrided for better type safety.
// if your plugin doesn't really define any property on Descriptor,
// you don't have to do this.
@Override
public DescriptorImpl getDescriptor() {
return (DescriptorImpl)super.getDescriptor();
}
/**
* Descriptor for {@link MozmillBuilder}. Used as a singleton.
* The class is marked as public so that it can be accessed from views.
*
* <p>
* See <tt>views/hudson/plugins/hello_world/HelloWorldBuilder/*.jelly</tt>
* for the actual HTML fragment for the configuration screen.
*/
@Extension // this marker indicates Hudson that this is an implementation of an extension point.
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
@Deprecated private transient boolean useFrench;
/**
* Performs on-the-fly validation of the form field 'name'.
*
* @param value
* This parameter receives the value that the user has typed.
* @return
* Indicates the outcome of the validation. This is sent to the browser.
*/
public FormValidation doCheckName(@QueryParameter String value) throws IOException, ServletException {
if(value.length()==0)
return FormValidation.error("Please set a name");
if(value.length()<4)
return FormValidation.warning("Isn't the name too short?");
return FormValidation.ok();
}
@Override
public boolean isApplicable(Class<? extends AbstractProject> aClass) {
// indicates that this builder can be used with all kinds of project types
return true;
}
/**
* This human readable name is used in the configuration screen.
*/
@Override
public String getDisplayName() {
return "Mozmill Test";
}
@Override
public boolean configure(StaplerRequest req, JSONObject o) throws FormException {
// to persist global configuration information,
// set that to properties and call save().
save();
return super.configure(req,o);
}
}
}