diff --git a/src/dev/run_quick_checks.ts b/src/dev/run_quick_checks.ts index cdb59bdce3cb2..2fe4b712bdbb1 100644 --- a/src/dev/run_quick_checks.ts +++ b/src/dev/run_quick_checks.ts @@ -6,10 +6,10 @@ * Side Public License, v 1. */ -import { exec } from 'child_process'; +import { execFile } from 'child_process'; import { availableParallelism } from 'os'; -import { join, isAbsolute } from 'path'; -import { readdirSync, readFileSync } from 'fs'; +import { isAbsolute, join } from 'path'; +import { existsSync, readdirSync, readFileSync } from 'fs'; import { run, RunOptions } from '@kbn/dev-cli-runner'; import { REPO_ROOT } from '@kbn/repo-info'; @@ -54,7 +54,7 @@ void run(async ({ log, flagsReader }) => { targetFile: flagsReader.string('file'), targetDir: flagsReader.string('dir'), checks: flagsReader.string('checks'), - }); + }).map((script) => (isAbsolute(script) ? script : join(REPO_ROOT, script))); logger.write( `--- Running ${scriptsToRun.length} checks, with parallelism ${MAX_PARALLELISM}...`, @@ -108,7 +108,7 @@ function collectScriptsToRun(inputOptions: { } } -async function runAllChecks(scriptsToRun: string[]) { +async function runAllChecks(scriptsToRun: string[]): Promise { const checksRunning: Array> = []; const checksFinished: CheckResult[] = []; @@ -121,10 +121,20 @@ async function runAllChecks(scriptsToRun: string[]) { const check = runCheckAsync(script); checksRunning.push(check); - check.then((result) => { - checksRunning.splice(checksRunning.indexOf(check), 1); - checksFinished.push(result); - }); + check + .then((result) => { + checksRunning.splice(checksRunning.indexOf(check), 1); + checksFinished.push(result); + }) + .catch((error) => { + checksRunning.splice(checksRunning.indexOf(check), 1); + checksFinished.push({ + success: false, + script, + output: error.message, + durationMs: 0, + }); + }); } await sleep(1000); @@ -138,9 +148,10 @@ async function runCheckAsync(script: string): Promise { const startTime = Date.now(); return new Promise((resolve) => { - const scriptProcess = exec(script); + validateScriptPath(script); + const scriptProcess = execFile('bash', [script]); let output = ''; - const appendToOutput = (data: string | Buffer) => (output += data); + const appendToOutput = (data: string | Buffer) => (output += data.toString()); scriptProcess.stdout?.on('data', appendToOutput); scriptProcess.stderr?.on('data', appendToOutput); @@ -170,9 +181,10 @@ function printResults(startTimestamp: number, results: CheckResult[]) { logger.info(`- Total time: ${total}, effective: ${effective}`); results.forEach((result) => { - logger.write( - `--- ${result.success ? '✅' : '❌'} ${result.script}: ${humanizeTime(result.durationMs)}` - ); + const resultLabel = result.success ? '✅' : '❌'; + const scriptPath = stripRoot(result.script); + const runtime = humanizeTime(result.durationMs); + logger.write(`--- ${resultLabel} ${scriptPath}: ${runtime}`); if (result.success) { logger.debug(result.output); } else { @@ -194,3 +206,22 @@ function humanizeTime(ms: number) { return `${minutes}m ${seconds}s`; } } + +function validateScriptPath(scriptPath: string) { + if (!isAbsolute(scriptPath)) { + logger.error(`Invalid script path: ${scriptPath}`); + throw new Error('Invalid script path'); + } else if (!scriptPath.endsWith('.sh')) { + logger.error(`Invalid script extension: ${scriptPath}`); + throw new Error('Invalid script extension'); + } else if (!existsSync(scriptPath)) { + logger.error(`Script not found: ${scriptPath}`); + throw new Error('Script not found'); + } else { + return; + } +} + +function stripRoot(script: string) { + return script.replace(REPO_ROOT, ''); +}