Skip to content

Commit 93b3342

Browse files
authored
fix: report failed pipelines to run status (#109)
1 parent a73546f commit 93b3342

7 files changed

Lines changed: 155 additions & 52 deletions

File tree

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
3737
<mockwebserver.version>0.1.8</mockwebserver.version>
3838
<junit-jupiter-engine.version>5.6.2</junit-jupiter-engine.version>
39-
<jx-pipeline.version>0.0.118</jx-pipeline.version>
39+
<jx-pipeline.version>0.0.119</jx-pipeline.version>
4040
</properties>
4141

4242
<licenses>

src/main/java/org/waveywaves/jenkins/plugins/tekton/client/build/create/CreateRaw.java

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
import com.google.common.base.Strings;
44
import com.google.common.io.Files;
55
import com.google.common.io.Resources;
6+
import edu.umd.cs.findbugs.annotations.NonNull;
67
import hudson.EnvVars;
78
import hudson.Extension;
89
import hudson.FilePath;
910
import hudson.Launcher;
1011
import hudson.model.AbstractProject;
12+
import hudson.model.Result;
1113
import hudson.model.Run;
1214
import hudson.model.TaskListener;
1315
import hudson.tasks.BuildStepDescriptor;
@@ -31,12 +33,13 @@
3133
import org.waveywaves.jenkins.plugins.tekton.client.logwatch.PipelineRunLogWatch;
3234
import org.waveywaves.jenkins.plugins.tekton.client.logwatch.TaskRunLogWatch;
3335

34-
import javax.annotation.Nonnull;
3536
import java.io.ByteArrayInputStream;
3637
import java.io.File;
3738
import java.io.IOException;
3839
import java.io.InputStream;
3940
import java.io.PrintStream;
41+
import java.io.PrintWriter;
42+
import java.io.StringWriter;
4043
import java.net.URL;
4144
import java.nio.charset.StandardCharsets;
4245
import java.util.List;
@@ -111,7 +114,7 @@ public String getClusterName() {
111114
return clusterName;
112115
}
113116

114-
protected String createWithResourceSpecificClient(TektonResourceType resourceType, InputStream inputStream) {
117+
protected String createWithResourceSpecificClient(TektonResourceType resourceType, InputStream inputStream) throws Exception {
115118
switch (resourceType) {
116119
case task:
117120
return createTask(inputStream);
@@ -126,7 +129,7 @@ protected String createWithResourceSpecificClient(TektonResourceType resourceTyp
126129
}
127130
}
128131

129-
public String createTaskRun(InputStream inputStream) {
132+
public String createTaskRun(InputStream inputStream) throws Exception {
130133
if (taskRunClient == null) {
131134
TektonClient tc = (TektonClient) tektonClient;
132135
setTaskRunClient(tc.v1beta1().taskRuns());
@@ -188,7 +191,7 @@ public String createPipeline(InputStream inputStream) {
188191
return resourceName;
189192
}
190193

191-
public String createPipelineRun(InputStream inputStream) {
194+
public String createPipelineRun(InputStream inputStream) throws Exception {
192195
if (pipelineRunClient == null) {
193196
TektonClient tc = (TektonClient) tektonClient;
194197
setPipelineRunClient(tc.v1beta1().pipelineRuns());
@@ -210,38 +213,38 @@ public String createPipelineRun(InputStream inputStream) {
210213
return resourceName;
211214
}
212215

213-
public void streamTaskRunLogsToConsole(TaskRun taskRun) {
216+
public void streamTaskRunLogsToConsole(TaskRun taskRun) throws Exception {
214217
synchronized (consoleLogger) {
215218
KubernetesClient kc = (KubernetesClient) kubernetesClient;
216219
TektonClient tc = (TektonClient) tektonClient;
217220
Thread logWatchTask = null;
218-
try {
219-
TaskRunLogWatch logWatch = new TaskRunLogWatch(kc, tc, taskRun, consoleLogger);
220-
logWatchTask = new Thread(logWatch);
221-
logWatchTask.start();
222-
logWatchTask.join();
223-
} catch (Exception e) {
224-
logger.warning("Exception occurred "+e.toString());
221+
TaskRunLogWatch logWatch = new TaskRunLogWatch(kc, tc, taskRun, consoleLogger);
222+
logWatchTask = new Thread(logWatch);
223+
logWatchTask.start();
224+
logWatchTask.join();
225+
Exception e = logWatch.getException();
226+
if (e != null) {
227+
throw e;
225228
}
226229
}
227230
}
228231

229-
public void streamPipelineRunLogsToConsole(PipelineRun pipelineRun) {
232+
public void streamPipelineRunLogsToConsole(PipelineRun pipelineRun) throws Exception {
230233
KubernetesClient kc = (KubernetesClient) kubernetesClient;
231234
TektonClient tc = (TektonClient) tektonClient;
232235
Thread logWatchTask;
233-
try {
234-
PipelineRunLogWatch logWatch = new PipelineRunLogWatch(kc, tc, pipelineRun, consoleLogger);
235-
logWatchTask = new Thread(logWatch);
236-
logWatchTask.start();
237-
logWatchTask.join();
238-
} catch (Exception e) {
239-
logger.warning("Exception occurred "+e.toString());
236+
PipelineRunLogWatch logWatch = new PipelineRunLogWatch(kc, tc, pipelineRun, consoleLogger);
237+
logWatchTask = new Thread(logWatch);
238+
logWatchTask.start();
239+
logWatchTask.join();
240+
Exception e = logWatch.getException();
241+
if (e != null) {
242+
throw e;
240243
}
241244
}
242245

243246
@Override
244-
public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnull Launcher launcher, @Nonnull TaskListener listener) throws InterruptedException, IOException {
247+
public void perform(@NonNull Run<?, ?> run, @NonNull FilePath workspace, @NonNull EnvVars envVars, @NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException, IOException {
245248
consoleLogger = listener.getLogger();
246249

247250
String clusterName = getClusterName();
@@ -260,11 +263,10 @@ public void perform(@Nonnull Run<?, ?> run, @Nonnull FilePath workspace, @Nonnul
260263
throw new IOException("no kubernetesClient for cluster " + clusterName);
261264
}
262265
}
263-
EnvVars envVars = run.getEnvironment(listener);
264-
runCreate(workspace, envVars);
266+
runCreate(run, workspace, envVars);
265267
}
266268

267-
protected String runCreate(FilePath workspace, EnvVars envVars) {
269+
protected String runCreate(Run<?, ?> run, FilePath workspace, EnvVars envVars) {
268270
URL url = null;
269271
byte[] data = null;
270272
File inputFile = null;
@@ -291,13 +293,32 @@ protected String runCreate(FilePath workspace, EnvVars envVars) {
291293
createdResourceName = createWithResourceSpecificClient(resourceType, new ByteArrayInputStream(data));
292294
}
293295
}
294-
} catch (Exception e) {
295-
logger.warning("possible URL related Exception has occurred " + e.toString());
296+
} catch (Throwable e) {
297+
logMessage("Failed: " + e.getMessage());
298+
StringWriter buffer = new StringWriter();
299+
PrintWriter writer = new PrintWriter(buffer);
300+
e.printStackTrace(writer);
301+
writer.close();
302+
logMessage(buffer.toString());
303+
304+
logger.warning("Caught: " + e.toString());
296305
e.printStackTrace();
306+
307+
run.setResult(Result.FAILURE);
297308
}
298309
return createdResourceName;
299310
}
300311

312+
protected void logMessage(String text) {
313+
synchronized (this.consoleLogger) {
314+
try {
315+
this.consoleLogger.write((text + "\n").getBytes(StandardCharsets.UTF_8));
316+
} catch (IOException e) {
317+
logger.warning("failed to log to console: " + e);
318+
}
319+
}
320+
}
321+
301322
/**
302323
* Performs any conversion on the Tekton resources before we apply it to Kubernetes
303324
*/

src/main/java/org/waveywaves/jenkins/plugins/tekton/client/logwatch/PipelineRunLogWatch.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public class PipelineRunLogWatch implements Runnable {
1919
private KubernetesClient kubernetesClient;
2020
private TektonClient tektonClient;
2121
private PipelineRun pipelineRun;
22+
private Exception exception;
2223
OutputStream consoleLogger;
2324

2425
ConcurrentHashMap<String, TaskRun> taskRunsOnWatch = new ConcurrentHashMap<String, TaskRun>();
@@ -34,6 +35,13 @@ public PipelineRunLogWatch(KubernetesClient kubernetesClient, TektonClient tekto
3435
this.consoleLogger = consoleLogger;
3536
}
3637

38+
/**
39+
* @return the exception if the pipeline failed to succeed
40+
*/
41+
public Exception getException() {
42+
return exception;
43+
}
44+
3745
@Override
3846
public void run() {
3947
String pipelineRunName = pipelineRun.getMetadata().getName();
@@ -72,16 +80,24 @@ public void run() {
7280
} catch (InterruptedException exception) {
7381
exception.printStackTrace();
7482
}
75-
logger.info("TaskRun " + trName + " completed");
83+
Exception e = logWatch.getException();
84+
if (e != null) {
85+
logger.info("TaskRun " + trName + " failed");
86+
if (exception == null) {
87+
exception = e;
88+
}
89+
} else {
90+
logger.info("TaskRun " + trName + " completed");
91+
}
7692
taskComplete = true;
7793
}
7894
}
7995
}
8096
if (taskComplete) {
81-
logger.info("completed PipelineTask " + pipelineTaskName);
97+
logMessage("completed PipelineTask " + pipelineTaskName);
8298
break;
8399
} else {
84-
logger.info("could not find OwnerReference for " + pipelineRunUid);
100+
logMessage("could not find OwnerReference for " + pipelineRunUid);
85101
}
86102
try {
87103
Thread.sleep(1000);

src/main/java/org/waveywaves/jenkins/plugins/tekton/client/logwatch/TaskRunLogWatch.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public class TaskRunLogWatch implements Runnable{
3131
private KubernetesClient kubernetesClient;
3232
private TektonClient tektonClient;
3333
private TaskRun taskRun;
34+
private Exception exception;
3435
OutputStream consoleLogger;
3536

3637
public TaskRunLogWatch(KubernetesClient kubernetesClient, TektonClient tektonClient, TaskRun taskRun, OutputStream consoleLogger) {
@@ -40,6 +41,13 @@ public TaskRunLogWatch(KubernetesClient kubernetesClient, TektonClient tektonCli
4041
this.consoleLogger = consoleLogger;
4142
}
4243

44+
/**
45+
* @return the exception if the task run failed to succeed
46+
*/
47+
public Exception getException() {
48+
return exception;
49+
}
50+
4351
@Override
4452
public void run() {
4553
HashSet<String> runningPhases = Sets.newHashSet("Running", "Succeeded", "Failed");
@@ -112,12 +120,14 @@ public void run() {
112120
}
113121
logPodFailures(pr.get());
114122
} else {
115-
logMessage("no pod could be found for TaskRun " + ns + "/" + taskRun.getMetadata().getName());
116-
123+
String message = "no pod could be found for TaskRun " + ns + "/" + taskRun.getMetadata().getName();
124+
logMessage(message);
125+
exception = new Exception(message);
117126

118127
// lets reload to get the latest status
119128
taskRun = tektonClient.v1beta1().taskRuns().inNamespace(ns).withName(taskRun.getMetadata().getName()).get();
120129
logTaskRunFailure(taskRun);
130+
121131
}
122132
}
123133

@@ -149,9 +159,14 @@ protected void logPodFailures(Pod pod) {
149159
String podName = pod.getMetadata().getName();
150160
PodStatus status = pod.getStatus();
151161
String phase = status.getPhase();
152-
logMessage("pod " + ns + "/" + podName + " status: " + phase);
162+
String message = "pod " + ns + "/" + podName + " status: " + phase;
163+
logMessage(message);
153164

154165
// TODO we could try diagnose more information from the failed pod to log
166+
167+
if (!phase.equals("Succeeded")) {
168+
exception = new Exception(message);
169+
}
155170
}
156171

157172

src/test/java/org/waveywaves/jenkins/plugins/tekton/client/build/create/CreateRawMockServerTest.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import java.util.ArrayList;
2424
import java.util.List;
2525

26+
import static org.assertj.core.api.Assertions.fail;
27+
2628

2729
public class CreateRawMockServerTest {
2830
public static final boolean EnableCatalog = false;
@@ -110,8 +112,15 @@ public void streamTaskRunLogsToConsole(TaskRun taskRun) {
110112
};
111113
createRaw.setTektonClient(client);
112114
createRaw.setTaskRunClient(taskRunClient);
113-
String createdTaskRunName = createRaw.createTaskRun(
114-
new ByteArrayInputStream(testTaskRunYaml.getBytes(StandardCharsets.UTF_8)));
115+
116+
String createdTaskRunName = "";
117+
118+
try {
119+
createdTaskRunName = createRaw.createTaskRun(
120+
new ByteArrayInputStream(testTaskRunYaml.getBytes(StandardCharsets.UTF_8)));
121+
} catch (Exception e) {
122+
fail(e.getMessage(), e);
123+
}
115124

116125
// Then
117126
TaskRunList testTaskRunList = taskRunClient.list();
@@ -197,8 +206,13 @@ public void streamPipelineRunLogsToConsole(PipelineRun pipelineRun) {
197206
};
198207
createRaw.setTektonClient(client);
199208
createRaw.setPipelineRunClient(pipelineRunClient);
200-
String createdPipelineName = createRaw.createPipelineRun(
201-
new ByteArrayInputStream(testPipelineRunYaml.getBytes(StandardCharsets.UTF_8)));
209+
String createdPipelineName = "";
210+
try {
211+
createdPipelineName = createRaw.createPipelineRun(
212+
new ByteArrayInputStream(testPipelineRunYaml.getBytes(StandardCharsets.UTF_8)));
213+
} catch (Exception e) {
214+
fail(e.getMessage(), e);
215+
}
202216

203217
// Then
204218
PipelineRunList testPipelineRunList = pipelineRunClient.list();

src/test/java/org/waveywaves/jenkins/plugins/tekton/client/build/create/CreateRawTest.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import hudson.EnvVars;
44
import hudson.FilePath;
5+
import hudson.model.Run;
56
import org.junit.Test;
67
import org.waveywaves.jenkins.plugins.tekton.client.TektonUtils;
78
import org.waveywaves.jenkins.plugins.tekton.client.build.create.mock.CreateRawMock;
@@ -14,6 +15,7 @@
1415

1516
public class CreateRawTest {
1617
public static final boolean EnableCatalog = false;
18+
public static Run<?,?> run;
1719
public static String namespace;
1820

1921
@Test
@@ -23,7 +25,7 @@ public void runCreateTaskTest() {
2325
"metadata:\n" +
2426
" name: testTask\n";
2527
CreateRaw createRaw = new CreateRawMock(testTaskYaml, CreateRaw.InputType.YAML.toString(), namespace, TektonUtils.DEFAULT_CLIENT_KEY, EnableCatalog);
26-
String created = createRaw.runCreate(null, null);
28+
String created = createRaw.runCreate(run, null, null);
2729
assert created.equals(TektonUtils.TektonResourceType.task.toString());
2830
}
2931

@@ -34,7 +36,7 @@ public void runCreateTaskRunTest() {
3436
"metadata:\n" +
3537
" generateName: home-is-set-\n";
3638
CreateRaw createRaw = new CreateRawMock(testTaskRunYaml, CreateRaw.InputType.YAML.toString(), namespace, TektonUtils.DEFAULT_CLIENT_KEY, EnableCatalog);
37-
String created = createRaw.runCreate(null, null);
39+
String created = createRaw.runCreate(run, null, null);
3840
assert created.equals(TektonUtils.TektonResourceType.taskrun.toString());
3941
}
4042

@@ -45,7 +47,7 @@ public void runCreatePipelineTest() {
4547
"metadata:\n" +
4648
" name: testPipeline\n";
4749
CreateRaw createRaw = new CreateRawMock(testPipelineYaml, CreateRaw.InputType.YAML.toString(), namespace, TektonUtils.DEFAULT_CLIENT_KEY, EnableCatalog);
48-
String created = createRaw.runCreate(null, null);
50+
String created = createRaw.runCreate(run, null, null);
4951
assert created.equals(TektonUtils.TektonResourceType.pipeline.toString());
5052
}
5153

@@ -56,7 +58,7 @@ public void runCreatePipelineRunTest() {
5658
"metadata:\n" +
5759
" name: testPipelineRun\n";
5860
CreateRaw createRaw = new CreateRawMock(testPipelineRunYaml, CreateRaw.InputType.YAML.toString(), namespace, TektonUtils.DEFAULT_CLIENT_KEY, EnableCatalog);
59-
String created = createRaw.runCreate(null, null);
61+
String created = createRaw.runCreate(run, null, null);
6062
assert created.equals(TektonUtils.TektonResourceType.pipelinerun.toString());
6163
}
6264

@@ -73,7 +75,7 @@ public void testCreateRawWithTektonCatalog() throws Exception {
7375

7476
String cheese = "edam";
7577
EnvVars envVars = new EnvVars("CHEESE", cheese);
76-
createRaw.runCreate(workspace, envVars);
78+
createRaw.runCreate(run, workspace, envVars);
7779

7880
String created = createRaw.getLastResource();
7981

0 commit comments

Comments
 (0)