From d21f81c0de6e397f63dbe1a47f1f4c769b50b155 Mon Sep 17 00:00:00 2001
From: Lukas <lukas@slucky.de>
Date: Tue, 15 Jun 2021 06:02:21 +0200
Subject: [PATCH] fix(pnpm): match package patterns that are matched by pnpm
 (#10389)

---
 .../nested-packages/group/a/package.json      | 12 ++++++
 .../nested-packages/group/b/package.json      | 12 ++++++
 .../non-nested-packages/a/package.json        | 12 ++++++
 .../b/package.json                            |  2 +-
 .../__fixtures__/pnpm-monorepo/pnpm-lock.yaml | 28 ++++++++++++-
 .../pnpm-monorepo/pnpm-workspace.yaml         |  5 ++-
 .../solo-package-trailing-slash/package.json  | 12 ++++++
 .../{packages/a => solo-package}/package.json |  2 +-
 .../extract/__snapshots__/pnpm.spec.ts.snap   | 34 +++++++++++----
 lib/manager/npm/extract/pnpm.spec.ts          | 34 +++++++++++----
 lib/manager/npm/extract/pnpm.ts               |  6 ++-
 lib/manager/npm/extract/utils.spec.ts         | 42 +++++++++++++++++++
 12 files changed, 181 insertions(+), 20 deletions(-)
 create mode 100644 lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/a/package.json
 create mode 100644 lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/b/package.json
 create mode 100644 lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/a/package.json
 rename lib/manager/npm/__fixtures__/pnpm-monorepo/{packages => non-nested-packages}/b/package.json (85%)
 create mode 100644 lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package-trailing-slash/package.json
 rename lib/manager/npm/__fixtures__/pnpm-monorepo/{packages/a => solo-package}/package.json (88%)
 create mode 100644 lib/manager/npm/extract/utils.spec.ts

diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/a/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/a/package.json
new file mode 100644
index 0000000000..279df4bbc3
--- /dev/null
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/a/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "@demo/nested-group-a",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "dependencies": {
+    "dotenv": "^9.0.2"
+  }
+}
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/b/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/b/package.json
new file mode 100644
index 0000000000..1081c3c013
--- /dev/null
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/nested-packages/group/b/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "@demo/nested-group-b",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "dependencies": {
+    "chalk": "^2.4.1"
+  }
+}
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/a/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/a/package.json
new file mode 100644
index 0000000000..101face8cb
--- /dev/null
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/a/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "@demo/non-nested-a",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "dependencies": {
+    "dotenv": "^9.0.2"
+  }
+}
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/packages/b/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/b/package.json
similarity index 85%
rename from lib/manager/npm/__fixtures__/pnpm-monorepo/packages/b/package.json
rename to lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/b/package.json
index 6a9a836db9..cf42bf384b 100644
--- a/lib/manager/npm/__fixtures__/pnpm-monorepo/packages/b/package.json
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/non-nested-packages/b/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "@demo/a",
+  "name": "@demo/non-nested-b",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-lock.yaml b/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-lock.yaml
index 7703c553f1..b0b4677c38 100644
--- a/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-lock.yaml
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-lock.yaml
@@ -8,18 +8,42 @@ importers:
     dependencies:
       chalk: 2.4.2
 
-  packages/a:
+  nested-packages/group/a:
     specifiers:
       dotenv: ^9.0.2
     dependencies:
       dotenv: 9.0.2
 
-  packages/b:
+  nested-packages/group/b:
     specifiers:
       chalk: ^2.4.1
     dependencies:
       chalk: 2.4.2
 
+  non-nested-packages/a:
+    specifiers:
+      dotenv: ^9.0.2
+    dependencies:
+      dotenv: 9.0.2
+
+  non-nested-packages/b:
+    specifiers:
+      chalk: ^2.4.1
+    dependencies:
+      chalk: 2.4.2
+
+  solo-package:
+    specifiers:
+      dotenv: ^9.0.2
+    dependencies:
+      dotenv: 9.0.2
+
+  solo-package-trailing-slash:
+    specifiers:
+      dotenv: ^9.0.2
+    dependencies:
+      dotenv: 9.0.2
+
 packages:
 
   /ansi-styles/3.2.1:
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-workspace.yaml b/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-workspace.yaml
index 14d2f77b70..d628e29b10 100644
--- a/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-workspace.yaml
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/pnpm-workspace.yaml
@@ -1,3 +1,6 @@
 packages:
   # all packages in subdirs of packages/
