Encode ViewCreation failures with FailureDetails
Bazel's analysis phase can fail with a ViewCreationFailedException,
encompassing a variety of loading, analysis, and post-analysis evaluation
problems. This change equips that exception with FailureDetails and
eliminates the final use of (non-success) DetailedExitCode without
FailureDetails.
Before this change, a ViewCreationFailedException (VCFE) always led to a
numerical exit code of 1. To ensure backwards compatibility, this change
uses the DetailedExitCode factory method which overrides the numerical
exit code metadata from failure_detail.proto. Most of the detailed failure
subcategories that can end up in a VCFE do have metadata specifying 1 as
their numerical exit code, but not all; e.g., post-analysis query
evaluation failures can cause a VCFE and, as query failures, have 2 or 7
for their metadata.
Ensuring the propagation of failure details from analysis to the VCFE
required the following work.
SkyframeBuildView translated analysis exceptions, designated via the
marker interface SaneAnalysisException, into VCFEs. Likewise, it
translated the loading-phase exceptions NoSuch{Package,Target}Exception
into VCFEs. By making SaneAnalysisException extend DetailedException,
that conversion now propagates any detailed failures described by those
three exception types.
SaneAnalysisException has six implementations. This change implements
DetailedException across them. Doing so with AspectCreationException and
ConfiguredValueCreationException involved moderately complex work. In
AspectFunction and ConfiguredTargetFunction, these two exception types
get instantiated when a nested set of "Cause"s is non-empty (and also in
several other more straightforward contexts).
"Cause" had already been equipped with a DetailedExitCode property, but
AnalysisFailedCause didn't support it (Cause's other implementations
did). This change implements the property for AnalysisFailedCause.
The nested set traversal in
ConfiguredTargetFunction.getPrioritizedDetailedExitCode does not involve
any deep traversals, though that's not obvious. If the nested set
builder ever gets another nested set added to it via addTransitive, then
it does so while handling a dependency's exception, which results in a
DependencyEvaluationException, whose handling avoids the call to
getPrioritizedDetailedExitCode.
This change does *not* detail analysis failures in maximum resolution. To
do so, a future change would need to enhance the error-event-sensitive
failure detection in AspectFunction and ConfiguredTargetFunction, using
e.g. the events-with-properties strategy used by
ErrorSensingEventHandler. It would also need to replace the non-detailed
AspectCreationException and ConfiguredValueCreationException
constructors.
RELNOTES: None.
PiperOrigin-RevId: 333827282
diff --git a/src/main/java/com/google/devtools/build/lib/util/DetailedExitCode.java b/src/main/java/com/google/devtools/build/lib/util/DetailedExitCode.java
index 3b0146b..847694a 100644
--- a/src/main/java/com/google/devtools/build/lib/util/DetailedExitCode.java
+++ b/src/main/java/com/google/devtools/build/lib/util/DetailedExitCode.java
@@ -27,7 +27,7 @@
import java.util.Objects;
import javax.annotation.Nullable;
-/** An {@link ExitCode} and an optional {@link FailureDetail}. */
+/** An {@link ExitCode} that has a {@link FailureDetail} unless it's {@link ExitCode#SUCCESS}. */
public class DetailedExitCode {
private final ExitCode exitCode;
@Nullable private final FailureDetail failureDetail;
@@ -65,25 +65,6 @@
}
/**
- * Returns a {@link DetailedExitCode} specifying {@link ExitCode} but no {@link FailureDetail}.
- *
- * <p>This method exists in order to allow for code which has not yet been wired for {@link
- * FailureDetail) support to interact with {@link FailureDetail}-handling code infrastructure.
- *
- * <p>Callsites should migrate to using either:
- *
- * <ul>
- * <li>{@link #of(ExitCode, FailureDetail)}, when they're wired for {@link FailureDetail}
- * support but not yet ready to have {@link FailureDetail} metadata determine exit code behavior
- * <li>{@link #of(FailureDetail)}, when changing exit code behavior is desired.
- * </ul>
- *
- */
- public static DetailedExitCode justExitCode(ExitCode exitCode) {
- return new DetailedExitCode(checkNotNull(exitCode), null);
- }
-
- /**
* Returns a {@link DetailedExitCode} combining the provided {@link FailureDetail} and {@link
* ExitCode}.
*
@@ -91,9 +72,9 @@
* FailureDetail)-handling code infrastructure without requiring any simultaneous change in exit
* code behavior.
*
- * <p>Callsites should migrate to using {@link #of(FailureDetail)} instead.
+ * <p>Unless contrained by backwards-compatibility needs, callers should use {@link
+ * #of(FailureDetail)} instead.
*/
- // TODO(b/138456686): consider controlling this behavior by flag if migration appears risky.
public static DetailedExitCode of(ExitCode exitCode, FailureDetail failureDetail) {
return new DetailedExitCode(checkNotNull(exitCode), checkNotNull(failureDetail));
}
@@ -103,7 +84,7 @@
* FailureDetail}'s metadata.
*/
public static DetailedExitCode of(FailureDetail failureDetail) {
- return new DetailedExitCode(getExitCode(failureDetail), failureDetail);
+ return new DetailedExitCode(getExitCode(failureDetail), checkNotNull(failureDetail));
}
@Override