diff --git a/src/main/java/hudson/cli/SetExternalBuildResultCommand.java b/src/main/java/hudson/cli/SetExternalBuildResultCommand.java new file mode 100644 index 0000000..66c78fb --- /dev/null +++ b/src/main/java/hudson/cli/SetExternalBuildResultCommand.java @@ -0,0 +1,82 @@ +package hudson.cli; + +import jenkins.model.Jenkins; +import hudson.Extension; +import hudson.model.ExternalJob; +import hudson.model.ExternalRun; +import hudson.model.Run; +import hudson.model.Item; +import hudson.remoting.Callable; +import org.apache.commons.io.IOUtils; +import org.kohsuke.args4j.Option; + +import java.io.IOException; +import java.io.Serializable; +import java.io.InputStream; + +/** + * Set build result for external monitor job. + * + * @author David Ostrovsky + */ +@Extension +public class SetExternalBuildResultCommand extends CLICommand implements Serializable { + + @Override + public String getShortDescription() { + return "Set external monitor job result."; + } + + @Option(name="--job", aliases={"-j"}, metaVar="JOB", usage="Name of the external monitor job", required=true) + public transient ExternalJob job; + + @Option(name="--display", aliases={"-n"}, metaVar="DISPLAY", usage="Display name of the job", required=false) + public transient String displayName; + + @Option(name="--result", aliases={"-r"}, metaVar="RESULT", usage="0: success, 1: fail", required=true) + public transient int result; + + @Option(name="--duration", aliases={"-d"}, metaVar="DURATION", usage="Number of milli-seconds it took to run this build", required=false) + public transient long duration = 0; + + @Option(name="--log", aliases={"-l"}, metaVar="-|LOG", usage="Log to be set. '-' to read from stdin (gzipped).", required=true) + public String log; + + @Option(name="--dump-build-number", aliases={"-b"}, metaVar="BUILD", usage="Log the produced build number to the standard output", required=false) + public boolean dumpBuildNumber; + + /** + * Entry point to the SetExternalBuildResultCommand command. + * + *

+ * Schedule an external build, put passed build result. + * If log is '-' then gzipped stream is expected on stdin, otherwise it is raw string + * (not BASE64 encoded). + * + * If -dump-build-number is set, the new created build number dumped to the stdout + * + * @return + * 0: success. + */ + protected int run() throws Exception { + ExternalRun run = job.newBuild(); + run.checkPermission(Run.UPDATE); + + if ("-".equals(log)) { + run.acceptRemoteSubmission(result, duration, stdin); + } else { + run.acceptRemoteSubmission(result, duration, log); + } + + if (displayName != null) { + run.setDisplayName(displayName); + } + + if (dumpBuildNumber) { + System.out.format("%d\n", run.getNumber()); + } + + return 0; + } + +} diff --git a/src/main/java/hudson/model/ExternalRun.java b/src/main/java/hudson/model/ExternalRun.java index b549383..e052c8c 100644 --- a/src/main/java/hudson/model/ExternalRun.java +++ b/src/main/java/hudson/model/ExternalRun.java @@ -34,7 +34,9 @@ import java.io.File; import java.io.IOException; import java.io.PrintStream; +import java.io.InputStream; import java.io.Reader; +import java.util.zip.GZIPInputStream; import static javax.xml.stream.XMLStreamConstants.*; @@ -168,4 +170,53 @@ public void cleanUp(BuildListener listener) { } } + public void acceptRemoteSubmission(final int result, final long duration, final InputStream stream) throws IOException { + execute(new RunExecution() { + public Result run(BuildListener listener) throws Exception { + PrintStream logger = new PrintStream(listener.getLogger()); + final int sChunk = 8192; + GZIPInputStream zipin = new GZIPInputStream(stream); + byte[] buffer = new byte[sChunk]; + int length; + while ((length = zipin.read(buffer, 0, sChunk)) != -1) + logger.write(buffer, 0, length); + Result r = result==0?Result.SUCCESS:Result.FAILURE; + return r; + } + + public void post(BuildListener listener) { + // do nothing + } + + public void cleanUp(BuildListener listener) { + // do nothing + } + }); + + super.duration = duration; + save(); + } + + public void acceptRemoteSubmission(final int result, final long duration, final String log) throws IOException { + execute(new RunExecution() { + public Result run(BuildListener listener) throws Exception { + PrintStream logger = new PrintStream(listener.getLogger()); + logger.print(log); + Result r = result==0?Result.SUCCESS:Result.FAILURE; + return r; + } + + public void post(BuildListener listener) { + // do nothing + } + + public void cleanUp(BuildListener listener) { + // do nothing + } + }); + + super.duration = duration; + save(); + } + }