Skip to content

Commit 18b96f0

Browse files
committed
fix(@angular/build): rewrite paths from sandboxed execroots when running under Bazel
rewriteForBazel only maps paths that fall inside BAZEL_BINDIR relative to JS_BINARY__EXECROOT. Locally sandboxed actions (darwin-sandbox, linux-sandbox) stage inputs as symlinks into a differently rooted copy of the execroot, so realpath resolves entry points to the unsandboxed execroot while the TypeScript program is keyed by sandbox paths. The compiler plugin then fails with "File 'main.ts' is missing from the TypeScript compilation". Derive the effective execroot from the working directory and re-anchor paths that resolve outside of it.
1 parent f8ccc41 commit 18b96f0

1 file changed

Lines changed: 35 additions & 5 deletions

File tree

packages/angular/build/src/tools/esbuild/angular/rewrite-bazel-paths.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,55 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import { join, relative } from 'node:path';
9+
import { join, relative, sep } from 'node:path';
1010

1111
const bazelBinDirectory = process.env['BAZEL_BINDIR'];
1212
const bazelExecRoot = process.env['JS_BINARY__EXECROOT'];
13+
const execRootMarker = `${sep}execroot${sep}`;
14+
15+
/**
16+
* Sandboxed actions run in a copy of the execroot whose absolute path differs from
17+
* `JS_BINARY__EXECROOT`, so the effective execroot is derived from the working directory.
18+
*/
19+
function effectiveExecRoot(): string | undefined {
20+
const cwd = process.cwd();
21+
const markerIndex = cwd.indexOf(execRootMarker);
22+
if (markerIndex === -1) {
23+
return bazelExecRoot;
24+
}
25+
26+
const workspaceEnd = cwd.indexOf(sep, markerIndex + execRootMarker.length);
27+
28+
return workspaceEnd === -1 ? cwd : cwd.slice(0, workspaceEnd);
29+
}
1330

1431
export function rewriteForBazel(path: string): string {
1532
if (!bazelBinDirectory || !bazelExecRoot) {
1633
return path;
1734
}
1835

19-
const fromExecRoot = relative(bazelExecRoot, path);
36+
const execRoot = effectiveExecRoot() ?? bazelExecRoot;
37+
38+
const fromExecRoot = relative(execRoot, path);
2039
if (!fromExecRoot.startsWith('..')) {
2140
return path;
2241
}
2342

2443
const fromBinDirectory = relative(bazelBinDirectory, path);
25-
if (fromBinDirectory.startsWith('..')) {
26-
return path;
44+
if (!fromBinDirectory.startsWith('..')) {
45+
return join(execRoot, fromBinDirectory);
46+
}
47+
48+
// A path that realpath resolved out of a symlink-staged sandbox into the
49+
// unsandboxed execroot: re-anchor its execroot-relative tail.
50+
const markerIndex = path.indexOf(execRootMarker);
51+
if (markerIndex !== -1) {
52+
const tail = path.slice(markerIndex + execRootMarker.length);
53+
const workspaceEnd = tail.indexOf(sep);
54+
if (workspaceEnd !== -1) {
55+
return join(execRoot, tail.slice(workspaceEnd + 1));
56+
}
2757
}
2858

29-
return join(bazelExecRoot, fromBinDirectory);
59+
return path;
3060
}

0 commit comments

Comments
 (0)