From 217e77671179748eb4ddb8becde78444db93d067 Mon Sep 17 00:00:00 2001 From: Matthew Weeks Date: Wed, 30 Aug 2023 12:59:25 -0400 Subject: [PATCH 01/14] add onTaskError option and pass it fatalErrors --- node-src/runBuild.ts | 1 + node-src/types.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/node-src/runBuild.ts b/node-src/runBuild.ts index 19c8f86ac..13bb8f82d 100644 --- a/node-src/runBuild.ts +++ b/node-src/runBuild.ts @@ -75,6 +75,7 @@ export async function runBuild(ctx: Context, extraOptions?: Partial) { if (errors.length && !ctx.userError) { ctx.log.info(''); ctx.log.error(fatalError(ctx, errors)); + ctx.options.onTaskError?.(ctx, fatalError(ctx, errors)); } if (!ctx.exitCode) { diff --git a/node-src/types.ts b/node-src/types.ts index 4451716b1..0bf38476e 100644 --- a/node-src/types.ts +++ b/node-src/types.ts @@ -90,6 +90,9 @@ export interface Options { /** A callback that is called at the completion of each task */ onTaskComplete?: (ctx: Context) => void; + + /** A callback that is called if a task fails */ + onTaskError?: (ctx: Context, error: Error | Error[] | string) => void; } export interface Context { From 3710903a0329da170661108b396eac7de058e3b8 Mon Sep 17 00:00:00 2001 From: Matthew Weeks Date: Wed, 30 Aug 2023 13:43:21 -0400 Subject: [PATCH 02/14] add a test for the onTaskError option --- node-src/main.test.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/node-src/main.test.ts b/node-src/main.test.ts index 5cc0044b2..fe60c024d 100644 --- a/node-src/main.test.ts +++ b/node-src/main.test.ts @@ -343,6 +343,23 @@ it('fails on missing project token', async () => { expect(ctx.testLogger.errors[0]).toMatch(/Missing project token/); }); +// Note this tests options errors, but not fatal task or runtime errors. +it('passes options error to onTaskError', async () => { + const ctx = getContext([]); + ctx.options = { + onTaskError: jest.fn(), + } as any; + + ctx.options.onTaskError = jest.fn(); + ctx.env.CHROMATIC_PROJECT_TOKEN = ''; + await runBuild(ctx); + + await expect(ctx.options.onTaskError).toHaveBeenCalledWith( + expect.anything(), // Context + expect.stringContaining('Missing project token') // Long formatted error fatalError https://github.com/chromaui/chromatic-cli/blob/217e77671179748eb4ddb8becde78444db93d067/node-src/ui/messages/errors/fatalError.ts#L11 + ); +}); + it('runs in simple situations', async () => { const ctx = getContext(['--project-token=asdf1234']); await runBuild(ctx); From 442217cc18010f3bbf8421e576a9ba8798952090 Mon Sep 17 00:00:00 2001 From: Matthew Weeks Date: Wed, 30 Aug 2023 13:43:57 -0400 Subject: [PATCH 03/14] Call onTaskError for all fatalErrors, not just user errors, and handle options errors --- node-src/runBuild.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node-src/runBuild.ts b/node-src/runBuild.ts index 13bb8f82d..8787379cc 100644 --- a/node-src/runBuild.ts +++ b/node-src/runBuild.ts @@ -26,6 +26,7 @@ export async function runBuild(ctx: Context, extraOptions?: Partial) { } catch (e) { ctx.log.info(''); ctx.log.error(fatalError(ctx, [e])); + ctx.options.onTaskError?.(ctx, fatalError(ctx, [e])); setExitCode(ctx, exitCodes.INVALID_OPTIONS, true); return; } @@ -71,11 +72,11 @@ export async function runBuild(ctx: Context, extraOptions?: Partial) { } } catch (error) { const errors = [].concat(error); // GraphQLClient might throw an array of errors + ctx.options.onTaskError?.(ctx, fatalError(ctx, errors)); if (errors.length && !ctx.userError) { ctx.log.info(''); ctx.log.error(fatalError(ctx, errors)); - ctx.options.onTaskError?.(ctx, fatalError(ctx, errors)); } if (!ctx.exitCode) { From f6356613c451abda979f2a83927c9d1fdc60fca6 Mon Sep 17 00:00:00 2001 From: Matthew Weeks Date: Thu, 31 Aug 2023 12:34:44 -0400 Subject: [PATCH 04/14] onTaskError accepts { formattedError, originalError } --- node-src/main.test.ts | 5 ++++- node-src/runBuild.ts | 7 +++++-- node-src/types.ts | 7 +++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/node-src/main.test.ts b/node-src/main.test.ts index fe60c024d..b30113b9e 100644 --- a/node-src/main.test.ts +++ b/node-src/main.test.ts @@ -356,7 +356,10 @@ it('passes options error to onTaskError', async () => { await expect(ctx.options.onTaskError).toHaveBeenCalledWith( expect.anything(), // Context - expect.stringContaining('Missing project token') // Long formatted error fatalError https://github.com/chromaui/chromatic-cli/blob/217e77671179748eb4ddb8becde78444db93d067/node-src/ui/messages/errors/fatalError.ts#L11 + expect.objectContaining({ + formattedError: expect.stringContaining('Missing project token'), // Long formatted error fatalError https://github.com/chromaui/chromatic-cli/blob/217e77671179748eb4ddb8becde78444db93d067/node-src/ui/messages/errors/fatalError.ts#L11 + originalError: expect.anything(), // No jest matcher for an error. + }) ); }); diff --git a/node-src/runBuild.ts b/node-src/runBuild.ts index 8787379cc..2c2f3a812 100644 --- a/node-src/runBuild.ts +++ b/node-src/runBuild.ts @@ -26,7 +26,7 @@ export async function runBuild(ctx: Context, extraOptions?: Partial) { } catch (e) { ctx.log.info(''); ctx.log.error(fatalError(ctx, [e])); - ctx.options.onTaskError?.(ctx, fatalError(ctx, [e])); + ctx.options.onTaskError?.(ctx, { formattedError: fatalError(ctx, [e]), originalError: e }); setExitCode(ctx, exitCodes.INVALID_OPTIONS, true); return; } @@ -72,7 +72,10 @@ export async function runBuild(ctx: Context, extraOptions?: Partial) { } } catch (error) { const errors = [].concat(error); // GraphQLClient might throw an array of errors - ctx.options.onTaskError?.(ctx, fatalError(ctx, errors)); + ctx.options.onTaskError?.(ctx, { + formattedError: fatalError(ctx, errors), + originalError: error, + }); if (errors.length && !ctx.userError) { ctx.log.info(''); diff --git a/node-src/types.ts b/node-src/types.ts index f2b235ef1..c9479fe41 100644 --- a/node-src/types.ts +++ b/node-src/types.ts @@ -92,8 +92,11 @@ export interface Options { onTaskComplete?: (ctx: Context) => void; /** A callback that is called if a task fails */ - onTaskError?: (ctx: Context, error: Error | Error[] | string) => void; - + onTaskError?: ( + ctx: Context, + { formattedError, originalError }: { formattedError: string; originalError: Error | Error[] } + ) => void; + /** A callback that is called during tasks that have incremental progress */ onTaskProgress?: ( ctx: Context, From 2d126605a65079c4370ade6ebfde3e2d8fa9c067 Mon Sep 17 00:00:00 2001 From: Matthew Weeks Date: Fri, 1 Sep 2023 19:34:07 -0400 Subject: [PATCH 05/14] fix tests - add options to mock and add better error assertion --- node-src/main.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node-src/main.test.ts b/node-src/main.test.ts index b30113b9e..b15b57ca9 100644 --- a/node-src/main.test.ts +++ b/node-src/main.test.ts @@ -331,6 +331,7 @@ const getContext = ( }, packagePath: '', statsPath: 'preview-stats.json', + options: {}, ...parseArgs(argv), } as any; }; @@ -358,7 +359,7 @@ it('passes options error to onTaskError', async () => { expect.anything(), // Context expect.objectContaining({ formattedError: expect.stringContaining('Missing project token'), // Long formatted error fatalError https://github.com/chromaui/chromatic-cli/blob/217e77671179748eb4ddb8becde78444db93d067/node-src/ui/messages/errors/fatalError.ts#L11 - originalError: expect.anything(), // No jest matcher for an error. + originalError: expect.any(Error), }) ); }); From 9e2d8bec42fd4d5e88a84f62a13806f2306ca2de Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Mon, 4 Sep 2023 10:20:07 +0200 Subject: [PATCH 06/14] 7.0.0 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60989b12e..41a455ae1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 7.0.0 - 2023-09-04 + +- [789](https://github.com/chromaui/chromatic-cli/pull/789) Use `@antfu/ni` to support `pnpm` for Storybook build +- [805](https://github.com/chromaui/chromatic-cli/pull/805) Add a `onTaskProgress` option and report progress on it + +This is a potentially breaking change due to the introduction of [@antfu/ni](https://github.com/antfu/ni) to handle running the `storybook build` command in the **Build Storybook** step. + # 6.24.1 - 2023-08-25 - [803](https://github.com/chromaui/chromatic-cli/pull/803) Support Mode Name as Suffix for Build Progress Indicator From 5b928dc0c3b451ed76e50b47cbd8d9456b648f35 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Mon, 4 Sep 2023 10:20:25 +0200 Subject: [PATCH 07/14] 7.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4745fb30b..33658a53c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.0.0-next.0", + "version": "7.0.0", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From 3cbe8fab8eb76d544567278bf82c200ed824136d Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 20:20:09 +1000 Subject: [PATCH 08/14] Only warn about single commit outside of CI --- node-src/git/getCommitAndBranch.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/node-src/git/getCommitAndBranch.ts b/node-src/git/getCommitAndBranch.ts index f6a4cc63e..c0649a779 100644 --- a/node-src/git/getCommitAndBranch.ts +++ b/node-src/git/getCommitAndBranch.ts @@ -21,7 +21,7 @@ interface CommitInfo { } export default async function getCommitAndBranch( - { log }, + { log, options }, { branchName, patchBaseRef, @@ -50,6 +50,7 @@ export default async function getCommitAndBranch( CHROMATIC_PULL_REQUEST_SHA, CHROMATIC_SLUG, } = process.env; + const { isCi, service, prBranch, branch: ciBranch, commit: ciCommit, slug: ciSlug } = envCi(); const isFromEnvVariable = CHROMATIC_SHA && CHROMATIC_BRANCH; // Our GitHub Action also sets these const isTravisPrBuild = TRAVIS_EVENT_TYPE === 'pull_request'; @@ -57,7 +58,12 @@ export default async function getCommitAndBranch( const isGitHubPrBuild = GITHUB_EVENT_NAME === 'pull_request'; if (!(await hasPreviousCommit())) { - throw new Error(gitOneCommit(isGitHubAction)); + const message = gitOneCommit(isGitHubAction); + if (isCi) { + throw new Error(message); + } else { + log.warn(message); + } } if (isFromEnvVariable) { @@ -117,7 +123,6 @@ export default async function getCommitAndBranch( slug = GITHUB_REPOSITORY; } - const { isCi, service, prBranch, branch: ciBranch, commit: ciCommit, slug: ciSlug } = envCi(); const ciService = process.env.CHROMATIC_ACTION ? 'chromaui/action' : service; slug = slug || ciSlug; From 74b08f9b0abe387d33a5bfab626c14a4cb3bdd4a Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:01:50 +1000 Subject: [PATCH 09/14] 7.1.0-canary.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 33658a53c..846397d3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.0.0", + "version": "7.1.0-canary.0", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From 2a4723b4a2d859170e0f1db922b3593b5d24d188 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:02:05 +1000 Subject: [PATCH 10/14] 7.1.0-canary.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 846397d3a..be9545380 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.1.0-canary.0", + "version": "7.1.0-canary.1", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From 653eee29465a3b824cd59515546d652c7c8bb261 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:02:26 +1000 Subject: [PATCH 11/14] 7.1.0-canary.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be9545380..4813cfb79 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.1.0-canary.1", + "version": "7.1.0-canary.2", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From f4047f5f850e57d38a0fa1bf32e654361a1f3cf6 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:02:33 +1000 Subject: [PATCH 12/14] 7.1.0-canary.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4813cfb79..776c9a550 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.1.0-canary.2", + "version": "7.1.0-canary.3", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From 29be461f6e7c11cb3363cb45f50e12dbc905dcdc Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:02:38 +1000 Subject: [PATCH 13/14] 7.1.0-canary.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 776c9a550..4a81c9db5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chromatic", - "version": "7.1.0-canary.3", + "version": "7.1.0-canary.4", "description": "Automate visual testing across browsers. Gather UI feedback. Versioned documentation.", "keywords": [ "storybook-addon", From 4bed9fea46d06389ce47a009a049f02f3aac8d10 Mon Sep 17 00:00:00 2001 From: Tom Coleman Date: Wed, 6 Sep 2023 21:24:57 +1000 Subject: [PATCH 14/14] Fix tests --- node-src/git/getCommitAndBranch.test.ts | 10 +++++++++- node-src/git/getCommitAndBranch.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/node-src/git/getCommitAndBranch.test.ts b/node-src/git/getCommitAndBranch.test.ts index 07f40cc60..4e1ac288a 100644 --- a/node-src/git/getCommitAndBranch.test.ts +++ b/node-src/git/getCommitAndBranch.test.ts @@ -87,11 +87,19 @@ describe('getCommitAndBranch', () => { expect(info).toMatchObject({ branch: 'master' }); }); - it('throws when there is only one commit', async () => { + it('throws when there is only one commit, CI', async () => { + envCi.mockReturnValue({ isCi: true }); hasPreviousCommit.mockResolvedValue(false); await expect(getCommitAndBranch({ log })).rejects.toThrow('Found only one commit'); }); + it('does NOT throw when there is only one commit, non-CI', async () => { + envCi.mockReturnValue({ isCi: false }); + hasPreviousCommit.mockResolvedValue(false); + const info = await getCommitAndBranch({ log }); + expect(info).toMatchObject({}); + }); + describe('with branchName', () => { it('uses provided branchName as branch', async () => { const info = await getCommitAndBranch({ log }, { branchName: 'foobar' }); diff --git a/node-src/git/getCommitAndBranch.ts b/node-src/git/getCommitAndBranch.ts index c0649a779..4f20ac369 100644 --- a/node-src/git/getCommitAndBranch.ts +++ b/node-src/git/getCommitAndBranch.ts @@ -21,7 +21,7 @@ interface CommitInfo { } export default async function getCommitAndBranch( - { log, options }, + { log }, { branchName, patchBaseRef,