diff --git a/scripts/changed-lanes.mjs b/scripts/changed-lanes.mjs index 92263af7189..eb83d6c2d3a 100644 --- a/scripts/changed-lanes.mjs +++ b/scripts/changed-lanes.mjs @@ -1,5 +1,6 @@ import { execFileSync } from "node:child_process"; import { appendFileSync } from "node:fs"; +import { booleanFlag, parseFlagArgs, stringFlag } from "./lib/arg-utils.mjs"; const DOCS_PATH_RE = /^(?:docs\/|README\.md$|AGENTS\.md$|.*\.mdx?$)/u; const APP_PATH_RE = /^(?:apps\/|Swabble\/|appcast\.xml$)/u; @@ -221,33 +222,23 @@ function parseArgs(argv) { githubOutput: false, paths: [], }; - for (let index = 0; index < argv.length; index += 1) { - const arg = argv[index]; - if (arg === "--base") { - args.base = argv[index + 1] ?? args.base; - index += 1; - continue; - } - if (arg === "--head") { - args.head = argv[index + 1] ?? args.head; - index += 1; - continue; - } - if (arg === "--staged") { - args.staged = true; - continue; - } - if (arg === "--json") { - args.json = true; - continue; - } - if (arg === "--github-output") { - args.githubOutput = true; - continue; - } - args.paths.push(arg); - } - return args; + return parseFlagArgs( + argv, + args, + [ + stringFlag("--base", "base"), + stringFlag("--head", "head"), + booleanFlag("--staged", "staged"), + booleanFlag("--json", "json"), + booleanFlag("--github-output", "githubOutput"), + ], + { + onUnhandledArg(arg, target) { + target.paths.push(arg); + return "handled"; + }, + }, + ); } function isDirectRun() { diff --git a/scripts/check-changed.mjs b/scripts/check-changed.mjs index 8a8609e0c10..3414885d7f8 100644 --- a/scripts/check-changed.mjs +++ b/scripts/check-changed.mjs @@ -6,6 +6,8 @@ import { listStagedChangedPaths, normalizeChangedPath, } from "./changed-lanes.mjs"; +import { booleanFlag, parseFlagArgs, stringFlag } from "./lib/arg-utils.mjs"; +import { printTimingSummary } from "./lib/check-timing-summary.mjs"; const ROUTABLE_TEST_PATH_RE = /^(?:src|test|extensions|ui|packages|apps)(?:\/|$)/u; @@ -199,23 +201,7 @@ async function runCommand(command, timings) { } function printSummary(timings, options) { - if (!options.timed && timings.every((timing) => timing.status === 0)) { - return; - } - console.error("\n[check:changed] summary"); - for (const timing of timings) { - const status = timing.status === 0 ? "ok" : `failed:${timing.status}`; - console.error( - `${formatMs(timing.durationMs).padStart(8)} ${status.padEnd(9)} ${timing.name}`, - ); - } -} - -function formatMs(durationMs) { - if (durationMs < 1000) { - return `${Math.round(durationMs)}ms`; - } - return `${(durationMs / 1000).toFixed(2)}s`; + printTimingSummary("check:changed", timings, { skipWhenAllOk: !options.timed }); } function parseArgs(argv) { @@ -227,33 +213,23 @@ function parseArgs(argv) { timed: false, paths: [], }; - for (let index = 0; index < argv.length; index += 1) { - const arg = argv[index]; - if (arg === "--base") { - args.base = argv[index + 1] ?? args.base; - index += 1; - continue; - } - if (arg === "--head") { - args.head = argv[index + 1] ?? args.head; - index += 1; - continue; - } - if (arg === "--staged") { - args.staged = true; - continue; - } - if (arg === "--dry-run") { - args.dryRun = true; - continue; - } - if (arg === "--timed") { - args.timed = true; - continue; - } - args.paths.push(normalizeChangedPath(arg)); - } - return args; + return parseFlagArgs( + argv, + args, + [ + stringFlag("--base", "base"), + stringFlag("--head", "head"), + booleanFlag("--staged", "staged"), + booleanFlag("--dry-run", "dryRun"), + booleanFlag("--timed", "timed"), + ], + { + onUnhandledArg(arg, target) { + target.paths.push(normalizeChangedPath(arg)); + return "handled"; + }, + }, + ); } function isDirectRun() { diff --git a/scripts/check.mjs b/scripts/check.mjs index 007f4be6fa8..3747d4490a9 100644 --- a/scripts/check.mjs +++ b/scripts/check.mjs @@ -1,5 +1,6 @@ import { spawn } from "node:child_process"; import { performance } from "node:perf_hooks"; +import { printTimingSummary } from "./lib/check-timing-summary.mjs"; export async function main(argv = process.argv.slice(2)) { const timed = argv.includes("--timed"); @@ -110,20 +111,7 @@ async function runCommand(command) { } function printSummary(timings) { - console.error("\n[check] summary"); - for (const timing of timings) { - const status = timing.status === 0 ? "ok" : `failed:${timing.status}`; - console.error( - `${formatMs(timing.durationMs).padStart(8)} ${status.padEnd(9)} ${timing.name}`, - ); - } -} - -function formatMs(durationMs) { - if (durationMs < 1000) { - return `${Math.round(durationMs)}ms`; - } - return `${(durationMs / 1000).toFixed(2)}s`; + printTimingSummary("check", timings); } if (import.meta.main) { diff --git a/scripts/lib/check-timing-summary.mjs b/scripts/lib/check-timing-summary.mjs new file mode 100644 index 00000000000..955021d4e2d --- /dev/null +++ b/scripts/lib/check-timing-summary.mjs @@ -0,0 +1,20 @@ +export function formatMs(durationMs) { + if (durationMs < 1000) { + return `${Math.round(durationMs)}ms`; + } + return `${(durationMs / 1000).toFixed(2)}s`; +} + +export function printTimingSummary(label, timings, options = {}) { + if (options.skipWhenAllOk && timings.every((timing) => timing.status === 0)) { + return; + } + + console.error(`\n[${label}] summary`); + for (const timing of timings) { + const status = timing.status === 0 ? "ok" : `failed:${timing.status}`; + console.error( + `${formatMs(timing.durationMs).padStart(8)} ${status.padEnd(9)} ${timing.name}`, + ); + } +}