diff --git a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.test.ts b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.test.ts index 8cd9822a8c35..f024d19c1133 100644 --- a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.test.ts +++ b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.test.ts @@ -276,35 +276,65 @@ describe('Yarn 2 Proxy', () => { }); describe('parseErrors', () => { - it('should parse yarn2 errors', () => { + it('should single yarn2 error message', () => { const YARN2_ERROR_SAMPLE = ` ➤ YN0000: ┌ Resolution step ➤ YN0001: │ Error: react@npm:28.2.0: No candidates found - at ge (/Users/yannbraga/.cache/node/corepack/yarn/3.5.1/yarn.js:439:8124) + at ge (/Users/xyz/.cache/node/corepack/yarn/3.5.1/yarn.js:439:8124) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Promise.allSettled (index 8) - at async io (/Users/yannbraga/.cache/node/corepack/yarn/3.5.1/yarn.js:390:10398) + at async io (/Users/xyz/.cache/node/corepack/yarn/3.5.1/yarn.js:390:10398) ➤ YN0000: └ Completed in 2s 369ms ➤ YN0000: Failed with errors in 2s 372ms ➤ YN0032: fsevents@npm:2.3.2: Implicit dependencies on node-gyp are discouraged ➤ YN0061: @npmcli/move-file@npm:2.0.1 is deprecated: This functionality has been moved to @npmcli/fs `; - expect(yarn2Proxy.parseErrorFromLogs(YARN2_ERROR_SAMPLE)).toEqual( - 'YARN2 error YN0001 - EXCEPTION: react@npm:28.2.0: No candidates found' + expect(yarn2Proxy.parseErrorFromLogs(YARN2_ERROR_SAMPLE)).toMatchInlineSnapshot( + ` + "YARN2 error + YN0001: EXCEPTION + -> Error: react@npm:28.2.0: No candidates found + " + ` ); }); - it('should show unknown yarn2 error', () => { - const YARN2_ERROR_SAMPLE = dedent` + it('shows multiple yarn2 error messages', () => { + const YARN2_ERROR_SAMPLE = ` + ➤ YN0000: · Yarn 4.1.1 ➤ YN0000: ┌ Resolution step - ➤ YN0000: └ Completed in 2s 369ms - ➤ YN0000: Failed with errors in 2s 372ms - ➤ YN0032: fsevents@npm:2.3.2: Implicit dependencies on node-gyp are discouraged - ➤ YN0061: @npmcli/move-file@npm:2.0.1 is deprecated: This functionality has been moved to @npmcli/fs + ➤ YN0085: │ + @chromatic-com/storybook@npm:1.2.25, and 300 more. + ➤ YN0000: └ Completed in 0s 763ms + ➤ YN0000: ┌ Post-resolution validation + ➤ YN0002: │ before-storybook@workspace:. doesn't provide @testing-library/dom (p1ac37), requested by @testing-library/user-event. + ➤ YN0002: │ before-storybook@workspace:. doesn't provide eslint (p1f657), requested by eslint-plugin-storybook. + ➤ YN0086: │ Some peer dependencies are incorrectly met; run yarn explain peer-requirements for details, where is the six-letter p-prefixed code. + ➤ YN0000: └ Completed + ➤ YN0000: ┌ Fetch step + ➤ YN0000: └ Completed + ➤ YN0000: ┌ Link step + ➤ YN0014: │ Failed to import certain dependencies + ➤ YN0071: │ Cannot link @storybook/test into before-storybook@workspace:. dependency @testing-library/jest-dom@npm:6.4.2 [ae73b] conflicts with parent dependency @testing-library/jest-dom@npm:5.17.0 + ➤ YN0071: │ Cannot link @storybook/test into before-storybook@workspace:. dependency @testing-library/user-event@npm:14.5.2 [ae73b] conflicts with parent dependency @testing-library/user-event@npm:13.5.0 [1b0ac] + ➤ YN0000: └ Completed in 0s 262ms + ➤ YN0000: · Failed with errors in 1s 301ms `; - expect(yarn2Proxy.parseErrorFromLogs(YARN2_ERROR_SAMPLE)).toEqual(`YARN2 error`); + expect(yarn2Proxy.parseErrorFromLogs(YARN2_ERROR_SAMPLE)).toMatchInlineSnapshot( + ` + "YARN2 error + YN0014: YARN_IMPORT_FAILED + -> Failed to import certain dependencies + + YN0071: NM_CANT_INSTALL_EXTERNAL_SOFT_LINK + -> Cannot link @storybook/test into before-storybook@workspace:. dependency @testing-library/jest-dom@npm:6.4.2 [ae73b] conflicts with parent dependency @testing-library/jest-dom@npm:5.17.0 + + YN0071: NM_CANT_INSTALL_EXTERNAL_SOFT_LINK + -> Cannot link @storybook/test into before-storybook@workspace:. dependency @testing-library/user-event@npm:14.5.2 [ae73b] conflicts with parent dependency @testing-library/user-event@npm:13.5.0 [1b0ac] + " + ` + ); }); }); }); diff --git a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts index 09f535e2dfa5..7014357cc44b 100644 --- a/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts +++ b/code/lib/core-common/src/js-package-manager/Yarn2Proxy.ts @@ -10,10 +10,35 @@ import type { PackageJson } from './PackageJson'; import type { InstallationMetadata, PackageMetadata } from './types'; import { parsePackageData } from './util'; -const YARN2_ERROR_REGEX = /(YN\d{4}):.*?Error:\s+(.*)/i; +const CRITICAL_YARN2_ERROR_CODES = { + YN0001: 'EXCEPTION', + YN0009: 'BUILD_FAILED', + YN0010: 'RESOLVER_NOT_FOUND', + YN0011: 'FETCHER_NOT_FOUND', + YN0012: 'LINKER_NOT_FOUND', + YN0014: 'YARN_IMPORT_FAILED', + YN0015: 'REMOTE_INVALID', + YN0016: 'REMOTE_NOT_FOUND', + YN0020: 'MISSING_LOCKFILE_ENTRY', + YN0021: 'WORKSPACE_NOT_FOUND', + YN0028: 'FROZEN_LOCKFILE_EXCEPTION', + YN0030: 'FETCH_FAILED', + YN0046: 'AUTOMERGE_FAILED_TO_PARSE', + YN0062: 'INCOMPATIBLE_OS', + YN0063: 'INCOMPATIBLE_CPU', + YN0071: 'NM_CANT_INSTALL_EXTERNAL_SOFT_LINK', + YN0072: 'NM_PRESERVE_SYMLINKS_REQUIRED', + YN0075: 'PROLOG_INSTANTIATION_ERROR', + YN0076: 'INCOMPATIBLE_ARCHITECTURE', + YN0078: 'RESOLUTION_MISMATCH', + YN0081: 'NETWORK_UNSAFE_HTTP', + YN0082: 'RESOLUTION_FAILED', + YN0083: 'AUTOMERGE_GIT_ERROR', +}; + const YARN2_ERROR_CODES = { + ...CRITICAL_YARN2_ERROR_CODES, YN0000: 'UNNAMED', - YN0001: 'EXCEPTION', YN0002: 'MISSING_PEER_DEPENDENCY', YN0003: 'CYCLIC_DEPENDENCIES', YN0004: 'DISABLED_BUILD_SCRIPTS', @@ -21,31 +46,19 @@ const YARN2_ERROR_CODES = { YN0006: 'SOFT_LINK_BUILD', YN0007: 'MUST_BUILD', YN0008: 'MUST_REBUILD', - YN0009: 'BUILD_FAILED', - YN0010: 'RESOLVER_NOT_FOUND', - YN0011: 'FETCHER_NOT_FOUND', - YN0012: 'LINKER_NOT_FOUND', YN0013: 'FETCH_NOT_CACHED', - YN0014: 'YARN_IMPORT_FAILED', - YN0015: 'REMOTE_INVALID', - YN0016: 'REMOTE_NOT_FOUND', YN0017: 'RESOLUTION_PACK', YN0018: 'CACHE_CHECKSUM_MISMATCH', YN0019: 'UNUSED_CACHE_ENTRY', - YN0020: 'MISSING_LOCKFILE_ENTRY', - YN0021: 'WORKSPACE_NOT_FOUND', YN0022: 'TOO_MANY_MATCHING_WORKSPACES', YN0023: 'CONSTRAINTS_MISSING_DEPENDENCY', YN0024: 'CONSTRAINTS_INCOMPATIBLE_DEPENDENCY', YN0025: 'CONSTRAINTS_EXTRANEOUS_DEPENDENCY', YN0026: 'CONSTRAINTS_INVALID_DEPENDENCY', YN0027: 'CANT_SUGGEST_RESOLUTIONS', - YN0028: 'FROZEN_LOCKFILE_EXCEPTION', YN0029: 'CROSS_DRIVE_VIRTUAL_LOCAL', - YN0030: 'FETCH_FAILED', YN0031: 'DANGEROUS_NODE_MODULES', YN0032: 'NODE_GYP_INJECTED', - YN0046: 'AUTOMERGE_FAILED_TO_PARSE', YN0047: 'AUTOMERGE_IMMUTABLE', YN0048: 'AUTOMERGE_SUCCESS', YN0049: 'AUTOMERGE_REQUIRED', @@ -53,16 +66,17 @@ const YARN2_ERROR_CODES = { YN0059: 'INVALID_RANGE_PEER_DEPENDENCY', YN0060: 'INCOMPATIBLE_PEER_DEPENDENCY', YN0061: 'DEPRECATED_PACKAGE', - YN0062: 'INCOMPATIBLE_OS', - YN0063: 'INCOMPATIBLE_CPU', YN0068: 'UNUSED_PACKAGE_EXTENSION', YN0069: 'REDUNDANT_PACKAGE_EXTENSION', - YN0071: 'NM_CANT_INSTALL_EXTERNAL_SOFT_LINK', - YN0072: 'NM_PRESERVE_SYMLINKS_REQUIRED', YN0074: 'NM_HARDLINKS_MODE_DOWNGRADED', - YN0075: 'PROLOG_INSTANTIATION_ERROR', - YN0076: 'INCOMPATIBLE_ARCHITECTURE', YN0077: 'GHOST_ARCHITECTURE', + YN0080: 'NETWORK_DISABLED', + YN0085: 'UPDATED_RESOLUTION_RECORD', + YN0086: 'EXPLAIN_PEER_DEPENDENCIES_CTA', + YN0087: 'MIGRATION_SUCCESS', + YN0088: 'VERSION_NOTICE', + YN0089: 'TIPS_NOTICE', + YN0090: 'OFFLINE_MODE_ENABLED', }; // This encompasses both yarn 2 and yarn 3 @@ -284,26 +298,25 @@ export class Yarn2Proxy extends JsPackageManager { } public parseErrorFromLogs(logs: string): string { - let finalMessage = 'YARN2 error'; - const match = logs.match(YARN2_ERROR_REGEX); - - if (match) { - const errorCode = match[1] as keyof typeof YARN2_ERROR_CODES; - if (errorCode) { - finalMessage = `${finalMessage} ${errorCode}`; - } - - const errorType = YARN2_ERROR_CODES[errorCode]; - if (errorType) { - finalMessage = `${finalMessage} - ${errorType}`; - } - - const errorMessage = match[2]; - if (errorMessage) { - finalMessage = `${finalMessage}: ${errorMessage}`; + const finalMessage = 'YARN2 error'; + const errorCodesWithMessages: { code: string; message: string }[] = []; + const regex = /(YN\d{4}): (.+)/g; + let match: RegExpExecArray | null; + + while ((match = regex.exec(logs)) !== null) { + const code = match[1]; + const message = match[2].replace(/[┌│└]/g, '').trim(); + if (CRITICAL_YARN2_ERROR_CODES[code]) { + errorCodesWithMessages.push({ + code, + message: `${CRITICAL_YARN2_ERROR_CODES[code]}\n-> ${message}\n`, + }); } } - return finalMessage.trim(); + return [ + finalMessage, + errorCodesWithMessages.map(({ code, message }) => `${code}: ${message}`).join('\n'), + ].join('\n'); } }