Skip to content

Commit 63d0170

Browse files
Merge pull request #32103 from storybookjs/yann/automigration-failure-telemetry
Telemetry: Add automigration errors
2 parents c22986b + 4345344 commit 63d0170

File tree

2 files changed

+55
-36
lines changed

2 files changed

+55
-36
lines changed

code/lib/cli-storybook/src/automigrate/multi-project.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { JsPackageManager } from 'storybook/internal/common';
22
import { CLI_COLORS, type TaskLogInstance, logger, prompt } from 'storybook/internal/node-logger';
3+
import { sanitizeError } from 'storybook/internal/telemetry';
34
import type { StorybookConfigRaw } from 'storybook/internal/types';
45

56
import type { UpgradeOptions } from '../upgrade';
@@ -246,20 +247,24 @@ export async function promptForAutomigrations(
246247
return automigrations.filter((am) => selectedIds.includes(am.fix.id));
247248
}
248249

250+
// Group automigrations by project
251+
type ConfigDir = string;
252+
type ErrorMessage = string;
253+
export type AutomigrationResult = {
254+
automigrationStatuses: Record<FixId, FixStatus>;
255+
automigrationErrors: Record<FixId, ErrorMessage>;
256+
};
249257
/** Runs selected automigrations for each project */
250258
export async function runAutomigrationsForProjects(
251259
selectedAutomigrations: AutomigrationCheckResult[],
252260
options: MultiProjectRunAutomigrationOptions
253-
): Promise<Record<string, Record<FixId, FixStatus>>> {
261+
): Promise<Record<ConfigDir, AutomigrationResult>> {
254262
const { dryRun, skipInstall, automigrations } = options;
255-
const projectResults: Record<ConfigDir, Record<FixId, FixStatus>> = {};
263+
const projectResults: Record<ConfigDir, AutomigrationResult> = {};
256264

257265
const applicableAutomigrations = selectedAutomigrations.filter((am) =>
258266
am.reports.every((rep) => rep.status !== 'not_applicable')
259267
);
260-
261-
// Group automigrations by project
262-
type ConfigDir = string;
263268
const projectAutomigrationResults = new Map<
264269
ConfigDir,
265270
{
@@ -327,6 +332,7 @@ export async function runAutomigrationsForProjects(
327332
},
328333
};
329334
const fixResults: Record<FixId, FixStatus> = {};
335+
const fixFailures: Record<FixId, ErrorMessage> = {};
330336

331337
for (const automigration of projectAutomigration) {
332338
const { fix, result, project, status } = automigration;
@@ -374,9 +380,12 @@ export async function runAutomigrationsForProjects(
374380
taskLog.message(CLI_COLORS.success(`${logger.SYMBOLS.success} ${fix.id}`));
375381
}
376382
} catch (error) {
383+
const errorMessage =
384+
(error instanceof Error ? error.stack : String(error)) ?? 'Unknown error';
377385
fixResults[fix.id] = FixStatus.FAILED;
386+
fixFailures[fix.id] = sanitizeError(error as Error);
378387
taskLog.message(CLI_COLORS.error(`${logger.SYMBOLS.error} ${automigration.fix.id}`));
379-
logger.debug(`${error instanceof Error ? error.stack : String(error)}`);
388+
logger.debug(errorMessage);
380389
}
381390
}
382391

@@ -391,7 +400,10 @@ export async function runAutomigrationsForProjects(
391400
taskLog.success(`${countPrefix}Completed automigrations for ${projectName}`);
392401
}
393402

394-
projectResults[configDir] = fixResults;
403+
projectResults[configDir] = {
404+
automigrationStatuses: fixResults,
405+
automigrationErrors: fixFailures,
406+
};
395407
}
396408

