Skip to content

Commit

Permalink
Added ability to check for a string in output to fail the step
Browse files Browse the repository at this point in the history
Added a timeout to fail the step if it goes over
  • Loading branch information
JeremyMarshall committed Aug 28, 2013
1 parent 3ac09e1 commit f9072da
Showing 1 changed file with 76 additions and 9 deletions.
85 changes: 76 additions & 9 deletions src/main/java/hudson/plugins/xshell/XShellBuilder.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package hudson.plugins.xshell;

import java.io.IOException;
import java.io.PrintStream;
import java.io.*;
import java.util.Map;

import hudson.EnvVars;
Expand All @@ -13,13 +12,18 @@
import hudson.model.Descriptor;
import hudson.tasks.Builder;
import hudson.util.ArgumentListBuilder;
import hudson.Proc;
import hudson.model.StreamBuildListener;

import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.kohsuke.stapler.DataBoundConstructor;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* XShell Builder Plugin.
*
Expand All @@ -46,6 +50,17 @@ public final class XShellBuilder extends Builder {
*/
private final Boolean executeFromWorkingDir;

/**
* if output matches this then kill the step.
*/
private final String regexToKill;

/**
* amount of time to allocate to the step
*/
private final String timeAllocated;


public String getCommandLine() {
return commandLine;
}
Expand All @@ -54,10 +69,20 @@ public Boolean getExecuteFromWorkingDir() {
return executeFromWorkingDir;
}

@DataBoundConstructor
public XShellBuilder(final String commandLine, final Boolean executeFromWorkingDir) {
public String getRegexToKill() {
return regexToKill;
}

public String getTimeAllocated() {
return timeAllocated;
}

@DataBoundConstructor
public XShellBuilder(final String commandLine, final Boolean executeFromWorkingDir, final String regexToKill, final String timeAllocated) {
this.commandLine = Util.fixEmptyAndTrim(commandLine);
this.executeFromWorkingDir = executeFromWorkingDir;
this.executeFromWorkingDir = executeFromWorkingDir;
this.regexToKill = regexToKill;
this.timeAllocated = timeAllocated;
}

@Override
Expand All @@ -69,7 +94,9 @@ public Descriptor<Builder> getDescriptor() {
public boolean perform(final AbstractBuild<?, ?> build, final Launcher launcher, final BuildListener listener)
throws InterruptedException, IOException {

LOG.log(Level.FINE, "Unmodified command line: " + commandLine);
LOG.log(Level.FINE, "Unmodified command line: " + commandLine);
LOG.log(Level.FINE, "Regex to kill: " + regexToKill);
LOG.log(Level.FINE, "Time allocated before kill: " + timeAllocated);

String cmdLine = convertSeparator(commandLine, (launcher.isUnix() ? UNIX_SEP : WINDOWS_SEP));
LOG.log(Level.FINE, "File separators sanitized: " + cmdLine);
Expand Down Expand Up @@ -99,10 +126,50 @@ public boolean perform(final AbstractBuild<?, ?> build, final Launcher launcher,
LOG.log(Level.FINE, "Command line: " + args.toStringWithQuote());
LOG.log(Level.FINE, "Working directory: " + build.getWorkspace());

Pattern r = Pattern.compile(this.regexToKill);
Long timeAllowed;

try{
timeAllowed = Long.parseLong(this.timeAllocated);
}catch(Exception e){
timeAllowed = new Long(0);
}

try {
final int result = launcher.decorateFor(build.getBuiltOn()).launch()
.cmds(args).envs(env).stdout(listener).pwd(build.getWorkspace()).join();
return result == 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
StreamBuildListener sbl = new StreamBuildListener(baos);

final Proc child = launcher.decorateFor(build.getBuiltOn()).launch()
.cmds(args).envs(env).stdout(sbl).pwd(build.getWorkspace()).start();

Long startTime = System.currentTimeMillis();

while(child.isAlive()){

baos.flush();
String s = baos.toString();
baos.reset();

listener.getLogger().print(s);
listener.getLogger().flush();

if ((this.regexToKill.length() > 0) && (r.matcher(s).find())){
LOG.log(Level.FINEST, "Matched failure in log");
child.kill();
listener.getLogger().println("Matched <" + this.regexToKill +"> in output. Terminated");
}else if( (timeAllowed > 0) && ((System.currentTimeMillis() - startTime) / 1000) > timeAllowed){
LOG.log(Level.FINEST, "Timed out");
child.kill();
listener.getLogger().println("Timed out <" + this.timeAllocated +">. Terminated");
}else{
Thread.currentThread().sleep(2);
}
}

baos.flush();
listener.getLogger().print(baos.toString());
listener.getLogger().flush();
return child.join() == 0;
} catch (final IOException e) {
Util.displayIOException(e, listener);
final String errorMessage = Messages.XShell_ExecFailed();
Expand Down

0 comments on commit f9072da

Please sign in to comment.