|
30 | 30 | import com.google.common.util.concurrent.SettableFuture; |
31 | 31 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; |
32 | 32 | import groovy.lang.Closure; |
33 | | -import hudson.Main; |
34 | 33 | import hudson.model.Descriptor; |
35 | 34 | import hudson.model.Result; |
36 | 35 | import hudson.util.DaemonThreadFactory; |
|
66 | 65 | import java.util.function.Function; |
67 | 66 | import java.util.logging.Level; |
68 | 67 | import java.util.logging.Logger; |
| 68 | +import java.util.stream.Stream; |
69 | 69 | import jenkins.model.CauseOfInterruption; |
70 | 70 | import jenkins.util.ContextResettingExecutorService; |
71 | 71 | import org.codehaus.groovy.runtime.InvokerInvocationException; |
@@ -345,12 +345,16 @@ private void completed(@NonNull Outcome newOutcome) { |
345 | 345 | LOGGER.log(Level.FINE, "earlier success: {0}", outcome.getNormal()); |
346 | 346 | } |
347 | 347 | } |
348 | | - if (failure != null && earlierFailure != null) { |
| 348 | + if (failure != null && earlierFailure != null && !refersTo(failure, earlierFailure)) { |
349 | 349 | earlierFailure.addSuppressed(failure); |
350 | 350 | } |
351 | 351 | } |
352 | 352 | } |
353 | 353 |
|
| 354 | + private static boolean refersTo(Throwable t1, Throwable t2) { |
| 355 | + return t1 == t2 || t1.getCause() != null && refersTo(t1.getCause(), t2) || Stream.of(t1.getSuppressed()).anyMatch(t3 -> refersTo(t3, t2)); |
| 356 | + } |
| 357 | + |
354 | 358 | /** |
355 | 359 | * When this step context has completed execution (successful or otherwise), plan the next action. |
356 | 360 | */ |
|
0 commit comments