@Override public final boolean start(StepContext context) { try { FilePath ws = context.get(FilePath.class); assert ws != null : context.getClass() + " failed to provide a FilePath even though one was requested"; String remote = ws.getRemote(); String node = null; for (Computer c : Jenkins.getInstance().getComputers()) { if (c.getChannel() == ws.getChannel()) { node = c.getName(); break; } } if (node == null) { throw new IllegalStateException("no known node for " + ws); } register( context, task() .launch( context.get(EnvVars.class), ws, context.get(Launcher.class), context.get(TaskListener.class)), node, remote); } catch (Exception x) { context.onFailure(x); } return false; // TODO implement stop, however it is design (will need to call Controller.stop) }
/** Checks for progress or completion of the external task. */ CheckResult check() { try { Computer c = Jenkins.getInstance().getComputer(node); if (c == null) { LOGGER.log(Level.FINE, "no such computer {0}", node); return CheckResult.NO_CHANGE; } if (c.isOffline()) { LOGGER.log(Level.FINE, "{0} is offline", node); return CheckResult.NO_CHANGE; } FilePath ws = new FilePath(c.getChannel(), remote); if (!ws.isDirectory()) { error = new AbortException("missing workspace " + remote + " on " + node); return CheckResult.DONE; } TaskListener listener = context.get(TaskListener.class); boolean wrote = controller.writeLog(ws, listener.getLogger()); Integer exitCode = controller.exitStatus(ws); if (exitCode == null) { LOGGER.log(Level.FINE, "still running in {0} on {1}", new Object[] {remote, node}); return wrote ? CheckResult.UPDATED : CheckResult.NO_CHANGE; } else if (exitCode == 0) { result = exitCode; // TODO could add an option to have this be text output from command } else { error = new AbortException("script returned exit code " + exitCode); } controller.cleanup(ws); return CheckResult.DONE; } catch (IOException x) { error = x; } catch (InterruptedException x) { error = x; } return CheckResult.DONE; }