



























@@ -6,8 +6,10 @@ import os from "node:os";
66import path from "node:path";
77import process from "node:process";
88import {
9+buildGauntletPrebuildEnv,
910collectGatewayCpuObservations,
1011collectMetricObservations,
12+collectQaBaselineRegressionObservations,
1113discoverBundledPluginManifests,
1214selectPluginEntries,
1315} from "./lib/plugin-gateway-gauntlet.mjs";
@@ -39,6 +41,7 @@ function parseArgs(argv) {
3941skipPrebuild: false,
4042skipLifecycle: false,
4143skipQa: false,
44+qaBaseline: false,
4245skipSlashHelp: false,
4346qaScenarios: [],
4447qaPluginChunkSize: DEFAULT_QA_PLUGIN_CHUNK_SIZE,
@@ -47,6 +50,8 @@ function parseArgs(argv) {
4750maxRssWarnMb: DEFAULT_MAX_RSS_WARN_MB,
4851wallAnomalyMultiplier: 3,
4952rssAnomalyMultiplier: 2.5,
53+qaCpuRegressionMultiplier: 2,
54+qaWallRegressionMultiplier: 2,
5055commandTimeoutMs: 120_000,
5156buildTimeoutMs: 600_000,
5257qaTimeoutMs: 900_000,
@@ -90,6 +95,9 @@ function parseArgs(argv) {
9095case "--qa-plugin-chunk-size":
9196options.qaPluginChunkSize = parsePositiveInt(readValue(), "--qa-plugin-chunk-size");
9297break;
98+case "--qa-baseline":
99+options.qaBaseline = true;
100+break;
93101case "--cpu-core-warn":
94102options.cpuCoreWarn = parsePositiveNumber(readValue(), "--cpu-core-warn");
95103break;
@@ -108,6 +116,18 @@ function parseArgs(argv) {
108116case "--rss-anomaly-multiplier":
109117options.rssAnomalyMultiplier = parsePositiveNumber(readValue(), "--rss-anomaly-multiplier");
110118break;
119+case "--qa-cpu-regression-multiplier":
120+options.qaCpuRegressionMultiplier = parsePositiveNumber(
121+readValue(),
122+"--qa-cpu-regression-multiplier",
123+);
124+break;
125+case "--qa-wall-regression-multiplier":
126+options.qaWallRegressionMultiplier = parsePositiveNumber(
127+readValue(),
128+"--qa-wall-regression-multiplier",
129+);
130+break;
111131case "--command-timeout-ms":
112132options.commandTimeoutMs = parsePositiveInt(readValue(), "--command-timeout-ms");
113133break;
@@ -156,6 +176,7 @@ Options:
156176 --output-dir <path> Artifact directory
157177 --qa-scenario <id> QA Lab scenario id, repeatable
158178 --qa-plugin-chunk-size <count> Plugins enabled per QA run (default: 12)
179+ --qa-baseline Run a no-extra-plugin QA baseline before plugin chunks
159180 --cpu-core-warn <ratio> Hot CPU threshold (default: 0.9)
160181 --hot-wall-warn-ms <ms> Minimum wall time for hot CPU observations (default: 30000)
161182 --max-rss-warn-mb <mb> Maximum RSS warning threshold (default: 1536)
@@ -416,19 +437,22 @@ function runSlashHelpProbes(params) {
416437}
417438418439function runQaChunks(params) {
419-const chunks = chunkArray(params.plugins, params.qaPluginChunkSize);
440+const chunks = [
441+ ...(params.qaBaseline ? [{ label: "baseline", plugins: [] }] : []),
442+ ...chunkArray(params.plugins, params.qaPluginChunkSize).map((plugins, index) => ({
443+label: `chunk-${String(index).padStart(2, "0")}`,
444+ plugins,
445+})),
446+];
420447const summaries = [];
421448for (let index = 0; index < chunks.length; index += 1) {
422449const chunk = chunks[index];
423-const outputDir = path.join(
424-params.outputDir,
425-"qa-suite",
426-`chunk-${String(index).padStart(2, "0")}`,
427-);
450+const outputDir = path.join(params.outputDir, "qa-suite", chunk.label);
428451const outputArg = toRepoRelativePath(params.repoRoot, outputDir);
429-const pluginIds = chunk.map((plugin) => plugin.id);
452+const pluginIds = chunk.plugins.map((plugin) => plugin.id);
453+const pluginIdLabel = pluginIds.length > 0 ? pluginIds.join(",") : "<baseline>";
430454process.stderr.write(
431-`[plugin-gauntlet] qa chunk ${index + 1}/${chunks.length}: ${pluginIds.join(",")}\n`,
455+`[plugin-gauntlet] qa chunk ${index + 1}/${chunks.length}: ${pluginIdLabel}\n`,
432456);
433457const row = runMeasuredCommand({
434458cwd: params.repoRoot,
@@ -446,14 +470,21 @@ function runQaChunks(params) {
446470 ...params.qaScenarios.flatMap((scenario) => ["--scenario", scenario]),
447471 ...pluginIds.flatMap((pluginId) => ["--enable-plugin", pluginId]),
448472]),
449-label: `qa-chunk-${String(index).padStart(2, "0")}`,
473+label: `qa-${chunk.label}`,
450474phase: "qa:rpc",
451475timeoutMs: params.qaTimeoutMs,
452476});
453-params.rows.push({ ...row, pluginId: pluginIds.join(",") });
454477const summaryPath = path.join(outputDir, "qa-suite-summary.json");
478+const qaSummary = fs.existsSync(summaryPath)
479+ ? JSON.parse(fs.readFileSync(summaryPath, "utf8"))
480+ : null;
481+params.rows.push({
482+ ...row,
483+pluginId: pluginIdLabel,
484+ ...(qaSummary?.metrics ? { qaMetrics: qaSummary.metrics } : {}),
485+});
455486if (fs.existsSync(summaryPath)) {
456-summaries.push(JSON.parse(fs.readFileSync(summaryPath, "utf8")));
487+summaries.push(qaSummary);
457488}
458489}
459490return summaries;
@@ -478,7 +509,7 @@ async function main() {
478509rows.push(
479510runMeasuredCommand({
480511cwd: repoRoot,
481- env,
512+env: buildGauntletPrebuildEnv(env, { includePrivateQa: !options.skipQa }),
482513logDir: path.join(options.outputDir, "logs", "prebuild"),
483514command: pnpmCommand(),
484515args: ["build"],
@@ -519,6 +550,7 @@ async function main() {
519550outputDir: options.outputDir,
520551 env,
521552plugins: selectedPlugins,
553+qaBaseline: options.qaBaseline,
522554 rows,
523555qaScenarios: options.qaScenarios,
524556qaPluginChunkSize: options.qaPluginChunkSize,
@@ -531,6 +563,10 @@ async function main() {
531563wallAnomalyMultiplier: options.wallAnomalyMultiplier,
532564rssAnomalyMultiplier: options.rssAnomalyMultiplier,
533565});
566+const qaBaselineObservations = collectQaBaselineRegressionObservations(rows, {
567+cpuRegressionMultiplier: options.qaCpuRegressionMultiplier,
568+wallRegressionMultiplier: options.qaWallRegressionMultiplier,
569+});
534570const gatewayObservations = qaSummaries.flatMap((qa) =>
535571collectGatewayCpuObservations({
536572startup: null,
@@ -554,6 +590,7 @@ async function main() {
554590limit: options.limit ?? null,
555591qaScenarios: options.qaScenarios,
556592qaPluginChunkSize: options.qaPluginChunkSize,
593+qaBaseline: options.qaBaseline,
557594skipLifecycle: options.skipLifecycle,
558595skipQa: options.skipQa,
559596skipSlashHelp: options.skipSlashHelp,
@@ -564,12 +601,14 @@ async function main() {
564601maxRssWarnMb: options.maxRssWarnMb,
565602wallAnomalyMultiplier: options.wallAnomalyMultiplier,
566603rssAnomalyMultiplier: options.rssAnomalyMultiplier,
604+qaCpuRegressionMultiplier: options.qaCpuRegressionMultiplier,
605+qaWallRegressionMultiplier: options.qaWallRegressionMultiplier,
567606},
568607},
569608 matrix,
570609 selectedPlugins,
571610 rows,
572-observations: [...metricObservations, ...gatewayObservations],
611+observations: [...metricObservations, ...qaBaselineObservations, ...gatewayObservations],
573612 failures,
574613};
575614const summaryPath = path.join(options.outputDir, "plugin-gateway-gauntlet-summary.json");
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。