From 4711d6b85d012fed1e5587341851144e73ea2302 Mon Sep 17 00:00:00 2001 From: Yann Braga Date: Wed, 11 Dec 2024 10:52:52 +0100 Subject: [PATCH] Build: Improve task command and error message --- scripts/task.ts | 39 +++++++++++++++++++++------------------ scripts/tasks/sandbox.ts | 24 ++++++++++++++++++++---- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/scripts/task.ts b/scripts/task.ts index 69c949254b32..be856bafb3ea 100644 --- a/scripts/task.ts +++ b/scripts/task.ts @@ -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'; @@ -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); @@ -179,7 +180,7 @@ export const options = createOptions({ }, }); -export type PassedOptionValues = Omit, 'task' | 'startFrom' | 'junit'>; +export type PassedOptionValues = Omit, 'startFrom' | 'junit'>; const logger = console; @@ -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; @@ -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)) @@ -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) => { diff --git a/scripts/tasks/sandbox.ts b/scripts/tasks/sandbox.ts index 80b0a2bf1045..cbf8856e0373 100644 --- a/scripts/tasks/sandbox.ts +++ b/scripts/tasks/sandbox.ts @@ -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; @@ -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) { @@ -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); }