Skip to content

Commit 867d263

Browse files
committed
Ensure a stashedFile parameter is retained on a Jenkins restart while in the queue
1 parent 01de771 commit 867d263

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

src/main/java/io/jenkins/plugins/file_parameters/StashedFileParameterValue.java

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,22 @@
2626

2727
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2828
import hudson.EnvVars;
29+
import hudson.Extension;
2930
import hudson.FilePath;
3031
import hudson.Launcher;
3132
import hudson.Util;
33+
import hudson.model.ParametersAction;
34+
import hudson.model.Queue;
3235
import hudson.model.Run;
3336
import hudson.model.TaskListener;
37+
import hudson.model.queue.QueueListener;
3438
import java.io.File;
3539
import java.io.IOException;
3640
import java.io.InputStream;
37-
import java.nio.file.Files;
3841

42+
import java.util.List;
43+
import java.util.logging.Level;
44+
import java.util.logging.Logger;
3945
import org.apache.commons.fileupload.FileItem;
4046
import org.apache.commons.io.FileUtils;
4147
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
@@ -44,11 +50,14 @@
4450

4551
public final class StashedFileParameterValue extends AbstractFileParameterValue {
4652

53+
private static final Logger LOGGER = Logger.getLogger(StashedFileParameterValue.class.getName());
54+
4755
private static final long serialVersionUID = 1L;
4856

57+
private final String tmpFile;
58+
4959
@SuppressFBWarnings(value = "SE_TRANSIENT_FIELD_NOT_RESTORED", justification = "Doesn't make sense to persist it")
50-
private transient File tmp;
51-
60+
5261
@DataBoundConstructor public StashedFileParameterValue(String name, FileItem file) throws IOException {
5362
this(name, file.getInputStream());
5463
setFilename(file.getName());
@@ -57,14 +66,15 @@ public final class StashedFileParameterValue extends AbstractFileParameterValue
5766

5867
StashedFileParameterValue(String name, InputStream src) throws IOException {
5968
super(name);
60-
tmp = new File(Util.createTempDir(), name);
61-
tmp.deleteOnExit();
69+
File tmp = new File(Util.createTempDir(), name);
6270
FileUtils.copyInputStreamToFile(src, tmp);
71+
tmpFile = tmp.getAbsolutePath();
6372
}
6473

6574
@Override public void buildEnvironment(Run<?, ?> build, EnvVars env) {
6675
super.buildEnvironment(build, env);
67-
if (tmp != null) {
76+
File tmp = tmpFile != null ? new File(tmpFile) : null;
77+
if (tmp != null && tmp.isFile()) {
6878
try {
6979
FlowExecutionOwner feo = build instanceof FlowExecutionOwner.Executable ? ((FlowExecutionOwner.Executable) build).asFlowExecutionOwner() : null;
7080
TaskListener listener = feo != null ? feo.getListener() : TaskListener.NULL;
@@ -75,8 +85,7 @@ public final class StashedFileParameterValue extends AbstractFileParameterValue
7585
throw new RuntimeException( x );
7686
}
7787
try {
78-
Files.deleteIfExists(tmp.toPath());
79-
tmp = null;
88+
FileUtils.deleteDirectory(tmp.getParentFile());
8089
} catch (IOException e) {
8190
throw new RuntimeException(e);
8291
}
@@ -88,4 +97,30 @@ public final class StashedFileParameterValue extends AbstractFileParameterValue
8897
return tempDir.child(name);
8998
}
9099

100+
@Extension
101+
public static class CancelledQueueListener extends QueueListener {
102+
103+
@Override
104+
public void onLeft(Queue.LeftItem li) {
105+
if (li.isCancelled()) {
106+
List<ParametersAction> actions = li.getActions(ParametersAction.class);
107+
actions.forEach(a -> {
108+
a.getAllParameters().stream()
109+
.filter(p -> p instanceof StashedFileParameterValue)
110+
.map(p -> (StashedFileParameterValue) p)
111+
.forEach(p -> {
112+
if (p.tmpFile != null) {
113+
File tmp = new File(p.tmpFile);
114+
try {
115+
FileUtils.deleteDirectory(tmp.getParentFile());
116+
} catch (IOException | IllegalArgumentException e) {
117+
LOGGER.log(Level.WARNING, "Unable to delete temporary file {0} for parameter {1} of task {2}",
118+
new Object[]{tmp.getAbsolutePath(), p.getName(), li.task.getName()});
119+
}
120+
}
121+
});
122+
});
123+
}
124+
}
125+
}
91126
}

src/test/java/io/jenkins/plugins/file_parameters/RestartTest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import hudson.model.Node;
2929
import hudson.model.ParametersDefinitionProperty;
3030
import hudson.model.Queue;
31+
import hudson.model.Result;
3132
import hudson.model.queue.CauseOfBlockage;
3233
import hudson.model.queue.QueueTaskDispatcher;
3334
import jenkins.model.Jenkins;
@@ -92,7 +93,32 @@ void restBase64() throws Throwable {
9293
});
9394
}
9495

95-
@TestExtension("restBase64")
96+
@Test
97+
void stashedFileIsRetained() throws Throwable {
98+
rr.then(r -> {
99+
r.jenkins.setSecurityRealm(r.createDummySecurityRealm());
100+
r.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy().grant(Jenkins.ADMINISTER).everywhere().to("admin"));
101+
WorkflowJob p = r.createProject(WorkflowJob.class, "p");
102+
p.addProperty(new ParametersDefinitionProperty(new StashedFileParameterDefinition("FILE")));
103+
p.setDefinition(new CpsFlowDefinition("node { unstash 'FILE' }", true));
104+
WebRequest req = new WebRequest(new URL(r.getURL() + "job/p/buildWithParameters"), HttpMethod.POST);
105+
File f = File.createTempFile("junit", null, tmp);
106+
FileUtils.write(f, "uploaded content here", "UTF-8");
107+
req.setEncodingType(FormEncodingType.MULTIPART);
108+
req.setRequestParameters(Collections.singletonList(new KeyDataPair("FILE", f, "myfile.txt", "text/plain", "UTF-8")));
109+
r.createWebClient().withBasicApiToken("admin").getPage(req);
110+
});
111+
rr.then(r -> {
112+
ExtensionList.lookupSingleton(Block.class).ready = true;
113+
WorkflowJob p = r.jenkins.getItemByFullName("p", WorkflowJob.class);
114+
r.waitUntilNoActivity();
115+
WorkflowRun b = p.getBuildByNumber(1);
116+
assertNotNull(b);
117+
assert(b.getResult().isBetterOrEqualTo(Result.SUCCESS));
118+
});
119+
}
120+
121+
@TestExtension({"restBase64", "stashedFileIsRetained"})
96122
public static final class Block extends QueueTaskDispatcher {
97123
private boolean ready;
98124
@Override

0 commit comments

Comments
 (0)