Skip to content
Permalink
Browse files

Merge pull request #147 from mmitche/add-retry

[JENKINS-39194] Implement SCM retry count
  • Loading branch information...
svanoort committed Jan 25, 2018
2 parents e9b1832 + e8fb2c8 commit d91d14d0323d0944dc5a89fef83c83283c7d13d9
@@ -27,19 +27,22 @@
import hudson.AbortException;
import hudson.Extension;
import hudson.FilePath;
import hudson.Functions;
import hudson.model.Action;
import hudson.model.Computer;
import hudson.model.Item;
import hudson.model.Job;
import hudson.model.Node;
import hudson.model.Queue;
import hudson.model.Run;
import hudson.model.Run.RunnerAbortedException;
import hudson.model.TaskListener;
import hudson.model.TopLevelItem;
import hudson.scm.SCM;
import hudson.scm.SCMDescriptor;
import hudson.slaves.WorkspaceList;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.Collection;
import java.util.List;
import jenkins.model.Jenkins;
@@ -125,7 +128,7 @@ public boolean isLightweight() {
dir = new FilePath(owner.getRootDir());
}
listener.getLogger().println("Checking out " + scm.getKey() + " into " + dir + " to read " + scriptPath);
String script;
String script = null;
Computer computer = node.toComputer();
if (computer == null) {
throw new IOException(node.getDisplayName() + " may be offline");
@@ -135,7 +138,30 @@ public boolean isLightweight() {
delegate.setChangelog(true);
FilePath acquiredDir;
try (WorkspaceList.Lease lease = computer.getWorkspaceList().acquire(dir)) {
delegate.checkout(build, dir, listener, node.createLauncher(listener));
for (int retryCount = Jenkins.getInstance().getScmCheckoutRetryCount(); retryCount >= 0; retryCount--) {
try {
delegate.checkout(build, dir, listener, node.createLauncher(listener));
break;
} catch (AbortException e) {
// abort exception might have a null message.
// 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
listener.error("Checkout failed").println(Functions.printThrowable(e).trim()); // TODO 2.43+ use Functions.printStackTrace
}

if (retryCount == 0) // all attempts failed
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);
@@ -26,6 +26,7 @@

import hudson.model.ParametersAction;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Result;
import hudson.model.StringParameterDefinition;
import hudson.model.StringParameterValue;
import hudson.plugins.git.BranchSpec;
@@ -59,6 +60,7 @@
@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsRule r = new JenkinsRule();
@Rule public GitSampleRepoRule sampleRepo = new GitSampleRepoRule();
@Rule public GitSampleRepoRule invalidRepo = new GitSampleRepoRule();

@Test public void configRoundtrip() throws Exception {
sampleRepo.init();
@@ -82,6 +84,7 @@
// TODO currently the log text is in Run.log, but not on FlowStartNode/LogAction, so not visible from Workflow Steps etc.
r.assertLogContains("hello from SCM", b);
r.assertLogContains("Staging flow.groovy", b);
r.assertLogNotContains("Retrying after 10 seconds", b);
FlowGraphWalker w = new FlowGraphWalker(b.getExecution());
int workspaces = 0;
for (FlowNode n : w) {
@@ -105,6 +108,7 @@
WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
r.assertLogContains("Cloning the remote Git repository", b);
r.assertLogContains("version one", b);
r.assertLogNotContains("Retrying after 10 seconds", b);
sampleRepo.write("flow.groovy", "echo 'version two'");
sampleRepo.git("add", "flow.groovy");
sampleRepo.git("commit", "--message=next");
@@ -113,6 +117,7 @@
assertEquals(2, b.number);
r.assertLogContains("Fetching changes from the remote Git repository", b);
r.assertLogContains("version two", b);
r.assertLogNotContains("Retrying after 10 seconds", b);
List<ChangeLogSet<? extends ChangeLogSet.Entry>> changeSets = b.getChangeSets();
assertEquals(1, changeSets.size());
ChangeLogSet<? extends ChangeLogSet.Entry> changeSet = changeSets.get(0);
@@ -138,6 +143,7 @@
WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
r.assertLogContains("Cloning the remote Git repository", b);
r.assertLogContains("version one", b);
r.assertLogNotContains("Retrying after 10 seconds", b);
b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
assertEquals(2, b.number);
List<ChangeLogSet<? extends ChangeLogSet.Entry>> changeSets = b.getChangeSets();
@@ -157,9 +163,24 @@
p.setDefinition(def);
WorkflowRun b = r.assertBuildStatusSuccess(p.scheduleBuild2(0));
r.assertLogNotContains("Cloning the remote Git repository", b);
r.assertLogNotContains("Retrying after 10 seconds", b);
r.assertLogContains("Obtained flow.groovy from git " + sampleRepo, b);
r.assertLogContains("version one", b);
}

@Issue("JENKINS-39194")
@Test public void retry() throws Exception {
// We use an un-initialized repo here to test retry
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
GitStep step = new GitStep(invalidRepo.toString());
CpsScmFlowDefinition def = new CpsScmFlowDefinition(step.createSCM(), "flow.groovy");
def.setLightweight(false);
p.setDefinition(def);
r.jenkins.setScmCheckoutRetryCount(1);
WorkflowRun b = r.assertBuildStatus(Result.FAILURE, p.scheduleBuild2(0));
r.assertLogContains("Could not read from remote repository", b);
r.assertLogContains("Retrying after 10 seconds", b);
}

@Issue("JENKINS-28447")
@Test public void usingParameter() throws Exception {

0 comments on commit d91d14d

Please sign in to comment.
You can’t perform that action at this time.