Skip to content

Commit

Permalink
Merge pull request #30018 from storybookjs/yann/improve-task-command
Browse files Browse the repository at this point in the history
Build: Improve task command and error message
  • Loading branch information
yannbf authored Dec 11, 2024
2 parents 53fa387 + 4711d6b commit bb14633
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 22 deletions.
39 changes: 21 additions & 18 deletions scripts/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { outputFile, pathExists, readFile } from 'fs-extra';
import type { TestCase } from 'junit-xml';
import { getJunitXml } from 'junit-xml';
import { join, resolve } from 'path';
import picocolors from 'picocolors';
import { prompt } from 'prompts';
import invariant from 'tiny-invariant';
import { dedent } from 'ts-dedent';
Expand Down Expand Up @@ -101,7 +102,7 @@ export const tasks = {
bench,
'vitest-integration': vitestTests,
};
type TaskKey = keyof typeof tasks;
export type TaskKey = keyof typeof tasks;

function isSandboxTask(taskKey: TaskKey) {
return !['install', 'compile', 'publish', 'run-registry', 'check', 'sync-docs'].includes(taskKey);
Expand Down Expand Up @@ -179,7 +180,7 @@ export const options = createOptions({
},
});

export type PassedOptionValues = Omit<OptionValues<typeof options>, 'task' | 'startFrom' | 'junit'>;
export type PassedOptionValues = Omit<OptionValues<typeof options>, 'startFrom' | 'junit'>;

const logger = console;

Expand Down Expand Up @@ -347,7 +348,8 @@ async function run() {

const allOptionValues = await getOptionsOrPrompt('yarn task', options);

const { task: taskKey, startFrom, junit, ...optionValues } = allOptionValues;
const { junit, startFrom, ...optionValues } = allOptionValues;
const taskKey = optionValues.task;

const finalTask = tasks[taskKey];
const { template: templateKey } = optionValues;
Expand All @@ -363,7 +365,6 @@ async function run() {
builtSandboxDir: templateKey && join(templateSandboxDir, 'storybook-static'),
junitFilename: junit && getJunitFilename(taskKey),
};

const { sortedTasks, tasksThatDepend } = getTaskList(finalTask, details, optionValues);
const sortedTasksReady = await Promise.all(
sortedTasks.map((t) => t.ready(details, optionValues))
Expand Down Expand Up @@ -482,27 +483,29 @@ async function run() {
}
} catch (err) {
invariant(err instanceof Error);
logger.error(`Error running task ${getTaskKey(task)}:`);
logger.error(
`Error running task ${picocolors.bold(getTaskKey(task))} for ${picocolors.bgMagenta(picocolors.bold(details.key))}:`
);
logger.error(JSON.stringify(err, null, 2));

if (process.env.CI) {
logger.error(
dedent`
To reproduce this error locally, run:
const separator = '\n--------------------------------------------\n';
const reproduceMessage = dedent`
To reproduce this error locally, run:
${getCommand('yarn task', options, {
${picocolors.bold(
getCommand('yarn task', options, {
...allOptionValues,
link: true,
startFrom: 'auto',
})}
Note this uses locally linking which in rare cases behaves differently to CI. For a closer match, run:
${getCommand('yarn task', options, {
...allOptionValues,
startFrom: 'auto',
})}`
);
})
)}
Note this uses locally linking which in rare cases behaves differently to CI.
For a closer match, add ${picocolors.bold('--no-link')} to the command above.
`;

err.message += `\n${separator}${reproduceMessage}${separator}\n`;
}

controllers.forEach((controller) => {
Expand Down
24 changes: 20 additions & 4 deletions scripts/tasks/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { join } from 'path';
import { promisify } from 'util';

import { now, saveBench } from '../bench/utils';
import type { Task } from '../task';
import type { Task, TaskKey } from '../task';

const logger = console;

Expand All @@ -22,8 +22,24 @@ export const sandbox: Task = {

return ['run-registry'];
},
async ready({ sandboxDir }) {
return pathExists(sandboxDir);
async ready({ sandboxDir }, { task: selectedTask }) {
// If the selected task requires the sandbox to exist, we check it. Else we always assume it needs to be created
// This avoids issues where you want to overwrite a sandbox and it will stop because it already exists
const tasksAfterSandbox: TaskKey[] = [
'vitest-integration',
'test-runner',
'test-runner-dev',
'e2e-tests',
'e2e-tests-dev',
'smoke-test',
'dev',
'build',
'serve',
'chromatic',
'bench',
];
const isSelectedTaskAfterSandboxCreation = tasksAfterSandbox.includes(selectedTask);
return isSelectedTaskAfterSandboxCreation && pathExists(sandboxDir);
},
async run(details, options) {
if (options.link && details.template.inDevelopment) {
Expand All @@ -33,7 +49,7 @@ export const sandbox: Task = {

options.link = false;
}
if (await this.ready(details)) {
if (await this.ready(details, options)) {
logger.info('🗑 Removing old sandbox dir');
await remove(details.sandboxDir);
}
Expand Down

0 comments on commit bb14633

Please sign in to comment.