Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6130717
Add `test-run` telemetry for vitest
tmeasday May 14, 2025
8ff81c4
Add BUILD_ENV_FOR_TESTING and use to trigger telemetry when building …
tmeasday May 14, 2025
9e1bfcb
Refactor `BUILD_ENV_FOR_TESTING` to happen after we have presets etc
tmeasday May 15, 2025
313fa63
Wait on both telemetry jobs in sync
tmeasday May 15, 2025
c0dbbbb
Refactor telemetry into `configureVitest`, check disabled
tmeasday May 15, 2025
73d7dd7
Remove out of date comment
tmeasday May 15, 2025
6d84231
Added chromatic to test packages list
tmeasday May 16, 2025
225ca62
Remove addon version from addon-test event as it is redundant (it's i…
tmeasday May 16, 2025
4e54284
Experiment with checking telemetry on test-runner/vitest jobs
tmeasday May 16, 2025
7f04ced
Change env var to `STORYBOOK_INVOKED_BY`
tmeasday May 19, 2025
37689d5
Add an expectation on `run-tests`
tmeasday May 19, 2025
d3d0ece
Try adding telemetry debug to vitest step
tmeasday May 19, 2025
fbd7e6c
Temporarily use test runner canary
tmeasday May 19, 2025
4a34208
Set environment for steps
tmeasday May 19, 2025
b65dcb9
Whoops added env to wrong command
tmeasday May 19, 2025
d4ef750
Allow no boot event for some types
tmeasday May 19, 2025
1cf0366
Send extra options to telemetry
tmeasday May 19, 2025
4e9e9b5
Add debug logs to build step
tmeasday May 19, 2025
7a6530a
Fix event name
tmeasday May 19, 2025
25e7319
Fixes
tmeasday May 19, 2025
d4bac18
Simplify call to telemetry slightly
tmeasday May 22, 2025
3213d04
Send `test-run` event immediately on "invoked" builds.
tmeasday May 27, 2025
87b1893
Update code/core/src/core-server/build-static.ts
tmeasday May 28, 2025
3d3bc0e
Update scripts/event-log-checker.ts
tmeasday May 28, 2025
c2d246c
Only send `test-run` event if invoked by a 3rd party
tmeasday May 28, 2025
8923e8c
Merge branch 'next' into tom/add-test-run-telemetry
shilman May 29, 2025
bcccd74
Merge branch 'next' into tom/add-test-run-telemetry
shilman May 29, 2025
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
133 changes: 76 additions & 57 deletions .circleci/config.yml

Large diffs are not rendered by default.

9 changes: 0 additions & 9 deletions code/addons/vitest/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,6 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti

if (!core.disableTelemetry) {
const enableCrashReports = core.enableCrashReports || options.enableCrashReports;
const packageJsonPath = require.resolve('@storybook/addon-vitest/package.json');

const { version: addonVersion } = JSON.parse(
readFileSync(packageJsonPath, { encoding: 'utf-8' })
);

channel.on(STORYBOOK_ADDON_TEST_CHANNEL, (event: Event) => {
telemetry('addon-test', {
Expand All @@ -193,14 +188,12 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
...event.payload,
storyId: oneWayHash(event.payload.storyId),
},
addonVersion,
});
});

store.subscribe('TOGGLE_WATCHING', async (event) => {
await telemetry('addon-test', {
watchMode: event.payload.to,
addonVersion,
});
});
store.subscribe('TEST_RUN_COMPLETED', async (event) => {
Expand All @@ -216,15 +209,13 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti
return sanitizeError(errorWithoutStacks);
}),
}),
addonVersion,
});
});

if (enableCrashReports) {
store.subscribe('FATAL_ERROR', async (event) => {
await telemetry('addon-test', {
fatalError: cleanPaths(event.payload.error.message),
addonVersion,
});
});
}
Expand Down
20 changes: 20 additions & 0 deletions code/addons/vitest/src/vitest-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
} from 'storybook/internal/core-server';
import { readConfig, vitestTransform } from 'storybook/internal/csf-tools';
import { MainFileMissingError } from 'storybook/internal/server-errors';
import { telemetry } from 'storybook/internal/telemetry';
import { oneWayHash } from 'storybook/internal/telemetry';
import type { Presets } from 'storybook/internal/types';

