fix: remapping of relative-path imports marked external
that don't correspond to a filesystem path in sandbox
#201
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
We have a ts_project target part of an npm_package that includes the following snippet:
When processed as part of an esbuild target, it will perform static analysis (not running the script) in order to resolve the imports, so it will check for both of them. The sandbox layout in the esbuild target is as follows for the file that imports psotcss.config.js and postcss.config.js itself:
As the latter side of the ternary can't be resolved (due to the sandbox layout), we have
../../../../postcss.config
marked as external in the esbuild target. The bazel sandbox plugin introduced in ~0.17.x will incorrectly reject this import as being outside BAZEL_BINDIR. This doesn't make sense, given that../../../../postcss.config
should be even less outside of the sandbox vs../../../../../../../../postcss.config
which doesnt get rejected. Looking further at the sandbox plugin, we can see that paths get rejected if they don't contain the BAZEL_BINDIR string. Adding some extra logging statements (see patch below) will show us whats going wrong.With this log, we get two log statements for postcss.config (one for each side of the ternary:
For the accepted path:
DEBUG: [bazel-sandbox] path /home/noah/.cache/bazel/_bazel_noah/8fd1d20666a46767e7f29541678514a0/execroot/__main__/bazel-out/k8-fastbuild/bin/postcss.config.js is outside execroot /home/noah/.cache/bazel/_bazel_noah/8fd1d20666a46767e7f29541678514a0/sandbox/linux-sandbox/9481/execroot/__main__
For the rejected path:
DEBUG: [bazel-sandbox] path ../../../../postcss.config is outside execroot /home/noah/.cache/bazel/_bazel_noah/8fd1d20666a46767e7f29541678514a0/sandbox/linux-sandbox/9470/execroot/__main__
So the rejected path doesn't become an absolute path, so it can never pass the check for containing the BAZEL_BINDIR string even though it would be within the execroot if we actually had an absolute path. If this path wasnt marked
external
it would be rejected at the point of callingbuild.resolve
.To address this, we assume that if we don't have an absolute path, then we're dealing with a path that 1) couldn't be resolved by esbuild to an actual path but 2) didn't error due to being marked external. Therefore, we build an absolute path for it by resolving it relative to the file that attempts to import this path (which can be gotten with
otherOptions.importer
), and then re-attempt to perform correction of the path to remap it within the sandboxChanges are visible to end-users: no
Test plan
The following commit contains this patch to rules_esbuild that you can comment out to reproduce the issue: https://github.com/sourcegraph/sourcegraph/commit/cf2a1c8856f
The target to build is
//client/web/dev:esbuild-config-production_bundle