Skip to content

Commit 0c7c67a

Browse files
committed
Gracefully handle output symlinks with BwoB
If an action creates output symlinks, `--remote_download_minimal` now falls back to downloading all its outputs rather than failing with an exception, which most of the time led to a broken build.
1 parent 0e8e611 commit 0c7c67a

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

src/main/java/com/google/devtools/build/lib/remote/RemoteExecutionService.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,10 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
11421142
||
11431143
// In case the action failed, download all outputs. It might be helpful for debugging
11441144
// and there is no point in injecting output metadata of a failed action.
1145-
result.getExitCode() != 0;
1145+
result.getExitCode() != 0
1146+
||
1147+
// Symlinks in actions output are not yet supported with BwoB.
1148+
!metadata.symlinks().isEmpty();
11461149

11471150
// Download into temporary paths, then move everything at the end.
11481151
// This avoids holding the output lock while downloading, which would prevent the local branch
@@ -1162,12 +1165,8 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
11621165
checkState(
11631166
result.getExitCode() == 0,
11641167
"injecting remote metadata is only supported for successful actions (exit code 0).");
1165-
1166-
if (!metadata.symlinks().isEmpty()) {
1167-
throw new IOException(
1168-
"Symlinks in action outputs are not yet supported by "
1169-
+ "--experimental_remote_download_outputs=minimal");
1170-
}
1168+
checkState(metadata.symlinks.isEmpty(), "Symlinks in action outputs are not yet supported by"
1169+
+ " --experimental_remote_download_outputs=minimal");
11711170
}
11721171

11731172
FileOutErr tmpOutErr = outErr.childOutErr();

src/test/java/com/google/devtools/build/lib/remote/BuildWithoutTheBytesIntegrationTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static com.google.common.truth.Truth.assertThat;
1818
import static com.google.devtools.build.lib.remote.util.IntegrationTestUtils.startWorker;
1919
import static org.junit.Assert.assertThrows;
20+
import static org.junit.Assume.assumeFalse;
2021

2122
import com.google.common.collect.ImmutableList;
2223
import com.google.devtools.build.lib.actions.Artifact;
@@ -32,6 +33,7 @@
3233
import com.google.devtools.build.lib.util.OS;
3334
import com.google.devtools.build.lib.vfs.FileSystemUtils;
3435
import com.google.devtools.build.lib.vfs.Path;
36+
import com.google.devtools.build.lib.vfs.Symlinks;
3537
import java.io.IOException;
3638
import org.junit.After;
3739
import org.junit.Test;
@@ -433,6 +435,38 @@ public void symlinkToNestedDirectory() throws Exception {
433435
buildTarget("//a:one_local", "//a:two_local", "//a:one_remote", "//a:two_remote");
434436
}
435437

438+
@Test
439+
public void outputSymlinkHandledGracefully() throws Exception {
440+
// Symlinks may not be supported on Windows
441+
assumeFalse(OS.getCurrent() == OS.WINDOWS);
442+
write(
443+
"a/defs.bzl",
444+
"def _impl(ctx):",
445+
" out = ctx.actions.declare_symlink(ctx.label.name)",
446+
" ctx.actions.run_shell(",
447+
" inputs = [],",
448+
" outputs = [out],",
449+
" command = 'ln -s hello $1',",
450+
" arguments = [out.path],",
451+
" )",
452+
" return DefaultInfo(files = depset([out]))",
453+
"",
454+
"my_rule = rule(",
455+
" implementation = _impl,",
456+
")");
457+
458+
write(
459+
"a/BUILD",
460+
"load(':defs.bzl', 'my_rule')",
461+
"",
462+
"my_rule(name = 'hello')");
463+
464+
buildTarget("//a:hello");
465+
466+
Path outputPath = getOutputPath("a/hello");
467+
assertThat(outputPath.stat(Symlinks.NOFOLLOW).isSymbolicLink()).isTrue();
468+
}
469+
436470
@Test
437471
public void replaceOutputDirectoryWithFile() throws Exception {
438472
write(

0 commit comments

Comments
 (0)