Add a flag to force Bazel to download certain artifacts when using --remote_download_minimal#15638
Add a flag to force Bazel to download certain artifacts when using --remote_download_minimal#15638lfpino wants to merge 11 commits intobazelbuild:masterfrom
Conversation
When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_force_downloads_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded. Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_force_downloads_regex=".*jar$", also included an integration test with several cases. Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
coeuvre
left a comment
There was a problem hiding this comment.
Thanks for your PR!
I think this is working towards the point 3 I mentioned in #12665.
The new flag works on output-wise, i.e. filter each output of a spawn. I didn't look into IDE usages yet, but since we are on the topic, I want to learn more about the requirements. Have you consider other options, like, filter at spawn level (that's how --remote_download_toplevel works) or use an aspect with output group?
| String regex = remoteOptions.experimentalForceDownloadsRegex; | ||
| // TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used | ||
| // without RemoteOutputsMode.MINIMAL | ||
| this.shouldForceDownloads = !regex.isEmpty() && remoteOptions.remoteOutputsMode == RemoteOutputsMode.MINIMAL; |
There was a problem hiding this comment.
I think we can also use this flag for --remote_download_toplevel.
| /* exitCode = */ result.getExitCode(), | ||
| hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload)); | ||
|
|
||
| ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder(); |
There was a problem hiding this comment.
I was trying to steer away from the current downloads codepath since I'm not an expert in this part of the code. Wanted to make sure this change is isolated to avoid any potential problems but if you want I can try to unify them using downloadsBuilder.
There was a problem hiding this comment.
I tried to unify them in a few ways but I always ended up finding issues and making the code more unreadable. Do you have any suggestions? Since this is experimental I'm inclined to leave it as it is right now and if we can confirm this is a good direction then we can refactor the code to make it more readable (I still find it very confusing the code path that depends on the downloadOutputs boolean)
There was a problem hiding this comment.
downloadOutputs basically means whether we are using BwoB. The two mods were merged into one function because eventually we want to only have BwoB (but the behaviour is still the same by default that Bazel download ALL outputs but in the background, so that the boolean is removed and only one code path left).
As you said this is an experimental feature, I am fine to move forward without unifying them at this PR if that introduce other issues.
There was a problem hiding this comment.
Yeah, I understood that, but some tests are failing when I'm unifying them and it's not entirely clear to me why that's the case. Seems like a bug somewhere where downloadOutputs is not entirely consistent with using BwoB. I'll go ahead as is.
| public int maximumOpenFiles; | ||
|
|
||
| @Option( | ||
| name = "experimental_force_downloads_regex", |
There was a problem hiding this comment.
How about name this flag --experimental_remote_download_regex to match other flags?
lfpino
left a comment
There was a problem hiding this comment.
Thanks for your PR!
I think this is working towards the point 3 I mentioned in #12665.
The new flag works on output-wise, i.e. filter each output of a spawn. I didn't look into IDE usages yet, but since we are on the topic, I want to learn more about the requirements. Have you consider other options, like, filter at spawn level (that's how
--remote_download_toplevelworks) or use an aspect with output group?
You're welcome! :-) and thanks for the prompt reply!
Yeah, I hadn't seen #12665 but this does contribute towards that goal.
The requirement is quite simple: Being able to use build without the bytes without breaking IDE integration. By using this flag, one can use IntelliJ with --remote_download_minimal and ask Bazel to also download the jar files.
I haven't explored any other options since, as usual, there's too many ways of doing this and I tried something that made sense when I looked at the code. Of course if you think that this is not ok architecturally I'm happy to look at other options but I'll probably need a couple of code pointers. If you think this approach is ok, I think we should merge and improve this with some follow-up PRs. WDYT?
| public int maximumOpenFiles; | ||
|
|
||
| @Option( | ||
| name = "experimental_force_downloads_regex", |
| /* exitCode = */ result.getExitCode(), | ||
| hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload)); | ||
|
|
||
| ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder(); |
There was a problem hiding this comment.
I was trying to steer away from the current downloads codepath since I'm not an expert in this part of the code. Wanted to make sure this change is isolated to avoid any potential problems but if you want I can try to unify them using downloadsBuilder.
| String regex = remoteOptions.experimentalForceDownloadsRegex; | ||
| // TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used | ||
| // without RemoteOutputsMode.MINIMAL | ||
| this.shouldForceDownloads = !regex.isEmpty() && remoteOptions.remoteOutputsMode == RemoteOutputsMode.MINIMAL; |
coeuvre
left a comment
There was a problem hiding this comment.
It seems that the new changes haven't been pushed.
| /* exitCode = */ result.getExitCode(), | ||
| hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload)); | ||
|
|
||
| ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder(); |
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
lfpino
left a comment
There was a problem hiding this comment.
Addressed comments PTAL
| /* exitCode = */ result.getExitCode(), | ||
| hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload)); | ||
|
|
||
| ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder(); |
There was a problem hiding this comment.
I tried to unify them in a few ways but I always ended up finding issues and making the code more unreadable. Do you have any suggestions? Since this is experimental I'm inclined to leave it as it is right now and if we can confirm this is a good direction then we can refactor the code to make it more readable (I still find it very confusing the code path that depends on the downloadOutputs boolean)
coeuvre
left a comment
There was a problem hiding this comment.
Sorry for the delay. I think this PR is good now. Just address remaining comments and we are ready to merge.
| /* exitCode = */ result.getExitCode(), | ||
| hasFilesToDownload(action.getSpawn().getOutputFiles(), filesToDownload)); | ||
|
|
||
| ImmutableList.Builder<ListenableFuture<FileMetadata>> forcedDownloadsBuilder = ImmutableList.builder(); |
There was a problem hiding this comment.
downloadOutputs basically means whether we are using BwoB. The two mods were merged into one function because eventually we want to only have BwoB (but the behaviour is still the same by default that Bazel download ALL outputs but in the background, so that the boolean is removed and only one code path left).
As you said this is an experimental feature, I am fine to move forward without unifying them at this PR if that introduce other issues.
| } | ||
|
|
||
| ImmutableList<ListenableFuture<FileMetadata>> forcedDownloads = forcedDownloadsBuilder.build(); | ||
| try (SilentCloseable c = Profiler.instance().profile("Remote.forcedDownload")) { |
There was a problem hiding this comment.
Consider extracting this into a function to share the code above.
There was a problem hiding this comment.
@coeuvre unfortunately the generic Exception catch here is making this code very brittle. Exception handling needs to be improved before we can move this to a generic function, I've added a TODO to avoid mixing things up. That was causing the test failures from my previous attempts.
| tmpOutErr.clearOut(); | ||
| tmpOutErr.clearErr(); | ||
|
|
||
| if (!forcedDownloads.isEmpty()) { |
There was a problem hiding this comment.
Consider moving this into else block below to make it clear that this is only available in BwoB.
| this.scheduler = Schedulers.from(executor, /*interruptibleWorker=*/ true); | ||
|
|
||
| String regex = remoteOptions.remoteDownloadRegex; | ||
| // TODO(bazel-team): Consider adding a warning or more validation if the experimentalForceDownloadsRegex is used |
…wnloads Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
|
@coeuvre this PR should be ready now, PTAL! |
|
There are some failures, let me check that first. |
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
|
@coeuvre you should be able to take a look now |
coeuvre
left a comment
There was a problem hiding this comment.
LGTM! I will import after following comment is addressed.
| return null; | ||
| } | ||
|
|
||
| // private void waitForDownloads(ImmutableList<ListenableFuture<FileMetadata>> downloads, |
Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com>
|
Done. Feel free to merge @coeuvre Thanks a lot! |
|
@bazel-io flag |
|
@bazel-io fork 5.3.0 |
…remote_download_minimal When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded. Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases. Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com> Closes bazelbuild#15638. PiperOrigin-RevId: 460672954 Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
…remote_download_minimal (#15870) When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded. Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases. Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com> Closes #15638. PiperOrigin-RevId: 460672954 Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd Co-authored-by: Luis Fernando Pino Duque <luis@engflow.com>
…remote_download_minimal When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded. Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases. Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com> Closes bazelbuild#15638. PiperOrigin-RevId: 460672954 Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
…remote_download_minimal When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded. Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases. Signed-off-by: Luis Fernando Pino Duque <luis@engflow.com> Closes bazelbuild#15638. PiperOrigin-RevId: 460672954 Change-Id: I3a4f18d046d2d91603a276f16173ad2a253480dd
When using --remote_download_minimal Bazel only downloads to the client the minimum number of artifacts necessary for the build to succeed. This can be sometimes problematic when local development (i.e. IDE) requires some artifacts to do local work (e.g. syntax completion). We add a flag --experimental_remote_download_regex that allow specifying a regular expression that will force certain artifacts to be forced to downloaded.
Tested locally that syntax errors disappear in IntelliJ when compiling Bazel itself with --remote_download_minimal and --experimental_remote_download_regex=".*jar$", also included an integration test with several cases.
Signed-off-by: Luis Fernando Pino Duque luis@engflow.com