use of org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint in project workflow-cps-plugin by jenkinsci.
the class CpsFlowDefinition method create.
@Override
@SuppressWarnings("deprecation")
public CpsFlowExecution create(FlowExecutionOwner owner, TaskListener listener, List<? extends Action> actions) throws IOException {
for (Action a : actions) {
if (a instanceof CpsFlowFactoryAction) {
CpsFlowFactoryAction fa = (CpsFlowFactoryAction) a;
return fa.create(this, owner, actions);
} else if (a instanceof CpsFlowFactoryAction2) {
return ((CpsFlowFactoryAction2) a).create(this, owner, actions);
}
}
Queue.Executable exec = owner.getExecutable();
FlowDurabilityHint hint = (exec instanceof Run) ? DurabilityHintProvider.suggestedFor(((Run) exec).getParent()) : GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint();
return new CpsFlowExecution(sandbox ? script : ScriptApproval.get().using(script, GroovyLanguage.get()), sandbox, owner, hint);
}
use of org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint in project workflow-cps-plugin by jenkinsci.
the class CpsScmFlowDefinition method create.
@Override
public CpsFlowExecution create(FlowExecutionOwner owner, TaskListener listener, List<? extends Action> actions) throws Exception {
for (Action a : actions) {
if (a instanceof CpsFlowFactoryAction2) {
return ((CpsFlowFactoryAction2) a).create(this, owner, actions);
}
}
Queue.Executable _build = owner.getExecutable();
if (!(_build instanceof Run)) {
throw new IOException("can only check out SCM into a Run");
}
Run<?, ?> build = (Run<?, ?>) _build;
if (isLightweight()) {
try (SCMFileSystem fs = SCMFileSystem.of(build.getParent(), scm)) {
if (fs != null) {
String script = fs.child(scriptPath).contentAsString();
listener.getLogger().println("Obtained " + scriptPath + " from " + scm.getKey());
Queue.Executable exec = owner.getExecutable();
FlowDurabilityHint hint = (exec instanceof Item) ? DurabilityHintProvider.suggestedFor((Item) exec) : GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint();
return new CpsFlowExecution(script, true, owner, hint);
} else {
listener.getLogger().println("Lightweight checkout support not available, falling back to full checkout.");
}
}
}
FilePath dir;
Node node = Jenkins.getActiveInstance();
if (build.getParent() instanceof TopLevelItem) {
FilePath baseWorkspace = node.getWorkspaceFor((TopLevelItem) build.getParent());
if (baseWorkspace == null) {
throw new IOException(node.getDisplayName() + " may be offline");
}
dir = getFilePathWithSuffix(baseWorkspace);
} else {
// should not happen, but just in case:
dir = new FilePath(owner.getRootDir());
}
listener.getLogger().println("Checking out " + scm.getKey() + " into " + dir + " to read " + scriptPath);
String script = null;
Computer computer = node.toComputer();
if (computer == null) {
throw new IOException(node.getDisplayName() + " may be offline");
}
SCMStep delegate = new GenericSCMStep(scm);
delegate.setPoll(true);
delegate.setChangelog(true);
FilePath acquiredDir;
try (WorkspaceList.Lease lease = computer.getWorkspaceList().acquire(dir)) {
for (int retryCount = Jenkins.getInstance().getScmCheckoutRetryCount(); retryCount >= 0; retryCount--) {
try {
delegate.checkout(build, dir, listener, node.createLauncher(listener));
break;
} catch (AbortException e) {
// If so, just skip echoing it.
if (e.getMessage() != null) {
listener.error(e.getMessage());
}
} catch (InterruptedIOException e) {
throw e;
} catch (IOException e) {
// checkout error not yet reported
// TODO 2.43+ use Functions.printStackTrace
listener.error("Checkout failed").println(Functions.printThrowable(e).trim());
}
if (// all attempts failed
retryCount == 0)
throw new AbortException("Maximum checkout retry attempts reached, aborting");
listener.getLogger().println("Retrying after 10 seconds");
Thread.sleep(10000);
}
FilePath scriptFile = dir.child(scriptPath);
if (!scriptFile.absolutize().getRemote().replace('\\', '/').startsWith(dir.absolutize().getRemote().replace('\\', '/') + '/')) {
// TODO JENKINS-26838
throw new IOException(scriptFile + " is not inside " + dir);
}
if (!scriptFile.exists()) {
throw new AbortException(scriptFile + " not found");
}
script = scriptFile.readToString();
acquiredDir = lease.path;
}
Queue.Executable queueExec = owner.getExecutable();
FlowDurabilityHint hint = (queueExec instanceof Run) ? DurabilityHintProvider.suggestedFor(((Run) queueExec).getParent()) : GlobalDefaultFlowDurabilityLevel.getDefaultDurabilityHint();
CpsFlowExecution exec = new CpsFlowExecution(script, true, owner, hint);
exec.flowStartNodeActions.add(new WorkspaceActionImpl(acquiredDir, null));
return exec;
}
use of org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint in project workflow-cps-plugin by jenkinsci.
the class CpsFlowExecution method createStorage.
private TimingFlowNodeStorage createStorage() throws IOException {
FlowNodeStorage wrappedStorage;
FlowDurabilityHint hint = getDurabilityHint();
wrappedStorage = (hint.isPersistWithEveryStep()) ? new SimpleXStreamFlowNodeStorage(this, getStorageDir()) : new BulkFlowNodeStorage(this, getStorageDir());
return new TimingFlowNodeStorage(wrappedStorage);
}
use of org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method fuzzTimingDurable.
/**
* Test interrupting build by randomly dying at unpredictable times.
*/
@Test
// Too long to run as part of main suite
@Ignore
@TimedRepeatRule.RepeatForTime(repeatMillis = 170_000)
public void fuzzTimingDurable() throws Exception {
final String jobName = "NestedParallelDurableJob";
final String[] logStart = new String[1];
final List<FlowNode> nodesOut = new ArrayList<FlowNode>();
// Create thread that eventually interrupts Jenkins with a hard shutdown at a random time interval
story.addStepWithDirtyShutdown(new Statement() {
@Override
public void evaluate() throws Throwable {
Jenkins jenkins = story.j.jenkins;
WorkflowJob job = jenkins.getItemByFullName(jobName, WorkflowJob.class);
if (job == null) {
// Job may already have been created
job = jenkins.createProject(WorkflowJob.class, jobName);
FlowDurabilityHint hint = FlowDurabilityHint.MAX_SURVIVABILITY;
TestDurabilityHintProvider provider = Jenkins.getInstance().getExtensionList(TestDurabilityHintProvider.class).get(0);
provider.registerHint(job.getFullName(), hint);
job.setDefinition(new CpsFlowDefinition("echo 'first'\n" + "def steps = [:]\n" + "steps['1'] = {\n" + " echo 'do 1 stuff'\n" + "}\n" + "steps['2'] = {\n" + " echo '2a'\n" + " echo '2b'\n" + " def nested = [:]\n" + " nested['2-1'] = {\n" + " echo 'do 2-1'\n" + " } \n" + " nested['2-2'] = {\n" + " sleep 1\n" + " echo '2 section 2'\n" + " }\n" + " parallel nested\n" + "}\n" + "parallel steps\n" + "echo 'final'"));
}
story.j.buildAndAssertSuccess(job);
long millisDuration = job.getLastBuild().getDuration();
int time = new Random().nextInt((int) millisDuration);
WorkflowRun run = job.scheduleBuild2(0).getStartCondition().get();
Thread.sleep(time);
logStart[0] = JenkinsRule.getLog(run);
nodesOut.clear();
nodesOut.addAll(new DepthFirstScanner().allNodes(run.getExecution()));
nodesOut.sort(FlowScanningUtils.ID_ORDER_COMPARATOR);
}
});
story.addStep(new Statement() {
@Override
public void evaluate() throws Throwable {
WorkflowRun run = story.j.jenkins.getItemByFullName(jobName, WorkflowJob.class).getLastBuild();
if (run.isBuilding()) {
story.j.waitForCompletion(run);
Assert.assertEquals(Result.SUCCESS, run.getResult());
} else {
verifyCompletedCleanly(story.j.jenkins, run);
}
assertIncludesNodes(nodesOut, run);
story.j.assertLogContains(logStart[0], run);
}
});
}
use of org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint in project workflow-cps-plugin by jenkinsci.
the class FlowDurabilityTest method testCompleteAndLoadBuilds.
/**
* Confirm that for ALL implementations, a run can complete and be loaded if you restart after completion.
*/
@Test
public void testCompleteAndLoadBuilds() throws Exception {
final FlowDurabilityHint[] durabilityHints = FlowDurabilityHint.values();
final WorkflowJob[] jobs = new WorkflowJob[durabilityHints.length];
final String[] logOutput = new String[durabilityHints.length];
// Create and run jobs for each of the durability hints
story.addStep(new Statement() {
@Override
public void evaluate() throws Throwable {
int i = 1;
for (FlowDurabilityHint hint : durabilityHints) {
try {
WorkflowRun run = createAndRunBasicJob(story.j.jenkins, "basicJob-" + hint.toString(), hint, i);
jobs[i - 1] = run.getParent();
SemaphoreStep.success("halt/" + i++, Result.SUCCESS);
story.j.waitForCompletion(run);
story.j.assertBuildStatus(Result.SUCCESS, run);
logOutput[i - 2] = JenkinsRule.getLog(run);
assertHasTimingAction(run.getExecution());
} catch (AssertionError ae) {
System.out.println("Error with durability level: " + hint);
throw ae;
}
}
}
});
// Restart and confirm we can still load them.
story.addStep(new Statement() {
@Override
public void evaluate() throws Throwable {
for (int i = 0; i < durabilityHints.length; i++) {
WorkflowJob j = jobs[i];
try {
WorkflowRun run = j.getLastBuild();
verifySucceededCleanly(story.j.jenkins, run);
Assert.assertEquals(durabilityHints[i], run.getExecution().getDurabilityHint());
Assert.assertEquals(logOutput[i], JenkinsRule.getLog(run));
assertHasTimingAction(run.getExecution());
} catch (AssertionError ae) {
System.out.println("Error with durability level: " + durabilityHints[i]);
throw ae;
}
}
}
});
}
Aggregations