diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java index 3d44776fd46ac7..95999c3eb4da01 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/SkyframeExecutor.java @@ -877,6 +877,9 @@ protected abstract MemoizingEvaluator createEvaluator( * more generally action lookup nodes) to action execution nodes. We take advantage of the fact * that if a node depends on an action lookup node and is not itself an action lookup node, then * it is an execution-phase node: the action lookup nodes are terminal in the analysis phase. + * + *
Skymeld: propagate events to BuildDriverKey nodes, since they cover both analysis & + * execution. */ protected static final EventFilter DEFAULT_EVENT_FILTER_WITH_ACTIONS = new EventFilter() { @@ -888,7 +891,10 @@ public boolean storeEvents() { @Override public boolean shouldPropagate(SkyKey depKey, SkyKey primaryKey) { // Do not propagate events from analysis phase nodes to execution phase nodes. - return isAnalysisPhaseKey(primaryKey) || !isAnalysisPhaseKey(depKey); + return isAnalysisPhaseKey(primaryKey) + || !isAnalysisPhaseKey(depKey) + // Skymeld only. + || primaryKey instanceof BuildDriverKey; } }; diff --git a/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java b/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java index ef86408a8085c1..368a3f6252ce3f 100644 --- a/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java +++ b/src/test/java/com/google/devtools/build/lib/buildtool/SkymeldBuildIntegrationTest.java @@ -391,7 +391,6 @@ public void symlinksReplantedEachBuild() throws Exception { public void targetAnalysisFailure_skymeld_correctAnalysisEvents(@TestParameter boolean keepGoing) throws Exception { addOptions("--keep_going=" + keepGoing); - addOptions("--experimental_merged_skyframe_analysis_execution"); writeMyRuleBzl(); write( "foo/BUILD", @@ -584,6 +583,41 @@ public void analysisOverlapPercentageSanityCheck_success() throws Exception { assertSingleAnalysisPhaseCompleteEventWithLabels("//foo:foo", "//foo:bar"); } + // Regression test for b/277783687. + @Test + public void targetAnalysisFailureNullBuild_correctErrorsPropagated( + @TestParameter boolean keepGoing) throws Exception { + addOptions("--keep_going=" + keepGoing); + writeMyRuleBzl(); + write( + "foo/BUILD", + "load('//foo:my_rule.bzl', 'my_rule')", + "my_rule(name = 'analysis_failure', srcs = ['foo.in'], deps = [':missing'])"); + write("foo/foo.in"); + + if (keepGoing) { + assertThrows(BuildFailedException.class, () -> buildTarget("//foo:analysis_failure")); + + } else { + assertThrows(ViewCreationFailedException.class, () -> buildTarget("//foo:analysis_failure")); + } + events.assertContainsError( + "in deps attribute of my_rule rule //foo:analysis_failure: rule '//foo:missing' does not" + + " exist"); + events.clear(); + + // Null build + if (keepGoing) { + assertThrows(BuildFailedException.class, () -> buildTarget("//foo:analysis_failure")); + + } else { + assertThrows(ViewCreationFailedException.class, () -> buildTarget("//foo:analysis_failure")); + } + events.assertContainsError( + "in deps attribute of my_rule rule //foo:analysis_failure: rule '//foo:missing' does not" + + " exist"); + } + private void assertSingleAnalysisPhaseCompleteEventWithLabels(String... labels) { assertThat(eventsSubscriber.getAnalysisPhaseCompleteEvents()).hasSize(1); AnalysisPhaseCompleteEvent analysisPhaseCompleteEvent =