-  - 'packages/**'
+  - 'nested-packages/**'
+  - 'non-nested-packages/*'
+  - 'solo-package'
+  - 'solo-package-trailing-slash/'
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package-trailing-slash/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package-trailing-slash/package.json
new file mode 100644
index 0000000000..46cce36062
--- /dev/null
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package-trailing-slash/package.json
@@ -0,0 +1,12 @@
+{
+  "name": "@demo/solo-trailing-slash",
+  "version": "1.0.0",
+  "description": "",
+  "main": "index.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "dependencies": {
+    "dotenv": "^9.0.2"
+  }
+}
diff --git a/lib/manager/npm/__fixtures__/pnpm-monorepo/packages/a/package.json b/lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package/package.json
similarity index 88%
rename from lib/manager/npm/__fixtures__/pnpm-monorepo/packages/a/package.json
rename to lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package/package.json
index 979ce6d981..09326319de 100644
--- a/lib/manager/npm/__fixtures__/pnpm-monorepo/packages/a/package.json
+++ b/lib/manager/npm/__fixtures__/pnpm-monorepo/solo-package/package.json
@@ -1,5 +1,5 @@
 {
-  "name": "@demo/a",
+  "name": "@demo/solo",
   "version": "1.0.0",
   "description": "",
   "main": "index.js",
diff --git a/lib/manager/npm/extract/__snapshots__/pnpm.spec.ts.snap b/lib/manager/npm/extract/__snapshots__/pnpm.spec.ts.snap
index c4e3102dcd..6c4a4b6528 100644
--- a/lib/manager/npm/extract/__snapshots__/pnpm.spec.ts.snap
+++ b/lib/manager/npm/extract/__snapshots__/pnpm.spec.ts.snap
@@ -7,13 +7,13 @@ Array [
     "pnpmShrinkwrap": "pnpm-lock.yaml",
   },
   Object {
-    "packageFile": "packages/a/package.json",
-    "packageJsonName": "@org/a",
+    "packageFile": "nested-packages/group/a/package.json",
+    "packageJsonName": "@demo/nested-group-a",
     "pnpmShrinkwrap": "pnpm-lock.yaml",
   },
   Object {
     "packageFile": "not-matching/b/package.json",
-    "packageJsonName": "@org/b",
+    "packageJsonName": "@not-matching/b",
     "pnpmShrinkwrap": undefined,
   },
 ]
@@ -35,13 +35,33 @@ Array [
     "pnpmShrinkwrap": "pnpm-lock.yaml",
   },
   Object {
-    "packageFile": "packages/a/package.json",
-    "packageJsonName": "@org/a",
+    "packageFile": "nested-packages/group/a/package.json",
+    "packageJsonName": "@demo/nested-group-a",
     "pnpmShrinkwrap": "pnpm-lock.yaml",
   },
   Object {
-    "packageFile": "packages/b/package.json",
-    "packageJsonName": "@org/b",
+    "packageFile": "nested-packages/group/b/package.json",
+    "packageJsonName": "@demo/nested-group-b",
+    "pnpmShrinkwrap": "pnpm-lock.yaml",
+  },
+  Object {
+    "packageFile": "non-nested-packages/a/package.json",
+    "packageJsonName": "@demo/non-nested-a",
+    "pnpmShrinkwrap": "pnpm-lock.yaml",
+  },
+  Object {
+    "packageFile": "non-nested-packages/b/package.json",
+    "packageJsonName": "@demo/non-nested-b",
+    "pnpmShrinkwrap": "pnpm-lock.yaml",
+  },
+  Object {
+    "packageFile": "solo-package/package.json",
+    "packageJsonName": "@demo/solo",
+    "pnpmShrinkwrap": "pnpm-lock.yaml",
+  },
+  Object {
+    "packageFile": "solo-package-trailing-slash/package.json",
+    "packageJsonName": "@demo/solo-trailing-slash",
     "pnpmShrinkwrap": "pnpm-lock.yaml",
   },
 ]
