From 3c8245a86a2547bc37fd75bdb4fd1bcbe7e023c2 Mon Sep 17 00:00:00 2001 From: Adrian Dimech Date: Thu, 20 Jul 2023 14:10:40 +1000 Subject: [PATCH] fix(core): ensure output paths returned are unique It is possible for users to define multiple duplicate outputs. This is leading to fs related issues like `ENOTEMPTY: directory not empty, rmdir`. The reason this occurs is that the src will tried to be copied to the cached directory in parallel for all output paths and is the reason why these errors are seen sporadically. By ensuring output paths are unique, we only ever copy one path which resolves this issue. fixes #17277, ##16337 --- packages/nx/src/tasks-runner/utils.ts | 29 +++++++++++++++------------ 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/nx/src/tasks-runner/utils.ts b/packages/nx/src/tasks-runner/utils.ts index c0ae7d81233dc1..b3282b8d176570 100644 --- a/packages/nx/src/tasks-runner/utils.ts +++ b/packages/nx/src/tasks-runner/utils.ts @@ -322,19 +322,22 @@ export function getOutputsForTargetAndConfiguration( if (targetConfiguration?.outputs) { validateOutputs(targetConfiguration.outputs); - return targetConfiguration.outputs - .map((output: string) => { - return interpolate(output, { - projectRoot: node.data.root, - projectName: node.name, - project: { ...node.data, name: node.name }, // this is legacy - options, - }); - }) - .filter( - (output) => - !!output && !output.match(/{(projectRoot|workspaceRoot|(options.*))}/) - ); + const result = new Set(); + for (const output of targetConfiguration.outputs) { + const interpolatedOutput = interpolate(output, { + projectRoot: node.data.root, + projectName: node.name, + project: { ...node.data, name: node.name }, // this is legacy + options, + }); + if ( + !!interpolatedOutput && + !interpolatedOutput.match(/{(projectRoot|workspaceRoot|(options.*))}/) + ) { + result.add(interpolatedOutput); + } + } + return Array.from(result); } // Keep backwards compatibility in case `outputs` doesn't exist