| 79 | } |
| 80 | |
| 81 | async function main() { |
| 82 | const start = new Date(); |
| 83 | |
| 84 | if (!options.noBuild) { |
| 85 | console.log("building codebase..."); |
| 86 | execSync("npm run build", { cwd: rootDir, stdio: "inherit", shell: true }); |
| 87 | } |
| 88 | |
| 89 | const files = await collectFiles(); |
| 90 | if (!files.length) { |
| 91 | console.log(chalk.red("No sample files matched.")); |
| 92 | process.exit(1); |
| 93 | } |
| 94 | |
| 95 | const launchArgs = process.env.CI ? ["--no-sandbox", "--disable-setuid-sandbox"] : []; |
| 96 | // generous protocol timeout: parallel screenshot-heavy runs can stall |
| 97 | // individual CDP calls well beyond the default |
| 98 | const browser = await puppeteer.launch({ args: launchArgs, protocolTimeout: 600000 }); |
| 99 | |
| 100 | const server = startServer(); |
| 101 | |
| 102 | console.log(`starting ${options.threads} thread(s), ${files.length} sample(s)`); |
| 103 | const state = { files, failed: [], status: true, index: 0 }; |
| 104 | const workers = []; |
| 105 | for (let i = 0; i < options.threads; i++) { |
| 106 | workers.push(runSmoke(browser, state)); |
| 107 | } |
| 108 | await Promise.all(workers).catch((e) => { |
| 109 | state.status = false; |
| 110 | console.log(chalk.red(e.toString())); |
| 111 | }); |
| 112 | |
| 113 | await browser.close(); |
| 114 | server.close(); |
| 115 | |
| 116 | const time = Math.round((new Date() - start) / 1000); |
| 117 | console.log(`Done ${files.length} samples in ${time}s`); |
| 118 | |
| 119 | if (state.status) { |
| 120 | console.log(chalk.green("All is fine!")); |
| 121 | process.exit(0); |
| 122 | } else { |
| 123 | console.log(chalk.red("Some problems detected:")); |
| 124 | console.log(chalk.red(" - " + state.failed.map(f => relSample(f)).join("\n - "))); |
| 125 | process.exit(1); |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | main(); |