From ed68933239e8922188a32afbaa8bd06cf89057dc Mon Sep 17 00:00:00 2001 From: chiwang Date: Tue, 16 Nov 2021 07:04:49 -0800 Subject: [PATCH] Remote: Invalidate actions if previous build used BwoB and remote cache is changed from enabled to disabled. Part of #14252. PiperOrigin-RevId: 410243297 --- .../lib/remote/options/RemoteOptions.java | 8 +++- .../build/lib/skyframe/SkyframeExecutor.java | 16 +++++++ .../bazel/remote/remote_execution_test.sh | 46 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java b/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java index 1d2586af78df5e..8fd3abe3c8b8d8 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java +++ b/src/main/java/com/google/devtools/build/lib/remote/options/RemoteOptions.java @@ -557,10 +557,14 @@ public RemoteOutputsStrategyConverter() { /** The maximum size of an outbound message sent via a gRPC channel. */ public int maxOutboundMessageSize = 1024 * 1024; - public boolean isRemoteEnabled() { - return !Strings.isNullOrEmpty(remoteCache) || isRemoteExecutionEnabled(); + /** Returns {@code true} if remote cache or disk cache is enabled. */ + public boolean isRemoteCacheEnabled() { + return !Strings.isNullOrEmpty(remoteCache) + || !(diskCache == null || diskCache.isEmpty()) + || isRemoteExecutionEnabled(); } + /** Returns {@code true} if remote execution is enabled. */ public boolean isRemoteExecutionEnabled() { return !Strings.isNullOrEmpty(remoteExecutor); } 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 0f2f155563e906..cfbb1d239f10bf 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 @@ -378,6 +378,7 @@ public abstract class SkyframeExecutor implements WalkableGraphFactory, Configur private Map lastRemoteDefaultExecProperties; private RemoteOutputsMode lastRemoteOutputsMode; + private Boolean lastRemoteCacheEnabled; class PathResolverFactoryImpl implements PathResolverFactory { @Override @@ -1727,10 +1728,25 @@ private void deleteActionsIfRemoteOptionsChanged(OptionsProvider options) lastRemoteDefaultExecProperties != null && !remoteDefaultExecProperties.equals(lastRemoteDefaultExecProperties); lastRemoteDefaultExecProperties = remoteDefaultExecProperties; + + boolean remoteCacheEnabled = remoteOptions != null && remoteOptions.isRemoteCacheEnabled(); + // If we have remote metadata from last build, and the remote cache is not + // enabled in this build, invalidate actions since they can't download those + // remote files. + // + // TODO(chiwang): Re-evaluate this after action rewinding is implemented in + // Bazel since we can treat that case as lost inputs. + if (lastRemoteOutputsMode != RemoteOutputsMode.ALL) { + needsDeletion |= + lastRemoteCacheEnabled != null && lastRemoteCacheEnabled && !remoteCacheEnabled; + } + lastRemoteCacheEnabled = remoteCacheEnabled; + RemoteOutputsMode remoteOutputsMode = remoteOptions != null ? remoteOptions.remoteOutputsMode : RemoteOutputsMode.ALL; needsDeletion |= lastRemoteOutputsMode != null && lastRemoteOutputsMode != remoteOutputsMode; this.lastRemoteOutputsMode = remoteOutputsMode; + if (needsDeletion) { memoizingEvaluator.delete(k -> SkyFunctions.ACTION_EXECUTION.equals(k.functionName())); } diff --git a/src/test/shell/bazel/remote/remote_execution_test.sh b/src/test/shell/bazel/remote/remote_execution_test.sh index 3a3218cb79f66f..04dfaa340f34c8 100755 --- a/src/test/shell/bazel/remote/remote_execution_test.sh +++ b/src/test/shell/bazel/remote/remote_execution_test.sh @@ -3204,4 +3204,50 @@ EOF expect_not_log "WARNING: Writing to Remote Cache:" } +function test_download_toplevel_when_turn_remote_cache_off() { + # Test that BwtB doesn't cause build failure if remote cache is disabled in a following build. + # See https://github.com/bazelbuild/bazel/issues/13882. + + cat > .bazelrc < a/BUILD <<'EOF' +genrule( + name = "producer", + outs = ["a.txt", "b.txt"], + cmd = "touch $(OUTS)", +) +genrule( + name = "consumer", + outs = ["out.txt"], + srcs = [":b.txt", "in.txt"], + cmd = "cat $(SRCS) > $@", +) +EOF + echo 'foo' > a/in.txt + + # populate the cache + bazel build \ + --remote_cache=grpc://localhost:${worker_port} \ + --remote_download_toplevel \ + //a:consumer >& $TEST_log || fail "Failed to populate the cache" + + bazel clean >& $TEST_log || fail "Failed to clean" + + # download top level outputs + bazel build \ + --remote_cache=grpc://localhost:${worker_port} \ + --remote_download_toplevel \ + //a:consumer >& $TEST_log || fail "Failed to download outputs" + [[ -f bazel-bin/a/a.txt ]] || [[ -f bazel-bin/a/b.txt ]] \ + && fail "Expected outputs of producer are not downloaded" + + # build without remote cache + echo 'bar' > a/in.txt + bazel build \ + --remote_download_toplevel \ + //a:consumer >& $TEST_log || fail "Failed to build without remote cache" +} + run_suite "Remote execution and remote cache tests"