Skip to content

Commit ed847c7

Browse files
bigelephant29copybara-github
authored andcommitted
Allow the post processing spawns to bypass the execution check.
The post processing spawn should likely not be governed by the strategy flags, considering that it is not language specific. This will eventually go away after some internal projects are landed, but there's no guaranteed timeline yet. PiperOrigin-RevId: 839585528 Change-Id: I3b7eccbb259c75417bc46f771b0374b192bdba47
1 parent fbe3009 commit ed847c7

File tree

6 files changed

+46
-106
lines changed

6 files changed

+46
-106
lines changed

src/main/java/com/google/devtools/build/lib/actions/ExecutionRequirements.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,11 @@ public enum WorkerProtocolFormat {
308308
* segment from the paths of all inputs and outputs.
309309
*/
310310
public static final String SUPPORTS_PATH_MAPPING = "supports-path-mapping";
311+
312+
/**
313+
* Google internal use only. If specified, this spawn is a post-processing step for archived tree
314+
* artifacts and should bypass dynamic strategy checks. See b/462023192.
315+
*/
316+
public static final String IS_ARCHIVED_TREE_POST_PROCESSING =
317+
"internal-is-archived-tree-post-processing";
311318
}

src/main/java/com/google/devtools/build/lib/dynamic/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ java_library(
1919
"//src/main/java/com/google/devtools/build/lib:runtime",
2020
"//src/main/java/com/google/devtools/build/lib/actions",
2121
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
22+
"//src/main/java/com/google/devtools/build/lib/actions:execution_requirements",
2223
"//src/main/java/com/google/devtools/build/lib/actions:localhost_capacity",
2324
"//src/main/java/com/google/devtools/build/lib/concurrent",
2425
"//src/main/java/com/google/devtools/build/lib/concurrent:thread_safety",

src/main/java/com/google/devtools/build/lib/dynamic/DynamicSpawnStrategy.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.google.devtools.build.lib.actions.DynamicStrategyRegistry;
3131
import com.google.devtools.build.lib.actions.DynamicStrategyRegistry.DynamicMode;
3232
import com.google.devtools.build.lib.actions.ExecException;
33+
import com.google.devtools.build.lib.actions.ExecutionRequirements;
3334
import com.google.devtools.build.lib.actions.SandboxedSpawnStrategy;
3435
import com.google.devtools.build.lib.actions.Spawn;
3536
import com.google.devtools.build.lib.actions.SpawnResult;
@@ -154,6 +155,12 @@ private static boolean canExecLocal(
154155
ExecutionPolicy executionPolicy,
155156
ActionContext.ActionContextRegistry acr,
156157
DynamicStrategyRegistry dsr) {
158+
if (spawn.getExecutionInfo() != null
159+
&& spawn
160+
.getExecutionInfo()
161+
.containsKey(ExecutionRequirements.IS_ARCHIVED_TREE_POST_PROCESSING)) {
162+
return executionPolicy.canRunLocally();
163+
}
157164
return getLocalStrategy(spawn, executionPolicy, acr, dsr) != null;
158165
}
159166

src/test/java/com/google/devtools/build/lib/dynamic/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ java_test(
6767
deps = [
6868
"//src/main/java/com/google/devtools/build/lib/actions",
6969
"//src/main/java/com/google/devtools/build/lib/actions:artifacts",
70+
"//src/main/java/com/google/devtools/build/lib/actions:execution_requirements",
7071
"//src/main/java/com/google/devtools/build/lib/actions:localhost_capacity",
7172
"//src/main/java/com/google/devtools/build/lib/bugreport",
7273
"//src/main/java/com/google/devtools/build/lib/dynamic",

src/test/java/com/google/devtools/build/lib/dynamic/DynamicSpawnStrategyTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.devtools.build.lib.actions.BaseSpawn;
3636
import com.google.devtools.build.lib.actions.DynamicStrategyRegistry;
3737
import com.google.devtools.build.lib.actions.ExecException;
38+
import com.google.devtools.build.lib.actions.ExecutionRequirements;
3839
import com.google.devtools.build.lib.actions.Executor;
3940
import com.google.devtools.build.lib.actions.ResourceSet;
4041
import com.google.devtools.build.lib.actions.SandboxedSpawnStrategy;
@@ -739,6 +740,35 @@ public void actionFailsIfLocalAndRemoteRunNothing() throws Exception {
739740
assertThat(remoteStrategy.succeeded()).isFalse();
740741
}
741742

743+
@Test
744+
public void archivedTreePostProcessingRequirementAllowsLocalExecution() throws Exception {
745+
MockSpawnStrategy localStrategy =
746+
new MockSpawnStrategy("MockLocalSpawnStrategy", DoExec.NOTHING, DoExec.NOTHING, false);
747+
MockSpawnStrategy remoteStrategy =
748+
new MockSpawnStrategy("MockRemoteSpawnStrategy", DoExec.NOTHING, DoExec.NOTHING, false);
749+
StrategyAndContext strategyAndContext = createSpawnStrategy(localStrategy, remoteStrategy);
750+
751+
// Without the requirement, spawn cannot execute because neither local nor remote can exec.
752+
ImmutableMap<String, String> baseRequirements =
753+
ImmutableMap.of(ExecutionRequirements.NO_REMOTE, "1");
754+
Spawn spawn = newCustomSpawn("Null", baseRequirements);
755+
assertThat(strategyAndContext.strategy().canExec(spawn, strategyAndContext.context()))
756+
.isFalse();
757+
758+
// With the requirement, spawn *can* execute because the check is bypassed for local.
759+
ImmutableMap<String, String> postProcessingRequirements =
760+
ImmutableMap.<String, String>builder()
761+
.putAll(baseRequirements)
762+
.put(ExecutionRequirements.IS_ARCHIVED_TREE_POST_PROCESSING, "1")
763+
.buildOrThrow();
764+
Spawn postProcessingSpawn = newCustomSpawn("Null", postProcessingRequirements);
765+
assertThat(
766+
strategyAndContext
767+
.strategy()
768+
.canExec(postProcessingSpawn, strategyAndContext.context()))
769+
.isTrue();
770+
}
771+
742772
@Test
743773
public void stopConcurrentSpawnsWaitForCompletion() throws Exception {
744774
CountDownLatch countDownLatch = new CountDownLatch(2);

src/test/java/com/google/devtools/build/lib/dynamic/DynamicSpawnStrategyUnitTest.java

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -212,83 +212,6 @@ public void exec_localOnlySpawn_runsLocalPostProcessingSpawn() throws Exception
212212
.inOrder();
213213
}
214214

215-
@Test
216-
public void exec_localOnlySpawn_noneCanExec_fails() throws Exception {
217-
Spawn spawn =
218-
new SpawnBuilder().withMnemonic("ThisMnemonic1").withOwnerPrimaryOutput(output1).build();
219-
Spawn postProcessingSpawn =
220-
new SpawnBuilder().withMnemonic("ThatMnemonic2").withOwnerPrimaryOutput(output2).build();
221-
222-
DynamicSpawnStrategy dynamicSpawnStrategy =
223-
createDynamicSpawnStrategy(
224-
ExecutionPolicy.LOCAL_EXECUTION_ONLY, mockGetPostProcessingSpawn);
225-
when(mockGetPostProcessingSpawn.apply(spawn)).thenReturn(Optional.of(postProcessingSpawn));
226-
SandboxedSpawnStrategy local = createMockSpawnStrategy(false);
227-
SandboxedSpawnStrategy remote = createMockSpawnStrategy();
228-
ActionExecutionContext actionExecutionContext = createMockActionExecutionContext(local, remote);
229-
230-
UserExecException thrown =
231-
assertThrows(
232-
UserExecException.class,
233-
() -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
234-
assertThat(thrown)
235-
.hasMessageThat()
236-
.isEqualTo(
237-
"Spawn is not executable in local: No usable dynamic_local_strategy found (and remote"
238-
+ " execution disabled) for action ThisMnemonic1. Post-Processing Spawn is not"
239-
+ " executable in local: No usable dynamic_local_strategy found (and remote"
240-
+ " execution disabled) for action ThatMnemonic2. ");
241-
assertThat(thrown).hasMessageThat().doesNotContain("dynamic_remote_strategy");
242-
verifyNoInteractions(remote);
243-
}
244-
245-
@Test
246-
public void exec_localOnlySpawnWithNonExecutablePostProcessingSpawn_doesNotExecLocalSpawn()
247-
throws Exception {
248-
Spawn spawn =
249-
new SpawnBuilder().withMnemonic("ThisMnemonic1").withOwnerPrimaryOutput(output1).build();
250-
Spawn postProcessingSpawn =
251-
new SpawnBuilder().withMnemonic("ThatMnemonic2").withOwnerPrimaryOutput(output2).build();
252-
253-
DynamicSpawnStrategy dynamicSpawnStrategy =
254-
createDynamicSpawnStrategy(
255-
ExecutionPolicy.LOCAL_EXECUTION_ONLY, mockGetPostProcessingSpawn);
256-
when(mockGetPostProcessingSpawn.apply(spawn)).thenReturn(Optional.of(postProcessingSpawn));
257-
258-
SandboxedSpawnStrategy local = createMockSpawnStrategy();
259-
260-
ActionExecutionContext actionExecutionContext = mock(ActionExecutionContext.class);
261-
when(actionExecutionContext.getFileOutErr()).thenReturn(new TestFileOutErr());
262-
when(actionExecutionContext.getContext(DynamicStrategyRegistry.class))
263-
.thenReturn(
264-
new DynamicStrategyRegistry() {
265-
@Override
266-
public ImmutableList<SandboxedSpawnStrategy> getDynamicSpawnActionContexts(
267-
Spawn spawn, DynamicMode dynamicMode) {
268-
if (spawn.getMnemonic().equals("ThisMnemonic1")) {
269-
return ImmutableList.of(local);
270-
}
271-
return ImmutableList.of();
272-
}
273-
274-
@Override
275-
public void notifyUsedDynamic(ActionContextRegistry actionContextRegistry) {}
276-
});
277-
when(actionExecutionContext.withFileOutErr(any())).thenReturn(actionExecutionContext);
278-
279-
UserExecException thrown =
280-
assertThrows(
281-
UserExecException.class,
282-
() -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
283-
284-
assertThat(thrown)
285-
.hasMessageThat()
286-
.isEqualTo(
287-
"Post-Processing Spawn is not executable in local: No usable dynamic_local_strategy"
288-
+ " found (and remote execution disabled) for action ThatMnemonic2. ");
289-
assertThat(thrown).hasMessageThat().doesNotContain("dynamic_remote_strategy");
290-
}
291-
292215
@Test
293216
public void exec_failedLocalSpawn_doesNotExecLocalPostProcessingSpawn() throws Exception {
294217
testExecFailedLocalSpawnDoesNotExecLocalPostProcessingSpawn(
@@ -333,7 +256,6 @@ private void testExecFailedLocalSpawnDoesNotExecLocalPostProcessingSpawn(SpawnRe
333256
assertThat(results).containsExactly(failedResult);
334257
assertThat(localSpawnCaptor.getAllValues()).containsExactly(spawn);
335258
verify(remote, never()).exec(any(), any(), any());
336-
verifyNoInteractions(postProcessingSpawn);
337259
}
338260

339261
@Test
@@ -638,7 +560,6 @@ public void exec_runAnywhereSpawn_localCantExec_runsRemote() throws Exception {
638560
assertThat(results).containsExactly(SUCCESSFUL_SPAWN_RESULT);
639561
// Never runs anything as it says it can't execute anything at all.
640562
verify(local, never()).exec(any(), any(), any());
641-
verifyNoInteractions(postProcessingSpawn);
642563
}
643564

644565
@Test
@@ -672,33 +593,6 @@ public void exec_runAnywhereSpawn_remoteCantExec_runsLocal() throws Exception {
672593
verify(remote, never()).exec(any(), any(), any());
673594
}
674595

675-
@Test
676-
public void exec_runAnywhereSpawn_noneCanExec_fails() throws Exception {
677-
Spawn spawn =
678-
new SpawnBuilder().withMnemonic("ThisMnemonic1").withOwnerPrimaryOutput(output1).build();
679-
Spawn postProcessingSpawn =
680-
new SpawnBuilder().withMnemonic("ThatMnemonic2").withOwnerPrimaryOutput(output2).build();
681-
682-
DynamicSpawnStrategy dynamicSpawnStrategy =
683-
createDynamicSpawnStrategy(ExecutionPolicy.ANYWHERE, mockGetPostProcessingSpawn);
684-
when(mockGetPostProcessingSpawn.apply(spawn)).thenReturn(Optional.of(postProcessingSpawn));
685-
SandboxedSpawnStrategy local = createMockSpawnStrategy(false);
686-
SandboxedSpawnStrategy remote = createMockSpawnStrategy(false);
687-
ActionExecutionContext actionExecutionContext = createMockActionExecutionContext(local, remote);
688-
689-
UserExecException thrown =
690-
assertThrows(
691-
UserExecException.class,
692-
() -> dynamicSpawnStrategy.exec(spawn, actionExecutionContext));
693-
assertThat(thrown)
694-
.hasMessageThat()
695-
.isEqualTo(
696-
"Spawn is not executable in local: No usable dynamic_local_strategy or"
697-
+ " dynamic_remote_strategy found for action ThisMnemonic1. Post-Processing Spawn"
698-
+ " is not executable in local: No usable dynamic_local_strategy or"
699-
+ " dynamic_remote_strategy found for action ThatMnemonic2. ");
700-
}
701-
702596
private DynamicSpawnStrategy createDynamicSpawnStrategy(
703597
ExecutionPolicy executionPolicy,
704598
Function<Spawn, Optional<Spawn>> getPostProcessingSpawnForLocalExecution) {

0 commit comments

Comments
 (0)