diff --git a/lib/manager/npm/extract/pnpm.spec.ts b/lib/manager/npm/extract/pnpm.spec.ts
index 72ce6298ac..77ba95585e 100644
--- a/lib/manager/npm/extract/pnpm.spec.ts
+++ b/lib/manager/npm/extract/pnpm.spec.ts
@@ -89,13 +89,33 @@ describe(getName(), () => {
           pnpmShrinkwrap: 'pnpm-lock.yaml',
         },
         {
-          packageFile: 'packages/a/package.json',
-          packageJsonName: '@org/a',
+          packageFile: 'nested-packages/group/a/package.json',
+          packageJsonName: '@demo/nested-group-a',
           pnpmShrinkwrap: undefined as undefined | string,
         },
         {
-          packageFile: 'packages/b/package.json',
-          packageJsonName: '@org/b',
+          packageFile: 'nested-packages/group/b/package.json',
+          packageJsonName: '@demo/nested-group-b',
+          pnpmShrinkwrap: undefined as undefined | string,
+        },
+        {
+          packageFile: 'non-nested-packages/a/package.json',
+          packageJsonName: '@demo/non-nested-a',
+          pnpmShrinkwrap: undefined as undefined | string,
+        },
+        {
+          packageFile: 'non-nested-packages/b/package.json',
+          packageJsonName: '@demo/non-nested-b',
+          pnpmShrinkwrap: undefined as undefined | string,
+        },
+        {
+          packageFile: 'solo-package/package.json',
+          packageJsonName: '@demo/solo',
+          pnpmShrinkwrap: undefined as undefined | string,
+        },
+        {
+          packageFile: 'solo-package-trailing-slash/package.json',
+          packageJsonName: '@demo/solo-trailing-slash',
           pnpmShrinkwrap: undefined as undefined | string,
         },
       ];
@@ -126,13 +146,13 @@ describe(getName(), () => {
           pnpmShrinkwrap: 'pnpm-lock.yaml',
         },
         {
-          packageFile: 'packages/a/package.json',
-          packageJsonName: '@org/a',
+          packageFile: 'nested-packages/group/a/package.json',
+          packageJsonName: '@demo/nested-group-a',
           pnpmShrinkwrap: undefined as undefined | string,
         },
         {
           packageFile: 'not-matching/b/package.json',
-          packageJsonName: '@org/b',
+          packageJsonName: '@not-matching/b',
           pnpmShrinkwrap: undefined as undefined | string,
         },
       ];
diff --git a/lib/manager/npm/extract/pnpm.ts b/lib/manager/npm/extract/pnpm.ts
index 2e6baa97c1..022ef6c8f4 100644
--- a/lib/manager/npm/extract/pnpm.ts
+++ b/lib/manager/npm/extract/pnpm.ts
@@ -102,7 +102,11 @@ export async function detectPnpmWorkspaces(
     }
     const packageFilters = packageFilterCache.get(workspaceYamlPath);
     const isPackageInWorkspace =
-      packageFilters !== null && matchesAnyPattern(packageFile, packageFilters);
+      packageFilters !== null &&
+      matchesAnyPattern(
+        packageFile,
+        packageFilters.map((filter) => filter.replace(/\/?$/, '/package.json'))
+      );
     if (isPackageInWorkspace) {
       p.pnpmShrinkwrap = lockFilePath;
     } else {
diff --git a/lib/manager/npm/extract/utils.spec.ts b/lib/manager/npm/extract/utils.spec.ts
new file mode 100644
index 0000000000..a818ae5b43
--- /dev/null
+++ b/lib/manager/npm/extract/utils.spec.ts
@@ -0,0 +1,42 @@
+import { getName } from '../../../../test/util';
+import { matchesAnyPattern } from './utils';
+
+describe(getName(), () => {
+  describe('.matchesAnyPattern()', () => {
+    it('matches package in nested directory', () => {
+      const packageFile = 'packages/group/a/package.json';
+      const packageFilters = ['packages/**'];
+
+      const isPackageInWorkspace = matchesAnyPattern(
+        packageFile,
+        packageFilters
+      );
+
+      expect(isPackageInWorkspace).toBeTrue();
+    });
+
+    it('matches package in non-nested directory', () => {
+      const packageFile = 'non-nested-packages/a/package.json';
+      const packageFilters = ['non-nested-packages/*/*'];
+
+      const isPackageInWorkspace = matchesAnyPattern(
+        packageFile,
+        packageFilters
+      );
+
+      expect(isPackageInWorkspace).toBeTrue();
+    });
+
+    it('matches package in explicitly defined directory', () => {
+      const packageFile = 'solo-package/package.json';
+      const packageFilters = ['solo-package/*'];
+
+      const isPackageInWorkspace = matchesAnyPattern(
+        packageFile,
+        packageFilters
+      );
+
+      expect(isPackageInWorkspace).toBeTrue();
+    });
+  });
+});
-- 
GitLab