Expand Down Expand Up @@ -144,13 +145,15 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin[]> =>
viteConfigFromStorybook,
staticDirs,
previewLevelTags,
core,
] = await Promise.all([
getStoryGlobsAndFiles(presets, directories),
presets.apply('framework', undefined),
presets.apply('env', {}),
presets.apply<{ plugins?: Plugin[] }>('viteFinal', {}),
presets.apply('staticDirs', []),
extractTagsFromPreview(finalOptions.configDir),
presets.apply('core'),
]);

const pluginsToIgnore = [
Expand Down Expand Up @@ -361,6 +364,23 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin[]> =>
},
configureVitest(context) {
context.vitest.config.coverage.exclude.push('storybook-static');

const disableTelemetryVar =
process.env.STORYBOOK_DISABLE_TELEMETRY &&
process.env.STORYBOOK_DISABLE_TELEMETRY !== 'false';
if (!core?.disableTelemetry && !disableTelemetryVar) {
// NOTE: we start telemetry immediately but do not wait on it. Typically it should complete
// before the tests do. If not we may miss the event, we are OK with that.
telemetry(
'test-run',
{
runner: 'vitest',
watch: context.vitest.config.watch,
coverage: !!context.vitest.config.coverage?.enabled,
},
{ configDir: finalOptions.configDir }
);
}
},
async configureServer(server) {
if (staticDirs) {
Expand Down
11 changes: 10 additions & 1 deletion code/core/src/core-server/build-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
presets.apply('docs'),
]);

const invokedBy = process.env.STORYBOOK_INVOKED_BY;
if (!core?.disableTelemetry && invokedBy) {
// NOTE: we don't await this event to avoid slowing things down.
// This could result in telemetry events being lost.
telemetry('test-run', { runner: invokedBy, watch: false }, { configDir: options.configDir });
}

const fullOptions: Options = {
...options,
presets,
Expand Down Expand Up @@ -205,7 +212,8 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
]);

