Skip to content

Commit

Permalink
Gracefully handle output symlinks with BwoB
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
fmeum committed Apr 13, 2023
1 parent 0e8e611 commit 8cc1a74
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,10 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
||
// In case the action failed, download all outputs. It might be helpful for debugging
// and there is no point in injecting output metadata of a failed action.
result.getExitCode() != 0;
result.getExitCode() != 0
||
// Symlinks in actions output are not yet supported with BwoB.
!metadata.symlinks().isEmpty();

// Download into temporary paths, then move everything at the end.
// This avoids holding the output lock while downloading, which would prevent the local branch
Expand All @@ -1162,12 +1165,8 @@ public InMemoryOutput downloadOutputs(RemoteAction action, RemoteActionResult re
checkState(
result.getExitCode() == 0,
"injecting remote metadata is only supported for successful actions (exit code 0).");

if (!metadata.symlinks().isEmpty()) {
throw new IOException(
"Symlinks in action outputs are not yet supported by "
+ "--experimental_remote_download_outputs=minimal");
}
checkState(metadata.symlinks.isEmpty(), "Symlinks in action outputs are not yet supported by"
+ " --experimental_remote_download_outputs=minimal");
}

FileOutErr tmpOutErr = outErr.childOutErr();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,37 @@ public void symlinkToNestedDirectory() throws Exception {
buildTarget("//a:one_local", "//a:two_local", "//a:one_remote", "//a:two_remote");
}

@Test
public void outputSymlinkHandledGracefully() throws Exception {
write(
"a/defs.bzl",
"def _impl(ctx):",
" out = ctx.actions.declare_symlink(ctx.label.name)",
" ctx.actions.run_shell(",
" inputs = [],",
" outputs = [out],",
" command = 'ln -s hello $1',",
" arguments = [out.path],",
" )",
" return DefaultInfo(files = depset([out]))",
"",
"my_rule = rule(",
" implementation = _impl,",
")");

write(
"a/BUILD",
"load(':defs.bzl', 'my_rule')",
"",
"my_rule(name = 'hello')");

buildTarget("//a:hello");

Path outputPath = getOutputPath("a/hello");
assertThat(outputPath.exists()).isTrue();
assertThat(outputPath.isSymbolicLink()).isTrue();
}

@Test
public void replaceOutputDirectoryWithFile() throws Exception {
write(
Expand Down

0 comments on commit 8cc1a74

Please sign in to comment.