397409
return projectResults;
@@ -402,7 +414,7 @@ export async function runAutomigrations(
402414
options: UpgradeOptions
403415
): Promise<{
404416
detectedAutomigrations: AutomigrationCheckResult[];
405-
automigrationResults: Record<string, Record<FixId, FixStatus>>;
417+
automigrationResults: Record<string, AutomigrationResult>;
406418
}> {
407419
// Prepare project data for automigrations
408420
const projectAutomigrationData: ProjectAutomigrationData[] = projects.map((project) => ({
@@ -453,13 +465,13 @@ export async function runAutomigrations(
453465

454466
// Special case handling for rnstorybook-config which renames the config dir
455467
// TODO: Remove this as soon as the rn-storybook-config automigration is removed
456-
Object.entries(automigrationResults).forEach(([configDir, fixResults]) => {
457-
if (fixResults[rnstorybookConfig.id] === FixStatus.SUCCEEDED) {
468+
Object.entries(automigrationResults).forEach(([configDir, resultData]) => {
469+
if (resultData.automigrationStatuses[rnstorybookConfig.id] === FixStatus.SUCCEEDED) {
458470
const project = projects.find((p) => p.configDir === configDir);
459471
if (project) {
460472
const oldConfigDir = project.configDir;
461473
project.configDir = project.configDir.replace('.storybook', '.rnstorybook');
462-
automigrationResults[project.configDir] = fixResults;
474+
automigrationResults[project.configDir] = resultData;
463475
delete automigrationResults[oldConfigDir];
464476
}
465477
}

code/lib/cli-storybook/src/upgrade.ts

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ import semver, { clean, lt } from 'semver';
2121
import { dedent } from 'ts-dedent';
2222

2323
import { processAutoblockerResults } from './autoblock/utils';
24-
import { type AutomigrationCheckResult, runAutomigrations } from './automigrate/multi-project';
25-
import type { FixId } from './automigrate/types';
24+
import {
25+
type AutomigrationCheckResult,
26+
type AutomigrationResult,
27+
runAutomigrations,
28+
} from './automigrate/multi-project';
2629
import { FixStatus } from './automigrate/types';
2730
import { displayDoctorResults, runMultiProjectDoctor } from './doctor';
2831
import type { ProjectDoctorData, ProjectDoctorResults } from './doctor/types';
@@ -127,30 +130,32 @@ export type UpgradeOptions = {
127130
};
128131

129132
function getUpgradeResults(
130-
projectResults: Record<string, Record<FixId, FixStatus>>,
133+
projectResults: Record<string, AutomigrationResult>,
131134
doctorResults: Record<string, ProjectDoctorResults>
132135
) {
133136
const successfulProjects: string[] = [];
134137
const failedProjects: string[] = [];
135138
const projectsWithNoFixes: string[] = [];
136139

137-
const allProjects = Object.entries(projectResults).map(([configDir, fixResults]) => {
138-
const automigrationResults = Object.entries(fixResults).map(([fixId, status]) => {
139-
const succeeded = status === FixStatus.SUCCEEDED || status === FixStatus.MANUAL_SUCCEEDED;
140-
return {
141-
fixId,
142-
status,
143-
succeeded,
144-
};
145-
});
140+
const allProjects = Object.entries(projectResults).map(([configDir, resultData]) => {
141+
const automigrationResults = Object.entries(resultData.automigrationStatuses).map(
142+
([fixId, status]) => {
143+
const succeeded = status === FixStatus.SUCCEEDED || status === FixStatus.MANUAL_SUCCEEDED;
144+
return {
145+
fixId,
146+
status,
147+
succeeded,
148+
};
149+
}
150+
);
146151

147152
const hasFailures = automigrationResults.some(
148153
(fix) => fix.status === FixStatus.FAILED || fix.status === FixStatus.CHECK_FAILED
149154
);
150155
const hasSuccessfulFixes = automigrationResults.some(
151156
(fix) => fix.status === FixStatus.SUCCEEDED || fix.status === FixStatus.MANUAL_SUCCEEDED
152157
);
153-
const noFixesNeeded = Object.keys(fixResults).length === 0;
158+
const noFixesNeeded = Object.keys(resultData.automigrationStatuses).length === 0;
154159

155160
// Determine if migration was successful (has successful fixes and no failures)
156161
const migratedSuccessfully = hasSuccessfulFixes && !hasFailures;
@@ -196,7 +201,7 @@ function getUpgradeResults(
196201

197202
/** Logs the results of the upgrade process, including project categorization and diagnostic messages */
198203
function logUpgradeResults(
199-
projectResults: Record<string, Record<FixId, FixStatus>>,
204+
projectResults: Record<string, AutomigrationResult>,
200205
detectedAutomigrations: AutomigrationCheckResult[],
201206
doctorResults: Record<string, ProjectDoctorResults>
202207
) {
@@ -242,10 +247,10 @@ function logUpgradeResults(
242247
const automigrationLinks = detectedAutomigrations
243248
.filter((am) =>
244249
Object.entries(projectResults).some(
245-
([_, fixResults]) =>
246-
fixResults[am.fix.id] === FixStatus.FAILED ||
247-
fixResults[am.fix.id] === FixStatus.SUCCEEDED ||
248-
fixResults[am.fix.id] === FixStatus.CHECK_FAILED
250+
([_, resultData]) =>
251+
resultData.automigrationStatuses[am.fix.id] === FixStatus.FAILED ||
252+
resultData.automigrationStatuses[am.fix.id] === FixStatus.SUCCEEDED ||
253+
resultData.automigrationStatuses[am.fix.id] === FixStatus.CHECK_FAILED
249254
)
250255
)
251256
.map((am) => `• ${createHyperlink(am.fix.id, am.fix.link!)}`);
@@ -267,7 +272,7 @@ function logUpgradeResults(
267272
interface MultiUpgradeTelemetryOptions {
268273
allProjects: CollectProjectsSuccessResult[];
269274
selectedProjects: CollectProjectsSuccessResult[];
270-
projectResults: Record<string, Record<FixId, FixStatus>>;
275+
projectResults: Record<string, AutomigrationResult>;
271276
doctorResults: Record<string, ProjectDoctorResults>;
272277
hasUserInterrupted?: boolean;
273278
}
@@ -339,7 +344,7 @@ export async function upgrade(options: UpgradeOptions): Promise<void> {
339344
);
340345
}
341346

342-
const automigrationResults: Record<string, Record<FixId, FixStatus>> = {};
347+
const automigrationResults: Record<string, AutomigrationResult> = {};
343348
let doctorResults: Record<string, ProjectDoctorResults> = {};
344349

345350
// Set up signal handling for interruptions
@@ -481,7 +486,10 @@ export async function upgrade(options: UpgradeOptions): Promise<void> {
481486
// TELEMETRY
482487
if (!options.disableTelemetry) {
483488
for (const project of storybookProjects) {
484-
const fixResults = automigrationResults[project.configDir] || {};
489+
const resultData = automigrationResults[project.configDir] || {
490+
automigrationStatuses: {},
491+
automigrationErrors: {},
492+
};
485493
let doctorFailureCount = 0;
486494
let doctorErrorCount = 0;
487495
Object.values(doctorResults[project.configDir]?.diagnostics || {}).forEach((status) => {
@@ -493,9 +501,7 @@ export async function upgrade(options: UpgradeOptions): Promise<void> {
493501
doctorErrorCount++;
494502
}
495503
});
496-
const automigrationFailureCount = Object.values(fixResults).filter(
497-
(status) => status === 'failed'
498-
).length;
504+
const automigrationFailureCount = Object.keys(resultData.automigrationErrors).length;
499505
const automigrationPreCheckFailure =
500506
project.autoblockerCheckResults && project.autoblockerCheckResults.length > 0
501507
? project.autoblockerCheckResults
@@ -510,7 +516,8 @@ export async function upgrade(options: UpgradeOptions): Promise<void> {
510516
await telemetry('upgrade', {
511517
beforeVersion: project.beforeVersion,
512518
afterVersion: project.currentCLIVersion,
513-
automigrationResults: fixResults,
519+
automigrationResults: resultData.automigrationStatuses,
520+
automigrationErrors: resultData.automigrationErrors,
514521
automigrationFailureCount,
515522
automigrationPreCheckFailure,
516523
doctorResults: doctorResults[project.configDir]?.diagnostics || {},

0 commit comments

Comments
 (0)