Skip to content

Commit 13510ad

Browse files
committed
fix(builtin): under runfiles linker should link node_modules folder at root of runfiles tree
Current it is link node_modules folder in the cwd which is `runfiles/wksp/node_modules` but this location means that script in external repositories such as `runfiles/external_wksp/path/to/script.js` will not resolve packages. This PR changes the linker to link to `runfiles/node_modules`.
1 parent ee7bc69 commit 13510ad

File tree

3 files changed

+24
-13
lines changed

3 files changed

+24
-13
lines changed

internal/linker/index.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ Include as much of the build output as you can without disclosing anything confi
112112
*/
113113
function resolveRoot(root, runfiles) {
114114
return __awaiter(this, void 0, void 0, function* () {
115+
if (!runfiles.execroot) {
116+
// Under runfiles, the repository should be layed out in the parent directory
117+
// since bazel sets our working directory to the repository where the build is happening
118+
process.chdir('..');
119+
}
115120
// create a node_modules directory if no root
116121
// this will be the case if only first-party modules are installed
117122
if (!root) {
@@ -135,7 +140,7 @@ Include as much of the build output as you can without disclosing anything confi
135140
else {
136141
// Under runfiles, the repository should be layed out in the parent directory
137142
// since bazel sets our working directory to the repository where the build is happening
138-
return path.join('..', root);
143+
return root;
139144
}
140145
});
141146
}
@@ -425,12 +430,14 @@ Include as much of the build output as you can without disclosing anything confi
425430
const [modulesManifest] = args;
426431
let { bin, root, modules, workspace } = JSON.parse(fs.readFileSync(modulesManifest));
427432
modules = modules || {};
428-
log_verbose(`module manifest '${modulesManifest}': workspace ${workspace}, bin ${bin}, root ${root} with first-party packages\n`, modules);
433+
log_verbose('manifest file', modulesManifest);
434+
log_verbose('manifest contents', JSON.stringify({ workspace, bin, root, modules }, null, 2));
435+
// Bazel starts actions with pwd=execroot/my_wksp
436+
const workspaceDir = path.resolve('.');
437+
// resolveRoot will change the cwd when under runfiles
429438
const rootDir = yield resolveRoot(root, runfiles);
430439
log_verbose('resolved root', root, 'to', rootDir);
431440
log_verbose('cwd', process.cwd());
432-
// Bazel starts actions with pwd=execroot/my_wksp
433-
const workspaceDir = path.resolve('.');
434441
// Create the $pwd/node_modules directory that node will resolve from
435442
yield symlink(rootDir, 'node_modules');
436443
process.chdir(rootDir);

internal/linker/link_node_modules.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ async function symlink(target: string, p: string): Promise<boolean> {
9595
* @param root a string like 'npm/node_modules'
9696
*/
9797
async function resolveRoot(root: string|undefined, runfiles: Runfiles) {
98+
if (!runfiles.execroot) {
99+
// Under runfiles, the repository should be layed out in the parent directory
100+
// since bazel sets our working directory to the repository where the build is happening
101+
process.chdir('..');
102+
}
98103
// create a node_modules directory if no root
99104
// this will be the case if only first-party modules are installed
100105
if (!root) {
@@ -118,7 +123,7 @@ async function resolveRoot(root: string|undefined, runfiles: Runfiles) {
118123
} else {
119124
// Under runfiles, the repository should be layed out in the parent directory
120125
// since bazel sets our working directory to the repository where the build is happening
121-
return path.join('..', root);
126+
return root;
122127
}
123128
}
124129

@@ -485,18 +490,17 @@ export async function main(args: string[], runfiles: Runfiles) {
485490
const [modulesManifest] = args;
486491
let {bin, root, modules, workspace} = JSON.parse(fs.readFileSync(modulesManifest));
487492
modules = modules || {};
488-
log_verbose(
489-
`module manifest '${modulesManifest}': workspace ${workspace}, bin ${bin}, root ${
490-
root} with first-party packages\n`,
491-
modules);
493+
log_verbose('manifest file', modulesManifest);
494+
log_verbose('manifest contents', JSON.stringify({workspace, bin, root, modules}, null, 2));
492495

496+
// Bazel starts actions with pwd=execroot/my_wksp
497+
const workspaceDir = path.resolve('.');
498+
499+
// resolveRoot will change the cwd when under runfiles
493500
const rootDir = await resolveRoot(root, runfiles);
494501
log_verbose('resolved root', root, 'to', rootDir);
495502
log_verbose('cwd', process.cwd());
496503

497-
// Bazel starts actions with pwd=execroot/my_wksp
498-
const workspaceDir = path.resolve('.');
499-
500504
// Create the $pwd/node_modules directory that node will resolve from
501505
await symlink(rootDir, 'node_modules');
502506
process.chdir(rootDir);

internal/linker/test/link_node_modules.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,6 @@ describe('link_node_modules', () => {
532532

533533
// The linker expects to run as its own process, so it changes the wd
534534
process.chdir(path.join(process.env['TEST_TMPDIR']!, workspace));
535-
expect(fs.readdirSync(path.join('node_modules', 'some-package'))).toContain('index.js');
535+
expect(fs.readdirSync(path.join('..', 'node_modules', 'some-package'))).toContain('index.js');
536536
});
537537
});

0 commit comments

Comments
 (0)