From 8250b93697e4812b5532a5e9ff13d11b3d8ea23b Mon Sep 17 00:00:00 2001 From: Bart Kalisz Date: Tue, 4 Jun 2024 13:36:51 +0200 Subject: [PATCH] try using spawn --- bin/plugin/commands/performance.js | 23 ++++++--- bin/plugin/lib/utils.js | 76 +++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 24 deletions(-) diff --git a/bin/plugin/commands/performance.js b/bin/plugin/commands/performance.js index a945319a5491b1..59dd1db823b64d 100644 --- a/bin/plugin/commands/performance.js +++ b/bin/plugin/commands/performance.js @@ -159,7 +159,8 @@ function printStats( m, s ) { */ async function runTestSuite( testSuite, testRunnerDir, runKey ) { await runShellScript( - `npm run test:performance -- ${ testSuite }`, + 'npm', + [ 'run', 'test:performance', '--', testSuite ], testRunnerDir, { ...process.env, @@ -329,7 +330,7 @@ async function runPerformanceTests( branches, options ) { const testRunnerDir = path.join( baseDir + '/tests' ); logAtIndent( 2, 'Copying source to:', formats.success( testRunnerDir ) ); - await runShellScript( `cp -R ${ sourceDir } ${ testRunnerDir }` ); + await runShellScript( 'cp', [ '-R', sourceDir, testRunnerDir ] ); logAtIndent( 2, @@ -341,7 +342,11 @@ async function runPerformanceTests( branches, options ) { logAtIndent( 2, 'Installing dependencies and building' ); await runShellScript( - `bash -c "source $HOME/.nvm/nvm.sh && nvm install && npm ci && npx playwright install chromium --with-deps && npm run build:packages"`, + 'bash', + [ + '-c', + '"source $HOME/.nvm/nvm.sh && nvm install && npm ci && npx playwright install chromium --with-deps && npm run build:packages"', + ], testRunnerDir ); @@ -376,7 +381,7 @@ async function runPerformanceTests( branches, options ) { const buildDir = path.join( envDir, 'plugin' ); logAtIndent( 3, 'Copying source to:', formats.success( buildDir ) ); - await runShellScript( `cp -R ${ sourceDir } ${ buildDir }` ); + await runShellScript( 'cp', [ '-R', sourceDir, buildDir ] ); logAtIndent( 3, 'Checking out:', formats.success( branch ) ); // @ts-ignore @@ -384,7 +389,11 @@ async function runPerformanceTests( branches, options ) { logAtIndent( 3, 'Installing dependencies and building' ); await runShellScript( - `bash -c "source $HOME/.nvm/nvm.sh && nvm install && npm ci && npm run build"`, + 'bash', + [ + '-c', + '"source $HOME/.nvm/nvm.sh && nvm install && npm ci && npm run build"', + ], buildDir ); @@ -479,13 +488,13 @@ async function runPerformanceTests( branches, options ) { const envDir = branchDirs[ branch ]; logAtIndent( 3, 'Starting environment' ); - await runShellScript( `${ wpEnvPath } start`, envDir ); + await runShellScript( wpEnvPath, [ 'start' ], envDir ); logAtIndent( 3, 'Running tests' ); await runTestSuite( testSuite, testRunnerDir, runKey ); logAtIndent( 3, 'Stopping environment' ); - await runShellScript( `${ wpEnvPath } stop`, envDir ); + await runShellScript( wpEnvPath, [ 'stop' ], envDir ); } } } diff --git a/bin/plugin/lib/utils.js b/bin/plugin/lib/utils.js index 0e20989ac526c7..67a45fabb3b6be 100644 --- a/bin/plugin/lib/utils.js +++ b/bin/plugin/lib/utils.js @@ -4,8 +4,7 @@ // @ts-ignore const inquirer = require( 'inquirer' ); const fs = require( 'fs' ); -const { promisify } = require( 'util' ); -const childProcess = require( 'child_process' ); +const { spawn } = require( 'child_process' ); const { v4: uuid } = require( 'uuid' ); const path = require( 'path' ); const os = require( 'os' ); @@ -20,22 +19,65 @@ const { log, formats } = require( './logger' ); * * @typedef {NodeJS.ProcessEnv} Env * - * @param {string} script Script to run. - * @param {string=} cwd Working directory. - * @param {Env=} env Additional environment variables to pass to the script. + * @param {string} command + * @param {string[]} args + * @param {string=} cwd Current working directory. + * @param {Env=} env Environment variables. + * @param {boolean=} shell Use shell. */ -async function runShellScript( script, cwd, env = {} ) { - const execPromisified = promisify( childProcess.exec ); - - return await execPromisified( script, { - cwd, - env: { - NO_CHECKS: 'true', - PATH: process.env.PATH, - HOME: process.env.HOME, - USER: process.env.USER, - ...env, - }, +async function runShellScript( command, args, cwd, env = {}, shell = false ) { + if ( ! command ) { + throw new Error( 'No command provided' ); + } + + return new Promise( ( resolve, reject ) => { + const child = spawn( command, args, { + cwd, + env: { + NO_CHECKS: 'true', + PATH: process.env.PATH, + HOME: process.env.HOME, + USER: process.env.USER, + ...env, + }, + shell: /cp|bash/.test( command ) ? true : shell, + stdio: 'inherit', + } ); + + let stdout = ''; + let stderr = ''; + + if ( child.stdout ) { + child.stdout.on( 'data', ( data ) => { + const dataStr = data.toString(); + stdout += dataStr; + process.stdout.write( dataStr ); // Print to console in real-time + } ); + } + + if ( child.stderr ) { + child.stderr.on( 'data', ( data ) => { + const dataStr = data.toString(); + stderr += dataStr; + process.stderr.write( dataStr ); // Print to console in real-time + } ); + } + + child.on( 'close', ( code ) => { + if ( code === 0 ) { + resolve( { stdout, stderr } ); + } else { + reject( + new Error( + `Process exited with code ${ code }: ${ stderr }` + ) + ); + } + } ); + + child.on( 'error', ( error ) => { + reject( error ); + } ); } ); }