diff --git a/src/util/fs/executeScript.test.ts b/src/util/fs/executeScript.test.ts index 81b3ea2..80a8063 100644 --- a/src/util/fs/executeScript.test.ts +++ b/src/util/fs/executeScript.test.ts @@ -1,4 +1,5 @@ import { execFile } from 'child_process'; +import { resolve } from 'path'; import executeScript from './executeScript.js'; jest.mock('child_process', () => ({ @@ -70,6 +71,25 @@ describe('executeScript', () => { ); }); + it('resolves relative hook paths before changing the working directory', async () => { + expect.assertions(1); + const scriptPath = 'project/.cli/init.js'; + const resolvedScriptPath = resolve(scriptPath); + mockExecFileResult(null, 'done'); + + await executeScript(scriptPath); + + expect(execFileMock).toHaveBeenCalledWith( + process.execPath, + [resolvedScriptPath], + { + cwd: resolve('project/.cli'), + encoding: 'utf8', + }, + expect.any(Function), + ); + }); + it('resolves stderr when stdout is empty', async () => { expect.assertions(1); mockExecFileResult(null, '', 'well, that went poorly'); diff --git a/src/util/fs/executeScript.ts b/src/util/fs/executeScript.ts index 3e86836..0220943 100644 --- a/src/util/fs/executeScript.ts +++ b/src/util/fs/executeScript.ts @@ -1,5 +1,5 @@ import { execFile } from 'child_process'; -import { dirname } from 'path'; +import { dirname, resolve as resolvePath } from 'path'; /** * Takes a path to a script, and executes it. @@ -9,14 +9,16 @@ import { dirname } from 'path'; export default async function executeScript( scriptPath: string, ): Promise { + const resolvedScriptPath = resolvePath(scriptPath); + return new Promise((resolve, reject) => { execFile( process.execPath, - [scriptPath], + [resolvedScriptPath], { // Run from the hook directory so hook-relative file operations do not // depend on the shell location that invoked the CLI. - cwd: dirname(scriptPath), + cwd: dirname(resolvedScriptPath), encoding: 'utf8', }, (error, stdout, stderr) => { @@ -25,7 +27,7 @@ export default async function executeScript( return reject( new Error( - `Unable to execute hook script "${scriptPath}": ${output}`, + `Unable to execute hook script "${resolvedScriptPath}": ${output}`, ), ); }