Skip to content

Commit 0819884

Browse files
authored
Merge pull request #82 from jglick/JENKINS-54128
[JENKINS-54128] Define an SPI in LogStorage to satisfy WorkflowRun.getLogFile
2 parents 79b08fe + de46235 commit 0819884

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-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: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,19 @@
2424

2525
package org.jenkinsci.plugins.workflow.log;
2626

27+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2728
import hudson.ExtensionList;
2829
import hudson.console.AnnotatedLargeText;
2930
import hudson.console.ConsoleAnnotationOutputStream;
3031
import hudson.model.BuildListener;
32+
import hudson.model.Run;
3133
import hudson.model.TaskListener;
3234
import java.io.File;
35+
import java.io.FileOutputStream;
3336
import java.io.IOException;
37+
import java.io.OutputStream;
38+
import java.util.logging.Level;
39+
import java.util.logging.Logger;
3440
import javax.annotation.Nonnull;
3541
import org.jenkinsci.plugins.workflow.actions.LogAction;
3642
import org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner;
@@ -108,6 +114,44 @@ public interface LogStorage {
108114
*/
109115
@Nonnull AnnotatedLargeText<FlowNode> stepLog(@Nonnull FlowNode node, boolean complete);
110116

117+
/**
118+
* Provide a file containing the log text.
119+
* The default implementation creates a temporary file based on the current contents of {@link #overallLog}.
120+
* @param build as in {@link #overallLog}
121+
* @param complete as in {@link #overallLog}
122+
* @return a possibly temporary file
123+
* @deprecated Only used for compatibility with {@link Run#getLogFile}.
124+
*/
125+
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "silly rule")
126+
@Deprecated
127+
default @Nonnull File getLogFile(@Nonnull FlowExecutionOwner.Executable build, boolean complete) {
128+
try {
129+
AnnotatedLargeText<FlowExecutionOwner.Executable> logText = overallLog(build, complete);
130+
FlowExecutionOwner owner = build.asFlowExecutionOwner();
131+
File f = File.createTempFile("deprecated", ".log", owner != null ? owner.getRootDir() : null);
132+
f.deleteOnExit();
133+
try (OutputStream os = new FileOutputStream(f)) {
134+
// Similar to Run#writeWholeLogTo but terminates even if !complete:
135+
long pos = 0;
136+
while (true) {
137+
long pos2 = logText.writeRawLogTo(pos, os);
138+
if (pos2 <= pos) {
139+
break;
140+
}
141+
pos = pos2;
142+
}
143+
}
144+
return f;
145+
} catch (Exception x) {
146+
Logger.getLogger(LogStorage.class.getName()).log(Level.WARNING, null, x);
147+
if (build instanceof Run) {
148+
return new File(((Run) build).getRootDir(), "log");
149+
} else {
150+
return new File("broken.log"); // not much we can do
151+
}
152+
}
153+
}
154+
111155
/**
112156
* Gets the available log storage method for a given build.
113157
* @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)