Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CI] Use execFile for quick-checks #191638

Merged
merged 2 commits into from
Aug 30, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 45 additions & 14 deletions src/dev/run_quick_checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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}...`,
Expand Down Expand Up @@ -108,7 +108,7 @@ function collectScriptsToRun(inputOptions: {
}
}

async function runAllChecks(scriptsToRun: string[]) {
async function runAllChecks(scriptsToRun: string[]): Promise<CheckResult[]> {
const checksRunning: Array<Promise<any>> = [];
const checksFinished: CheckResult[] = [];

Expand All @@ -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);
Expand All @@ -138,9 +148,10 @@ async function runCheckAsync(script: string): Promise<CheckResult> {
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);
Expand Down Expand Up @@ -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 {
Expand All @@ -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, '');
}