// Now the code has successfully built, we can count this as a 'dev' event.
if (!core?.disableTelemetry) {
// NOTE: we don't send the 'build' event for test runs as we want to be as fast as possible
if (!core?.disableTelemetry && !options.test) {
effects.push(
initializedStoryIndexGenerator.then(async (generator) => {
const storyIndex = await generator?.getIndex();
Expand All @@ -217,6 +225,7 @@ export async function buildStaticStandalone(options: BuildStaticStandaloneOption
storyIndex: summarizeIndex(storyIndex),
});
}

await telemetry('build', payload, { configDir: options.configDir });
})
);
Expand Down
2 changes: 1 addition & 1 deletion code/core/src/core-server/presets/common-preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export const experimental_serverAPI = (extension: Record<string, Function>, opti
*/
export const core = async (existing: CoreConfig, options: Options): Promise<CoreConfig> => ({
...existing,
disableTelemetry: options.disableTelemetry === true || options.test === true,
disableTelemetry: options.disableTelemetry === true,
enableCrashReports:
options.enableCrashReports || optionalEnvToBoolean(process.env.STORYBOOK_ENABLE_CRASH_REPORTS),
});
Expand Down
1 change: 1 addition & 0 deletions code/core/src/telemetry/storybook-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ export const computeStorybookMetadata = async ({
'msw',
'miragejs',
'sinon',
'chromatic',
];
const testPackageDeps = Object.keys(allDependencies).filter((dep) =>
testPackages.find((pkg) => dep.includes(pkg))
Expand Down
3 changes: 2 additions & 1 deletion code/core/src/telemetry/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export type EventType =
| 'testing-module-watch-mode'
| 'testing-module-completed-report'
| 'testing-module-crash-report'
| 'addon-test';
| 'addon-test'
| 'test-run';

export interface Dependency {
version: string | undefined;
Expand Down
73 changes: 50 additions & 23 deletions scripts/event-log-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ import { esMain } from './utils/esmain';

const PORT = process.env.PORT || 6007;

const eventTypeExpectations = {
type EventType = 'build' | 'test-run';
type EventDefinition = {
noBoot?: boolean;
};

const eventTypeDefinitions: Record<EventType, EventDefinition> = {
build: {},
'test-run': { noBoot: true },
};

async function run() {
Expand All @@ -29,9 +35,9 @@ async function run() {
);
}

const expectation = eventTypeExpectations[eventType as keyof typeof eventTypeExpectations];
const definition = eventTypeDefinitions[eventType as EventType];

if (!expectation) {
if (!definition) {
throw new Error(`Unexpected eventType '${eventType}'`);
}

Expand All @@ -43,23 +49,38 @@ async function run() {

const events: any = await (await fetch(`http://localhost:${PORT}/event-log`)).json();

test('Should log 2 events', () => {
assert.equal(
events.length,
2,
`Expected 2 events but received ${
events.length
} instead. The following events were logged: ${JSON.stringify(events)}`
);
});
if (definition.noBoot) {
test('Should log 1 event', () => {
assert.equal(
events.length,
1,
`Expected 1 event but received ${
events.length
} instead. The following events were logged: ${JSON.stringify(events)}`
);
});
} else {
test('Should log 2 events', () => {
assert.equal(
events.length,
2,
`Expected 2 events but received ${
events.length
} instead. The following events were logged: ${JSON.stringify(events)}`
);
});
}

const [bootEvent, mainEvent] = events;
if (events.length === 0) throw new Error('No events were logged');
const [bootEvent, mainEvent] = definition.noBoot ? [null, events[0]] : events;

const storybookVersion = versions.storybook;
test('boot event should have cliVersion and storybookVersion in context', () => {
assert.equal(bootEvent.context.cliVersion, storybookVersion);
assert.equal(bootEvent.context.storybookVersion, storybookVersion);
});
if (bootEvent) {
test('boot event should have cliVersion and storybookVersion in context', () => {
assert.equal(bootEvent.context.cliVersion, storybookVersion);
assert.equal(bootEvent.context.storybookVersion, storybookVersion);
});
}

test(`main event should have storybookVersion in context`, () => {
assert.equal(mainEvent.context.storybookVersion, storybookVersion);
Expand All @@ -69,15 +90,21 @@ async function run() {
assert.equal(mainEvent.metadata.storybookVersion, storybookVersion);
});

test(`Should log a boot event with a payload of type ${eventType}`, () => {
assert.equal(bootEvent.eventType, 'boot');
assert.equal(bootEvent.payload?.eventType, eventType);
});
if (bootEvent) {
test(`Should log a boot event with a payload of type ${eventType}`, () => {
assert.equal(bootEvent.eventType, 'boot');
assert.equal(bootEvent.payload?.eventType, eventType);
});
}

test(`main event should be ${eventType} and contain correct id and session id`, () => {
assert.equal(mainEvent.eventType, eventType);
assert.notEqual(mainEvent.eventId, bootEvent.eventId);
assert.equal(mainEvent.sessionId, bootEvent.sessionId);
assert.ok(typeof mainEvent.eventId === 'string');
assert.ok(typeof mainEvent.sessionId === 'string');
if (bootEvent) {
assert.notEqual(mainEvent.eventId, bootEvent.eventId);
assert.equal(mainEvent.sessionId, bootEvent.sessionId);
}
});

test(`main event should contain anonymousId properly hashed`, () => {
Expand Down
3 changes: 2 additions & 1 deletion scripts/tasks/sandbox-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,8 @@ export async function addExtraDependencies({
debug: boolean;
extraDeps?: string[];
}) {
const extraDevDeps = ['@storybook/test-runner@next'];
// FIXME: revert back to `next` once https://github.com/storybookjs/test-runner/pull/560 is merged
const extraDevDeps = ['@storybook/[email protected]'];

if (debug) {
logger.log('\uD83C\uDF81 Adding extra dev deps', extraDevDeps);
Expand Down
Loading