Skip to content

Commit eeb597c

Browse files
committed
[JENKINS-54128] Define an SPI in LogStorage to satisfy WorkflowRun.getLogFile.
1 parent 79b08fe commit eeb597c

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<parent>
2929
<groupId>org.jenkins-ci.plugins</groupId>
3030
<artifactId>plugin</artifactId>
31-
<version>3.25</version>
31+
<version>3.28</version>
3232
<relativePath />
3333
</parent>
3434
<groupId>org.jenkins-ci.plugins.workflow</groupId>

src/main/java/org/jenkinsci/plugins/workflow/log/FileLogStorage.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,4 +322,9 @@ private void maybeFlush() {
322322
}
323323
}
324324

325+
@Deprecated
326+
@Override public File getLogFile(FlowExecutionOwner.Executable build, boolean complete) {
327+
return log;
328+
}
329+
325330
}

src/main/java/org/jenkinsci/plugins/workflow/log/LogStorage.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,12 @@
2828
import hudson.console.AnnotatedLargeText;
2929
import hudson.console.ConsoleAnnotationOutputStream;
3030
import hudson.model.BuildListener;
31+
import hudson.model.Run;
3132
import hudson.model.TaskListener;
3233
import java.io.File;
34+
import java.io.FileOutputStream;
3335
import java.io.IOException;
36+
import java.io.OutputStream;
3437
import javax.annotation.Nonnull;
3538
import org.jenkinsci.plugins.workflow.actions.LogAction;
3639
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
@@ -108,6 +111,41 @@ public interface LogStorage {
108111
*/
109112
@Nonnull AnnotatedLargeText<FlowNode> stepLog(@Nonnull FlowNode node, boolean complete);
110113

114+
/**
115+
* Provide a file containing the log text.
116+
* The default implementation creates a temporary file based on the current contents of {@link #overallLog}.
117+
* @param build as in {@link #overallLog
118+
* @param complete as in {@link #overallLog
119+
* @return a possibly temporary file
120+
* @deprecated Only used for compatibility with {@link Run#getLogFile}.
121+
*/
122+
@Deprecated
123+
default @Nonnull File getLogFile(@Nonnull FlowExecutionOwner.Executable build, boolean complete) {
124+
try {
125+
AnnotatedLargeText<FlowExecutionOwner.Executable> logText = overallLog(build, complete);
126+
File f = File.createTempFile("deprecated", ".log", build instanceof Run ? ((Run) build).getRootDir() : null);
127+
f.deleteOnExit();
128+
try (OutputStream os = new FileOutputStream(f)) {
129+
// Similar to Run#writeWholeLogTo but terminates even if !complete:
130+
long pos = 0;
131+
while (true) {
132+
long pos2 = logText.writeRawLogTo(pos, os);
133+
if (pos2 <= pos) {
134+
break;
135+
}
136+
pos = pos2;
137+
}
138+
}
139+
return f;
140+
} catch (Exception x) {
141+
if (build instanceof Run) {
142+
return new File(((Run) build).getRootDir(), "log");
143+
} else {
144+
return new File("broken.log"); // not much we can do
145+
}
146+
}
147+
}
148+
111149
/**
112150
* Gets the available log storage method for a given build.
113151
* @param b a build about to start

src/test/java/org/jenkinsci/plugins/workflow/log/LogStorageTestBase.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@
3838
import java.util.concurrent.Callable;
3939
import java.util.function.BiFunction;
4040
import jenkins.security.MasterToSlaveCallable;
41+
import org.apache.commons.io.FileUtils;
4142
import org.apache.commons.io.output.NullOutputStream;
4243
import org.apache.commons.io.output.NullWriter;
4344
import org.apache.commons.io.output.WriterOutputStream;
45+
import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
4446
import org.jenkinsci.plugins.workflow.graph.FlowNode;
47+
import org.jenkinsci.plugins.workflow.job.WorkflowJob;
48+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
4549
import static org.junit.Assert.*;
4650
import org.junit.Before;
4751
import org.junit.ClassRule;
@@ -221,6 +225,26 @@ private static final class RemotePrint extends MasterToSlaveCallable<Void, Excep
221225
text("2").writeRawLogTo(0, new NullOutputStream());
222226
}
223227

228+
@SuppressWarnings("deprecation")
229+
@Test public void getLogFile() throws Exception {
230+
LogStorage ls = createStorage();
231+
TaskListener overall = ls.overallListener();
232+
overall.getLogger().println("starting");
233+
TaskListener step1 = ls.nodeListener(new MockNode("1"));
234+
step1.getLogger().println("from step");
235+
step1.getLogger().flush();
236+
overall.getLogger().println("finishing");
237+
overall.getLogger().flush();
238+
WorkflowJob fakeProject = r.createProject(WorkflowJob.class, "fake");
239+
fakeProject.setDefinition(new CpsFlowDefinition("", true));
240+
WorkflowRun fakeBuild = r.buildAndAssertSuccess(fakeProject);
241+
assertOverallLog(0, FileUtils.readFileToString(ls.getLogFile(fakeBuild, false)), false);
242+
close(overall);
243+
ls = createStorage();
244+
assertOverallLog(0, FileUtils.readFileToString(ls.getLogFile(fakeBuild, true)), false);
245+
close(overall);
246+
}
247+
224248
// TODO test missing final newline
225249

226250
protected final long assertOverallLog(long start, String expected, boolean html) throws Exception {

0 commit comments

Comments
 (0)