From 718c3fcdfc9270c7493d7a9d679cdb05e8eb5b82 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 22 Nov 2024 11:05:39 +0700 Subject: [PATCH] fix(plugin-workspace-tools): properly report errors for all non-zero exit codes (#6535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What's the problem this PR addresses? `yarn workspaces foreach [...]` does not clearly indicate that there was a failure, or for what workspace there were non-zero exit codes. Before: (just says "done", but exit code is 1) ``` Done in 57s 886ms endo3 on  yarn-workspaces-for-scripts [!?] via  v18.20.4 took 58s ❯ echo $? 1 ``` After: ``` The command failed in workspace ses@workspace:packages/ses Failed with errors in 45s 837ms ``` ## How did you fix it? I used the `report.reportError` feature to report all the workspaces that had non-zero exit codes. The final exitCode is not changed in this PR. ## Checklist - [x] I have read the [Contributing Guide](https://yarnpkg.com/advanced/contributing). - [x] I have set the packages that need to be released for my changes to be effective. - [x] I will check that all automated PR checks pass before the PR gets reviewed. 🙏 @arcanis thank you for yarn 🙏 --------- Co-authored-by: Maël Nison --- .yarn/versions/30ae755e.yml | 24 +++++++++++++++++++ .../sources/commands/foreach.ts | 16 +++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 .yarn/versions/30ae755e.yml diff --git a/.yarn/versions/30ae755e.yml b/.yarn/versions/30ae755e.yml new file mode 100644 index 000000000000..c211beb49726 --- /dev/null +++ b/.yarn/versions/30ae755e.yml @@ -0,0 +1,24 @@ +releases: + "@yarnpkg/cli": patch + "@yarnpkg/plugin-workspace-tools": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-nm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" + - "@yarnpkg/pnp" diff --git a/packages/plugin-workspace-tools/sources/commands/foreach.ts b/packages/plugin-workspace-tools/sources/commands/foreach.ts index 47668fc447c8..b63e9e54c518 100644 --- a/packages/plugin-workspace-tools/sources/commands/foreach.ts +++ b/packages/plugin-workspace-tools/sources/commands/foreach.ts @@ -405,7 +405,7 @@ export default class WorkspacesForeachCommand extends BaseCommand { needsProcessing.delete(identHash); processing.delete(workspace.anchoredDescriptor.descriptorHash); - return exitCode; + return {workspace, exitCode}; })); // If we're not executing processes in parallel we can just wait for it @@ -424,13 +424,15 @@ export default class WorkspacesForeachCommand extends BaseCommand { return; } - const exitCodes: Array = await Promise.all(commandPromises); - const errorCode = exitCodes.find(code => code !== 0); + const results: Array<{ workspace: Workspace, exitCode: number }> = await Promise.all(commandPromises); + results.forEach(({workspace, exitCode}) => { + if (exitCode !== 0) { + report.reportError(MessageName.UNNAMED, `The command failed in workspace ${structUtils.prettyLocator(configuration, workspace.anchoredLocator)} with exit code ${exitCode}`); + } + }); - // The order in which the exit codes will be processed is fairly - // opaque, so better just return a generic "1" for determinism. - if (finalExitCode === null) - finalExitCode = typeof errorCode !== `undefined` ? 1 : finalExitCode; + const exitCodes = results.map(result => result.exitCode); + const errorCode = exitCodes.find(code => code !== 0); if ((this.topological || this.topologicalDev) && typeof errorCode !== `undefined`) { report.reportError(MessageName.UNNAMED, `The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph`);