From 0ca3d54dbdcbd5660bc9d527f1a40b8c4a07f0a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:02:34 +0000 Subject: [PATCH 1/3] Bump eslint in /npm_and_yarn/helpers in the dev-dependencies group Bumps the dev-dependencies group in /npm_and_yarn/helpers with 1 update: [eslint](https://github.com/eslint/eslint). Updates `eslint` from 9.13.0 to 9.14.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.13.0...v9.14.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor dependency-group: dev-dependencies ... Signed-off-by: dependabot[bot] --- npm_and_yarn/helpers/package-lock.json | 195 ++++++++++++++----------- npm_and_yarn/helpers/package.json | 2 +- 2 files changed, 109 insertions(+), 88 deletions(-) diff --git a/npm_and_yarn/helpers/package-lock.json b/npm_and_yarn/helpers/package-lock.json index 274e9e2bb02..2b396b63879 100644 --- a/npm_and_yarn/helpers/package-lock.json +++ b/npm_and_yarn/helpers/package-lock.json @@ -21,7 +21,7 @@ "helper": "run.js" }, "devDependencies": { - "eslint": "^9.13.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "jest": "^29.7.0", "prettier": "^3.3.3" @@ -723,9 +723,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -836,9 +836,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -866,27 +866,40 @@ } }, "node_modules/@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "dependencies": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" }, "engines": { "node": ">=18.18.0" } }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -901,9 +914,9 @@ } }, "node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", "dev": true, "engines": { "node": ">=18.18" @@ -3159,9 +3172,9 @@ } }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4579,21 +4592,21 @@ } }, "node_modules/eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -4601,9 +4614,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -4651,9 +4664,9 @@ } }, "node_modules/eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -4757,9 +4770,9 @@ } }, "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4842,14 +4855,14 @@ } }, "node_modules/espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "dependencies": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -4859,9 +4872,9 @@ } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -16876,9 +16889,9 @@ } }, "@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true }, "@eslint/config-array": { @@ -16959,9 +16972,9 @@ } }, "@eslint/js": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.13.0.tgz", - "integrity": "sha512-IFLyoY4d72Z5y/6o/BazFBezupzI/taV8sGumxTAVw3lXG9A6md1Dc34T9s1FoD/an9pJH8RHbAxsaEbBed9lA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz", + "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==", "dev": true }, "@eslint/object-schema": { @@ -16980,19 +16993,27 @@ } }, "@humanfs/core": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", - "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true }, "@humanfs/node": { - "version": "0.16.5", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", - "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "requires": { - "@humanfs/core": "^0.19.0", + "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" + }, + "dependencies": { + "@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true + } } }, "@humanwhocodes/module-importer": { @@ -17002,9 +17023,9 @@ "dev": true }, "@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.0.tgz", + "integrity": "sha512-xnRgu9DxZbkWak/te3fcytNyp8MTbuiZIaueg2rgEvBuN55n04nwLYLU9TX/VVlusc9L2ZNXi99nUFNkHXtr5g==", "dev": true }, "@isaacs/cliui": { @@ -18675,9 +18696,9 @@ "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==" }, "acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true }, "acorn-jsx": { @@ -19759,21 +19780,21 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "eslint": { - "version": "9.13.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz", - "integrity": "sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==", + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz", + "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.11.0", + "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.18.0", "@eslint/core": "^0.7.0", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.13.0", + "@eslint/js": "9.14.0", "@eslint/plugin-kit": "^0.2.0", - "@humanfs/node": "^0.16.5", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.3.1", + "@humanwhocodes/retry": "^0.4.0", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", @@ -19781,9 +19802,9 @@ "cross-spawn": "^7.0.2", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.1.0", - "eslint-visitor-keys": "^4.1.0", - "espree": "^10.2.0", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -19851,9 +19872,9 @@ "dev": true }, "eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true }, "find-up": { @@ -19915,9 +19936,9 @@ "requires": {} }, "eslint-scope": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", - "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -19931,20 +19952,20 @@ "dev": true }, "espree": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", - "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", "dev": true, "requires": { - "acorn": "^8.12.0", + "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.1.0" + "eslint-visitor-keys": "^4.2.0" }, "dependencies": { "eslint-visitor-keys": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", - "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true } } diff --git a/npm_and_yarn/helpers/package.json b/npm_and_yarn/helpers/package.json index ada07fc2160..c8c03515a46 100644 --- a/npm_and_yarn/helpers/package.json +++ b/npm_and_yarn/helpers/package.json @@ -21,7 +21,7 @@ "patch-package": "^8.0.0" }, "devDependencies": { - "eslint": "^9.13.0", + "eslint": "^9.14.0", "eslint-config-prettier": "^9.1.0", "jest": "^29.7.0", "prettier": "^3.3.3" From c71a9d9e3c018bb53fda002ae146d4b6b4e6b1b0 Mon Sep 17 00:00:00 2001 From: "dependabot-core-action-automation[bot]" <98560086+dependabot-core-action-automation[bot]@users.noreply.github.com> Date: Tue, 5 Nov 2024 10:27:09 -0500 Subject: [PATCH 2/3] v0.284.0 (#10894) Release notes: https://github.com/dependabot/dependabot-core/releases/tag/v0.284.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Gemfile.lock | 84 ++++++++++++++++++++-------------------- common/lib/dependabot.rb | 2 +- updater/Gemfile.lock | 84 ++++++++++++++++++++-------------------- 3 files changed, 85 insertions(+), 85 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 876d04a6f11..5e5e87c9737 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,20 +1,20 @@ PATH remote: bundler specs: - dependabot-bundler (0.283.0) - dependabot-common (= 0.283.0) + dependabot-bundler (0.284.0) + dependabot-common (= 0.284.0) parallel (~> 1.24) PATH remote: cargo specs: - dependabot-cargo (0.283.0) - dependabot-common (= 0.283.0) + dependabot-cargo (0.284.0) + dependabot-common (= 0.284.0) PATH remote: common specs: - dependabot-common (0.283.0) + dependabot-common (0.284.0) aws-sdk-codecommit (~> 1.28) aws-sdk-ecr (~> 1.5) bundler (>= 1.16, < 3.0.0) @@ -38,113 +38,113 @@ PATH PATH remote: composer specs: - dependabot-composer (0.283.0) - dependabot-common (= 0.283.0) + dependabot-composer (0.284.0) + dependabot-common (= 0.284.0) PATH remote: devcontainers specs: - dependabot-devcontainers (0.283.0) - dependabot-common (= 0.283.0) + dependabot-devcontainers (0.284.0) + dependabot-common (= 0.284.0) PATH remote: docker specs: - dependabot-docker (0.283.0) - dependabot-common (= 0.283.0) + dependabot-docker (0.284.0) + dependabot-common (= 0.284.0) PATH remote: dotnet_sdk specs: - dependabot-dotnet_sdk (0.283.0) - dependabot-common (= 0.283.0) + dependabot-dotnet_sdk (0.284.0) + dependabot-common (= 0.284.0) PATH remote: elm specs: - dependabot-elm (0.283.0) - dependabot-common (= 0.283.0) + dependabot-elm (0.284.0) + dependabot-common (= 0.284.0) PATH remote: git_submodules specs: - dependabot-git_submodules (0.283.0) - dependabot-common (= 0.283.0) + dependabot-git_submodules (0.284.0) + dependabot-common (= 0.284.0) parseconfig (~> 1.0, < 1.1.0) PATH remote: github_actions specs: - dependabot-github_actions (0.283.0) - dependabot-common (= 0.283.0) + dependabot-github_actions (0.284.0) + dependabot-common (= 0.284.0) PATH remote: go_modules specs: - dependabot-go_modules (0.283.0) - dependabot-common (= 0.283.0) + dependabot-go_modules (0.284.0) + dependabot-common (= 0.284.0) PATH remote: gradle specs: - dependabot-gradle (0.283.0) - dependabot-common (= 0.283.0) - dependabot-maven (= 0.283.0) + dependabot-gradle (0.284.0) + dependabot-common (= 0.284.0) + dependabot-maven (= 0.284.0) PATH remote: hex specs: - dependabot-hex (0.283.0) - dependabot-common (= 0.283.0) + dependabot-hex (0.284.0) + dependabot-common (= 0.284.0) PATH remote: maven specs: - dependabot-maven (0.283.0) - dependabot-common (= 0.283.0) + dependabot-maven (0.284.0) + dependabot-common (= 0.284.0) PATH remote: npm_and_yarn specs: - dependabot-npm_and_yarn (0.283.0) - dependabot-common (= 0.283.0) + dependabot-npm_and_yarn (0.284.0) + dependabot-common (= 0.284.0) PATH remote: nuget specs: - dependabot-nuget (0.283.0) - dependabot-common (= 0.283.0) + dependabot-nuget (0.284.0) + dependabot-common (= 0.284.0) rubyzip (>= 2.3.2, < 3.0) PATH remote: pub specs: - dependabot-pub (0.283.0) - dependabot-common (= 0.283.0) + dependabot-pub (0.284.0) + dependabot-common (= 0.284.0) PATH remote: python specs: - dependabot-python (0.283.0) - dependabot-common (= 0.283.0) + dependabot-python (0.284.0) + dependabot-common (= 0.284.0) PATH remote: silent specs: - dependabot-silent (0.283.0) - dependabot-common (= 0.283.0) + dependabot-silent (0.284.0) + dependabot-common (= 0.284.0) PATH remote: swift specs: - dependabot-swift (0.283.0) - dependabot-common (= 0.283.0) + dependabot-swift (0.284.0) + dependabot-common (= 0.284.0) PATH remote: terraform specs: - dependabot-terraform (0.283.0) - dependabot-common (= 0.283.0) + dependabot-terraform (0.284.0) + dependabot-common (= 0.284.0) GEM remote: https://rubygems.org/ diff --git a/common/lib/dependabot.rb b/common/lib/dependabot.rb index 711e5c0ee8f..b83397f281f 100644 --- a/common/lib/dependabot.rb +++ b/common/lib/dependabot.rb @@ -2,5 +2,5 @@ # frozen_string_literal: true module Dependabot - VERSION = "0.283.0" + VERSION = "0.284.0" end diff --git a/updater/Gemfile.lock b/updater/Gemfile.lock index bf933301e11..181db12affb 100644 --- a/updater/Gemfile.lock +++ b/updater/Gemfile.lock @@ -1,20 +1,20 @@ PATH remote: ../bundler specs: - dependabot-bundler (0.283.0) - dependabot-common (= 0.283.0) + dependabot-bundler (0.284.0) + dependabot-common (= 0.284.0) parallel (~> 1.24) PATH remote: ../cargo specs: - dependabot-cargo (0.283.0) - dependabot-common (= 0.283.0) + dependabot-cargo (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../common specs: - dependabot-common (0.283.0) + dependabot-common (0.284.0) aws-sdk-codecommit (~> 1.28) aws-sdk-ecr (~> 1.5) bundler (>= 1.16, < 3.0.0) @@ -38,113 +38,113 @@ PATH PATH remote: ../composer specs: - dependabot-composer (0.283.0) - dependabot-common (= 0.283.0) + dependabot-composer (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../devcontainers specs: - dependabot-devcontainers (0.283.0) - dependabot-common (= 0.283.0) + dependabot-devcontainers (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../docker specs: - dependabot-docker (0.283.0) - dependabot-common (= 0.283.0) + dependabot-docker (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../dotnet_sdk specs: - dependabot-dotnet_sdk (0.283.0) - dependabot-common (= 0.283.0) + dependabot-dotnet_sdk (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../elm specs: - dependabot-elm (0.283.0) - dependabot-common (= 0.283.0) + dependabot-elm (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../git_submodules specs: - dependabot-git_submodules (0.283.0) - dependabot-common (= 0.283.0) + dependabot-git_submodules (0.284.0) + dependabot-common (= 0.284.0) parseconfig (~> 1.0, < 1.1.0) PATH remote: ../github_actions specs: - dependabot-github_actions (0.283.0) - dependabot-common (= 0.283.0) + dependabot-github_actions (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../go_modules specs: - dependabot-go_modules (0.283.0) - dependabot-common (= 0.283.0) + dependabot-go_modules (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../gradle specs: - dependabot-gradle (0.283.0) - dependabot-common (= 0.283.0) - dependabot-maven (= 0.283.0) + dependabot-gradle (0.284.0) + dependabot-common (= 0.284.0) + dependabot-maven (= 0.284.0) PATH remote: ../hex specs: - dependabot-hex (0.283.0) - dependabot-common (= 0.283.0) + dependabot-hex (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../maven specs: - dependabot-maven (0.283.0) - dependabot-common (= 0.283.0) + dependabot-maven (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../npm_and_yarn specs: - dependabot-npm_and_yarn (0.283.0) - dependabot-common (= 0.283.0) + dependabot-npm_and_yarn (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../nuget specs: - dependabot-nuget (0.283.0) - dependabot-common (= 0.283.0) + dependabot-nuget (0.284.0) + dependabot-common (= 0.284.0) rubyzip (>= 2.3.2, < 3.0) PATH remote: ../pub specs: - dependabot-pub (0.283.0) - dependabot-common (= 0.283.0) + dependabot-pub (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../python specs: - dependabot-python (0.283.0) - dependabot-common (= 0.283.0) + dependabot-python (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../silent specs: - dependabot-silent (0.283.0) - dependabot-common (= 0.283.0) + dependabot-silent (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../swift specs: - dependabot-swift (0.283.0) - dependabot-common (= 0.283.0) + dependabot-swift (0.284.0) + dependabot-common (= 0.284.0) PATH remote: ../terraform specs: - dependabot-terraform (0.283.0) - dependabot-common (= 0.283.0) + dependabot-terraform (0.284.0) + dependabot-common (= 0.284.0) GEM remote: https://rubygems.org/ From 2cb56bd4bfb8cb3fc732d68a8b8ec6a0c12156a6 Mon Sep 17 00:00:00 2001 From: kbukum1 Date: Tue, 5 Nov 2024 12:31:26 -0800 Subject: [PATCH 3/3] Add support for centralized package manager abstraction for `npm_and_yarn` ecosystem (#10862) * Refactor npm_and_yarn to use separate classes for npm, yarn, and pnpm, aligning with centralized package manager abstraction used across ecosystems. --- .../dependabot/npm_and_yarn/file_fetcher.rb | 81 ++++-- .../dependabot/npm_and_yarn/file_parser.rb | 93 ++++++- .../lib/dependabot/npm_and_yarn/helpers.rb | 31 ++- .../npm_and_yarn/package_manager.rb | 251 +++++++++++++++++- .../npm_and_yarn/npm_package_manager_spec.rb | 50 ++++ .../package_manager_detector_spec.rb | 166 ++++++++++++ .../package_manager_helper_spec.rb | 121 +++++++++ .../npm_and_yarn/pnpm_package_manager_spec.rb | 50 ++++ .../npm_and_yarn/yarn_package_manager_spec.rb | 50 ++++ 9 files changed, 834 insertions(+), 59 deletions(-) create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_detector_spec.rb create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb create mode 100644 npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb index eb9161a676a..3539503ac46 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb @@ -182,71 +182,93 @@ def inferred_npmrc # rubocop:disable Metrics/PerceivedComplexity sig { returns(T.nilable(T.any(Integer, String))) } def npm_version - @npm_version ||= T.let(package_manager.setup("npm"), T.nilable(T.any(Integer, String))) + @npm_version ||= T.let(package_manager_helper.setup(NpmPackageManager::NAME), T.nilable(T.any(Integer, String))) end sig { returns(T.nilable(T.any(Integer, String))) } def yarn_version - @yarn_version ||= T.let(package_manager.setup("yarn"), T.nilable(T.any(Integer, String))) + @yarn_version ||= T.let( + package_manager_helper.setup(YarnPackageManager::NAME), + T.nilable(T.any(Integer, String)) + ) end sig { returns(T.nilable(T.any(Integer, String))) } def pnpm_version - @pnpm_version ||= T.let(package_manager.setup("pnpm"), T.nilable(T.any(Integer, String))) + @pnpm_version ||= T.let( + package_manager_helper.setup(PNPMPackageManager::NAME), + T.nilable(T.any(Integer, String)) + ) end - sig { returns(PackageManager) } - def package_manager - @package_manager ||= T.let(PackageManager.new( - parsed_package_json, - lockfiles: { npm: package_lock || shrinkwrap, yarn: yarn_lock, pnpm: pnpm_lock } - ), T.nilable(PackageManager)) + sig { returns(PackageManagerHelper) } + def package_manager_helper + @package_manager_helper ||= T.let( + PackageManagerHelper.new( + parsed_package_json, + lockfiles: lockfiles + ), T.nilable(PackageManagerHelper) + ) + end + + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def lockfiles + { + npm: package_lock || shrinkwrap, + yarn: yarn_lock, + pnpm: pnpm_lock + } end sig { returns(DependencyFile) } def package_json - @package_json ||= T.let(fetch_file_from_host("package.json"), T.nilable(DependencyFile)) + @package_json ||= T.let(fetch_file_from_host(MANIFEST_FILENAME), T.nilable(DependencyFile)) end sig { returns(T.nilable(DependencyFile)) } def package_lock return @package_lock if defined?(@package_lock) - @package_lock ||= T.let(fetch_file_if_present("package-lock.json"), T.nilable(DependencyFile)) + @package_lock ||= T.let(fetch_file_if_present(NpmPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile)) end sig { returns(T.nilable(DependencyFile)) } def yarn_lock return @yarn_lock if defined?(@yarn_lock) - @yarn_lock ||= T.let(fetch_file_if_present("yarn.lock"), T.nilable(DependencyFile)) + @yarn_lock ||= T.let(fetch_file_if_present(YarnPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile)) end sig { returns(T.nilable(DependencyFile)) } def pnpm_lock return @pnpm_lock if defined?(@pnpm_lock) - @pnpm_lock ||= T.let(fetch_file_if_present("pnpm-lock.yaml"), T.nilable(DependencyFile)) + @pnpm_lock ||= T.let(fetch_file_if_present(PNPMPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile)) end sig { returns(T.nilable(DependencyFile)) } def shrinkwrap return @shrinkwrap if defined?(@shrinkwrap) - @shrinkwrap ||= T.let(fetch_file_if_present("npm-shrinkwrap.json"), T.nilable(DependencyFile)) + @shrinkwrap ||= T.let( + fetch_file_if_present( + NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME + ), + T.nilable(DependencyFile) + ) end sig { returns(T.nilable(DependencyFile)) } def npmrc return @npmrc if defined?(@npmrc) - @npmrc ||= T.let(fetch_support_file(".npmrc"), T.nilable(DependencyFile)) + @npmrc ||= T.let(fetch_support_file(NpmPackageManager::RC_FILENAME), T.nilable(DependencyFile)) return @npmrc if @npmrc || directory == "/" # Loop through parent directories looking for an npmrc (1..directory.split("/").count).each do |i| - @npmrc = fetch_file_from_host(("../" * i) + ".npmrc") + @npmrc = fetch_file_from_host(("../" * i) + NpmPackageManager::RC_FILENAME) .tap { |f| f.support_file = true } break if @npmrc rescue Dependabot::DependencyFileNotFound @@ -261,13 +283,13 @@ def npmrc def yarnrc return @yarnrc if defined?(@yarnrc) - @yarnrc ||= T.let(fetch_support_file(".yarnrc"), T.nilable(DependencyFile)) + @yarnrc ||= T.let(fetch_support_file(YarnPackageManager::RC_FILENAME), T.nilable(DependencyFile)) return @yarnrc if @yarnrc || directory == "/" # Loop through parent directories looking for an yarnrc (1..directory.split("/").count).each do |i| - @yarnrc = fetch_file_from_host(("../" * i) + ".yarnrc") + @yarnrc = fetch_file_from_host(("../" * i) + YarnPackageManager::RC_FILENAME) .tap { |f| f.support_file = true } break if @yarnrc rescue Dependabot::DependencyFileNotFound @@ -280,21 +302,24 @@ def yarnrc sig { returns(T.nilable(DependencyFile)) } def yarnrc_yml - @yarnrc_yml ||= T.let(fetch_support_file(".yarnrc.yml"), T.nilable(DependencyFile)) + @yarnrc_yml ||= T.let(fetch_support_file(YarnPackageManager::RC_YML_FILENAME), T.nilable(DependencyFile)) end sig { returns(T.nilable(DependencyFile)) } def pnpm_workspace_yaml return @pnpm_workspace_yaml if defined?(@pnpm_workspace_yaml) - @pnpm_workspace_yaml = T.let(fetch_support_file("pnpm-workspace.yaml"), T.nilable(DependencyFile)) + @pnpm_workspace_yaml = T.let( + fetch_support_file(PNPMPackageManager::PNPM_WS_YML_FILENAME), + T.nilable(DependencyFile) + ) end sig { returns(T.nilable(DependencyFile)) } def lerna_json return @lerna_json if defined?(@lerna_json) - @lerna_json = T.let(fetch_support_file("lerna.json"), T.nilable(DependencyFile)) + @lerna_json = T.let(fetch_support_file(LERNA_JSON_FILENAME), T.nilable(DependencyFile)) end sig { returns(T::Array[DependencyFile]) } @@ -329,7 +354,7 @@ def path_dependencies(fetched_files) filename = path # NPM/Yarn support loading path dependencies from tarballs: # https://docs.npmjs.com/cli/pack.html - filename = File.join(filename, "package.json") unless filename.end_with?(".tgz", ".tar", ".tar.gz") + filename = File.join(filename, MANIFEST_FILENAME) unless filename.end_with?(".tgz", ".tar", ".tar.gz") cleaned_name = Pathname.new(filename).cleanpath.to_path next if fetched_files.map(&:name).include?(cleaned_name) @@ -380,7 +405,7 @@ def path_dependency_details(fetched_files) # rubocop:disable Metrics/AbcSize sig { params(file: DependencyFile).returns(T::Array[[String, String]]) } def path_dependency_details_from_manifest(file) - return [] unless file.name.end_with?("package.json") + return [] unless file.name.end_with?(MANIFEST_FILENAME) current_dir = file.name.rpartition("/").first current_dir = nil if current_dir == "" @@ -471,9 +496,9 @@ def fetch_lerna_packages_from_path(path) return [] unless package_json [package_json] + [ - fetch_file_if_present(File.join(path, "package-lock.json")), - fetch_file_if_present(File.join(path, "yarn.lock")), - fetch_file_if_present(File.join(path, "npm-shrinkwrap.json")) + fetch_file_if_present(File.join(path, NpmPackageManager::LOCKFILE_NAME)), + fetch_file_if_present(File.join(path, YarnPackageManager::LOCKFILE_NAME)), + fetch_file_if_present(File.join(path, NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME)) ] end @@ -542,7 +567,7 @@ def recursive_find_directories(glob, prefix = "") sig { params(workspace: String).returns(T.nilable(DependencyFile)) } def fetch_package_json_if_present(workspace) - file = File.join(workspace, "package.json") + file = File.join(workspace, MANIFEST_FILENAME) begin fetch_file_from_host(file) @@ -635,4 +660,4 @@ def parsed_lerna_json end Dependabot::FileFetchers - .register("npm_and_yarn", Dependabot::NpmAndYarn::FileFetcher) + .register(Dependabot::NpmAndYarn::ECOSYSTEM, Dependabot::NpmAndYarn::FileFetcher) diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_parser.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_parser.rb index e78b6c23a81..5c19fcfe49d 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_parser.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_parser.rb @@ -19,7 +19,7 @@ module Dependabot module NpmAndYarn - class FileParser < Dependabot::FileParsers::Base + class FileParser < Dependabot::FileParsers::Base # rubocop:disable Metrics/ClassLength extend T::Sig require "dependabot/file_parsers/base/dependency_set" @@ -78,8 +78,82 @@ def parse end end + sig { returns(Ecosystem) } + def ecosystem + @ecosystem ||= T.let( + Ecosystem.new( + name: ECOSYSTEM, + package_manager: package_manager_helper.package_manager + ), + T.nilable(Ecosystem) + ) + end + private + sig { returns(PackageManagerHelper) } + def package_manager_helper + @package_manager_helper ||= T.let( + PackageManagerHelper.new( + parsed_package_json, + lockfiles: lockfiles + ), T.nilable(PackageManagerHelper) + ) + end + + sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) } + def lockfiles + { + npm: package_lock || shrinkwrap, + yarn: yarn_lock, + pnpm: pnpm_lock + } + end + + sig { returns(T.untyped) } + def parsed_package_json + JSON.parse(T.must(package_json.content)) + rescue JSON::ParserError + raise Dependabot::DependencyFileNotParseable, package_json.path + end + + sig { returns(Dependabot::DependencyFile) } + def package_json + # Declare the instance variable with T.let and the correct type + @package_json ||= T.let( + T.must(dependency_files.find { |f| f.name == MANIFEST_FILENAME }), + T.nilable(Dependabot::DependencyFile) + ) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def shrinkwrap + @shrinkwrap ||= T.let(dependency_files.find do |f| + f.name == NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME + end, T.nilable(Dependabot::DependencyFile)) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def package_lock + @package_lock ||= T.let(dependency_files.find do |f| + f.name == NpmPackageManager::LOCKFILE_NAME + end, T.nilable(Dependabot::DependencyFile)) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def yarn_lock + @yarn_lock ||= T.let(dependency_files.find do |f| + f.name == YarnPackageManager::LOCKFILE_NAME + end, T.nilable(Dependabot::DependencyFile)) + end + + sig { returns(T.nilable(Dependabot::DependencyFile)) } + def pnpm_lock + @pnpm_lock ||= T.let(dependency_files.find do |f| + f.name == PNPMPackageManager::LOCKFILE_NAME + end, T.nilable(Dependabot::DependencyFile)) + end + sig { returns(Dependabot::FileParsers::Base::DependencySet) } def manifest_dependencies dependency_set = DependencySet.new @@ -154,7 +228,7 @@ def build_dependency(file:, type:, name:, requirement:) Dependency.new( name: name, version: converted_version, - package_manager: "npm_and_yarn", + package_manager: ECOSYSTEM, requirements: [{ requirement: requirement_for(requirement), file: file.name, @@ -166,7 +240,10 @@ def build_dependency(file:, type:, name:, requirement:) sig { override.void } def check_required_files - raise DependencyFileNotFound.new(nil, "package.json not found.") unless get_original_file("package.json") + return if get_original_file(MANIFEST_FILENAME) + + raise DependencyFileNotFound.new(nil, + "#{MANIFEST_FILENAME} not found.") end sig { params(requirement: String).returns(T::Boolean) } @@ -186,7 +263,7 @@ def local_path?(requirement) sig { params(requirement: String).returns(T::Boolean) } def alias_package?(requirement) - requirement.start_with?("npm:") + requirement.start_with?("#{NpmPackageManager::NAME}:") end sig { params(requirement: String).returns(T::Boolean) } @@ -208,7 +285,7 @@ def git_url_with_semver?(requirement) sig { params(name: String).returns(T::Boolean) } def aliased_package_name?(name) - name.include?("@npm:") + name.include?("@#{NpmPackageManager::NAME}:") end sig { returns(T::Array[String]) } @@ -370,8 +447,8 @@ def support_package_files def sub_package_files return T.must(@sub_package_files) if defined?(@sub_package_files) - files = dependency_files.select { |f| f.name.end_with?("package.json") } - .reject { |f| f.name == "package.json" } + files = dependency_files.select { |f| f.name.end_with?(MANIFEST_FILENAME) } + .reject { |f| f.name == MANIFEST_FILENAME } .reject { |f| f.name.include?("node_modules/") } @sub_package_files ||= T.let(files, T.nilable(T::Array[Dependabot::DependencyFile])) end @@ -380,7 +457,7 @@ def sub_package_files def package_files @package_files ||= T.let( [ - dependency_files.find { |f| f.name == "package.json" }, + dependency_files.find { |f| f.name == MANIFEST_FILENAME }, *sub_package_files ].compact, T.nilable(T::Array[DependencyFile]) ) diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb index baed146df29..e5e20fdd6d0 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/helpers.rb @@ -37,7 +37,7 @@ module Helpers # Determines the npm version depends to the feature flag # If the feature flag is enabled, we are going to use the minimum version npm 8 # Otherwise, we are going to use old versionining npm 6 - sig { params(lockfile: DependencyFile).returns(Integer) } + sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) } def self.npm_version_numeric(lockfile) fallback_version_npm8 = Dependabot::Experiments.enabled?(:npm_fallback_version_above_v6) @@ -46,10 +46,15 @@ def self.npm_version_numeric(lockfile) npm_version_numeric_npm6_or_higher(lockfile) end - sig { params(lockfile: DependencyFile).returns(Integer) } + sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) } def self.npm_version_numeric_npm6_or_higher(lockfile) - lockfile_content = T.must(lockfile.content) - return NPM_V8 if JSON.parse(lockfile_content)["lockfileVersion"].to_i >= 2 + lockfile_content = lockfile&.content + + if lockfile_content.nil? || + lockfile_content.strip.empty? || + JSON.parse(lockfile_content)["lockfileVersion"].to_i >= 2 + return NPM_V8 + end NPM_V6 rescue JSON::ParserError @@ -60,9 +65,9 @@ def self.npm_version_numeric_npm6_or_higher(lockfile) # - NPM 7 uses lockfileVersion 2 # - NPM 8 uses lockfileVersion 2 # - NPM 9 uses lockfileVersion 3 - sig { params(lockfile: DependencyFile).returns(Integer) } + sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) } def self.npm_version_numeric_npm8_or_higher(lockfile) - lockfile_content = lockfile.content + lockfile_content = lockfile&.content # Return default NPM version if there's no lockfile or it's empty return NPM_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty? @@ -85,8 +90,12 @@ def self.npm_version_numeric_npm8_or_higher(lockfile) NPM_DEFAULT_VERSION # Fallback to default npm version if parsing fails end - sig { params(yarn_lock: DependencyFile).returns(Integer) } + sig { params(yarn_lock: T.nilable(DependencyFile)).returns(Integer) } def self.yarn_version_numeric(yarn_lock) + lockfile_content = yarn_lock&.content + + return YARN_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty? + if yarn_berry?(yarn_lock) YARN_DEFAULT_VERSION else @@ -97,8 +106,12 @@ def self.yarn_version_numeric(yarn_lock) # Mapping from lockfile versions to PNPM versions is at # https://github.com/pnpm/spec/tree/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile, but simplify it for now. - sig { params(pnpm_lock: DependencyFile).returns(Integer) } + sig { params(pnpm_lock: T.nilable(DependencyFile)).returns(Integer) } def self.pnpm_version_numeric(pnpm_lock) + lockfile_content = pnpm_lock&.content + + return PNPM_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty? + pnpm_lockfile_version = pnpm_lockfile_version(pnpm_lock).to_f return PNPM_V9 if pnpm_lockfile_version >= 9.0 return PNPM_V8 if pnpm_lockfile_version >= 6.0 @@ -117,7 +130,7 @@ def self.fetch_yarnrc_yml_value(key, default_value) sig { params(package_lock: T.nilable(DependencyFile)).returns(T::Boolean) } def self.npm8?(package_lock) - return true unless package_lock + return true unless package_lock&.content npm_version_numeric(package_lock) == NPM_V8 end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb index c60d98d6b5a..90e80df590f 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/package_manager.rb @@ -2,18 +2,225 @@ # frozen_string_literal: true require "dependabot/shared_helpers" +require "dependabot/ecosystem" require "dependabot/npm_and_yarn/version_selector" module Dependabot module NpmAndYarn - class PackageManager + ECOSYSTEM = "npm_and_yarn" + MANIFEST_FILENAME = "package.json" + LERNA_JSON_FILENAME = "lerna.json" + + MANIFEST_PACKAGE_MANAGER_KEY = "packageManager" + MANIFEST_ENGINES_KEY = "engines" + + class NpmPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "npm" + RC_FILENAME = ".npmrc" + LOCKFILE_NAME = "package-lock.json" + SHRINKWRAP_LOCKFILE_NAME = "npm-shrinkwrap.json" + + NPM_V6 = "6" + NPM_V7 = "7" + NPM_V8 = "8" + NPM_V9 = "9" + + # Keep versions in ascending order + SUPPORTED_VERSIONS = T.let([ + Version.new(NPM_V6), + Version.new(NPM_V7), + Version.new(NPM_V8), + Version.new(NPM_V9) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig { params(raw_version: String).void } + def initialize(raw_version) + super( + NAME, + Version.new(raw_version), + DEPRECATED_VERSIONS, + SUPPORTED_VERSIONS + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + + class YarnPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "yarn" + RC_FILENAME = ".yarnrc" + RC_YML_FILENAME = ".yarnrc.yml" + LOCKFILE_NAME = "yarn.lock" + + YARN_V1 = "1" + YARN_V2 = "2" + YARN_V3 = "3" + + SUPPORTED_VERSIONS = T.let([ + Version.new(YARN_V1), + Version.new(YARN_V2), + Version.new(YARN_V3) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig { params(raw_version: String).void } + def initialize(raw_version) + super( + NAME, + Version.new(raw_version), + DEPRECATED_VERSIONS, + SUPPORTED_VERSIONS + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + + class PNPMPackageManager < Ecosystem::VersionManager + extend T::Sig + NAME = "pnpm" + LOCKFILE_NAME = "pnpm-lock.yaml" + PNPM_WS_YML_FILENAME = "pnpm-workspace.yaml" + + PNPM_V7 = "7" + PNPM_V8 = "8" + PNPM_V9 = "9" + + SUPPORTED_VERSIONS = T.let([ + Version.new(PNPM_V7), + Version.new(PNPM_V8), + Version.new(PNPM_V9) + ].freeze, T::Array[Dependabot::Version]) + + DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version]) + + sig { params(raw_version: String).void } + def initialize(raw_version) + super( + NAME, + Version.new(raw_version), + DEPRECATED_VERSIONS, + SUPPORTED_VERSIONS + ) + end + + sig { override.returns(T::Boolean) } + def deprecated? + false + end + + sig { override.returns(T::Boolean) } + def unsupported? + false + end + end + + DEFAULT_PACKAGE_MANAGER = NpmPackageManager::NAME + + PACKAGE_MANAGER_CLASSES = { + NpmPackageManager::NAME => NpmPackageManager, + YarnPackageManager::NAME => YarnPackageManager, + PNPMPackageManager::NAME => PNPMPackageManager + }.freeze + + class PackageManagerDetector + extend T::Sig + extend T::Helpers + + sig do + params( + lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)], + package_json: T::Hash[String, T.untyped] + ).void + end + def initialize(lockfiles, package_json) + @lockfiles = lockfiles + @package_json = package_json + @manifest_package_manager = package_json["packageManager"] + @engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil) + end + + # Returns npm, yarn, or pnpm based on the lockfiles, package.json, and engines + # Defaults to npm if no package manager is detected + sig { returns(String) } + def detect_package_manager + name_from_lockfiles || name_from_package_manager_attr || name_from_engines || DEFAULT_PACKAGE_MANAGER + end + + private + + sig { returns(T.nilable(String)) } + def name_from_lockfiles + PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash + return manager_name.to_s if @lockfiles[manager_name.to_sym] + end + nil + end + + sig { returns(T.nilable(String)) } + def name_from_package_manager_attr + return unless @manifest_package_manager + + PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash + return manager_name.to_s if @manifest_package_manager.start_with?("#{manager_name}@") + end + end + + sig { returns(T.nilable(String)) } + def name_from_engines + return unless @engines.is_a?(Hash) + + PACKAGE_MANAGER_CLASSES.each_key do |manager_name| + return manager_name if @engines[manager_name] + end + nil + end + end + + class PackageManagerHelper extend T::Sig extend T::Helpers + + sig do + params( + package_json: T::Hash[String, T.untyped], + lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)] + ).void + end def initialize(package_json, lockfiles:) @package_json = package_json @lockfiles = lockfiles - @package_manager = package_json.fetch("packageManager", nil) - @engines = package_json.fetch("engines", nil) + @manifest_package_manager = package_json[MANIFEST_PACKAGE_MANAGER_KEY] + @engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil) + @package_manager_detector = PackageManagerDetector.new(@lockfiles, @package_json) + end + + sig { returns(Ecosystem::VersionManager) } + def package_manager + package_manager_by_name( + @package_manager_detector.detect_package_manager + ) end # rubocop:disable Metrics/CyclomaticComplexity @@ -23,24 +230,29 @@ def setup(name) # i.e. if { engines : "pnpm" : "6" } and { packageManager: "pnpm@6.0.2" }, # we go for the specificity mentioned in packageManager (6.0.2) - unless @package_manager&.start_with?("#{name}@") || (@package_manager&.==name.to_s) || @package_manager.nil? + unless @manifest_package_manager&.start_with?("#{name}@") || + (@manifest_package_manager&.==name.to_s) || + @manifest_package_manager.nil? return end - if @engines && @package_manager.nil? + if @engines && @manifest_package_manager.nil? # if "packageManager" doesn't exists in manifest file, # we check if we can extract "engines" information version = check_engine_version(name) - elsif @package_manager&.==name.to_s + elsif @manifest_package_manager&.==name.to_s # if "packageManager" is found but no version is specified (i.e. pnpm@1.2.3), # we check if we can get "engines" info to override default version version = check_engine_version(name) if @engines - elsif @package_manager&.start_with?("#{name}@") + elsif @manifest_package_manager&.start_with?("#{name}@") # if "packageManager" info has version specification i.e. yarn@3.3.1 # we go with the version in "packageManager" - Dependabot.logger.info("Found \"packageManager\" : \"#{@package_manager}\". Skipped checking \"engines\".") + Dependabot.logger.info( + "Found \"#{MANIFEST_PACKAGE_MANAGER_KEY}\" : \"#{@manifest_package_manager}\". " \ + "Skipped checking \"#{MANIFEST_ENGINES_KEY}\"." + ) end version ||= requested_version(name) @@ -55,7 +267,7 @@ def setup(name) if version raise_if_unsupported!(name, version.to_s) - install(name, version) if name == "pnpm" + install(name, version) if name == PNPMPackageManager::NAME end end @@ -66,11 +278,22 @@ def setup(name) private + sig { params(name: String).returns(Ecosystem::VersionManager) } + def package_manager_by_name(name) + package_manager_class = PACKAGE_MANAGER_CLASSES[name] + + package_manager_class ||= PACKAGE_MANAGER_CLASSES[DEFAULT_PACKAGE_MANAGER] + + version = Helpers.send(:"#{name}_version_numeric", @lockfiles[name.to_sym]) + + package_manager_class.new(version.to_s) + end + def raise_if_unsupported!(name, version) - return unless name == "pnpm" + return unless name == PNPMPackageManager::NAME return unless Version.new(version) < Version.new("7") - raise ToolVersionNotSupported.new("PNPM", version, "7.*, 8.*") + raise ToolVersionNotSupported.new(PNPMPackageManager::NAME.upcase, version, "7.*, 8.*") end def install(name, version) @@ -83,9 +306,9 @@ def install(name, version) end def requested_version(name) - return unless @package_manager + return unless @manifest_package_manager - match = @package_manager.match(/^#{name}@(?\d+.\d+.\d+)/) + match = @manifest_package_manager.match(/^#{name}@(?\d+.\d+.\d+)/) return unless match Dependabot.logger.info("Requested version #{match['version']}") @@ -111,7 +334,7 @@ def check_engine_version(name) return if engine_versions.empty? version = engine_versions[name] - Dependabot.logger.info("Returned (engines) info \"#{name}\" : \"#{version}\"") + Dependabot.logger.info("Returned (#{MANIFEST_ENGINES_KEY}) info \"#{name}\" : \"#{version}\"") version end end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb new file mode 100644 index 00000000000..77ac6c251be --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/npm_package_manager_spec.rb @@ -0,0 +1,50 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "dependabot/ecosystem" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::NpmPackageManager do + let(:package_manager) { described_class.new(version) } + + describe "#initialize" do + context "when version is a String" do + let(:version) { "8" } + + it "sets the version correctly" do + expect(package_manager.version).to eq(Dependabot::Version.new(version)) + end + + it "sets the name correctly" do + expect(package_manager.name).to eq(Dependabot::NpmAndYarn::NpmPackageManager::NAME) + end + + it "sets the deprecated_versions correctly" do + expect(package_manager.deprecated_versions).to eq( + Dependabot::NpmAndYarn::NpmPackageManager::DEPRECATED_VERSIONS + ) + end + + it "sets the supported_versions correctly" do + expect(package_manager.supported_versions).to eq(Dependabot::NpmAndYarn::NpmPackageManager::SUPPORTED_VERSIONS) + end + end + end + + describe "#deprecated?" do + let(:version) { "6" } + + it "returns false" do + expect(package_manager.deprecated?).to be false + end + end + + describe "#unsupported?" do + let(:version) { "5" } + + it "returns false for supported versions" do + expect(package_manager.unsupported?).to be false + end + end +end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_detector_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_detector_spec.rb new file mode 100644 index 00000000000..4c14f9fa513 --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_detector_spec.rb @@ -0,0 +1,166 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::PackageManagerDetector do + let(:npm_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "package-lock.json", + content: <<~LOCKFILE + { + "name": "example-npm-project", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-abc123" + } + } + } + LOCKFILE + ) + end + + let(:yarn_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "yarn.lock", + content: <<~LOCKFILE + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + lodash@^4.17.20: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#abc123" + integrity sha512-abc123 + LOCKFILE + ) + end + + let(:pnpm_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "pnpm-lock.yaml", + content: <<~LOCKFILE + lockfileVersion: 5.4 + + dependencies: + lodash: + specifier: ^4.17.20 + version: 4.17.21 + resolution: + integrity: sha512-abc123 + tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz + LOCKFILE + ) + end + + let(:lockfiles) { { npm: npm_lockfile, yarn: yarn_lockfile, pnpm: pnpm_lockfile } } + let(:package_json) { { "packageManager" => "npm@7" } } + let(:detector) { described_class.new(lockfiles, package_json) } + + describe "#detect_package_manager" do + context "when npm lockfile exists" do + it "returns npm as the package manager" do + expect(detector.detect_package_manager).to eq("npm") + end + end + + context "when yarn lockfile exists and npm lockfile is absent" do + let(:lockfiles) { { yarn: yarn_lockfile } } + + it "returns yarn as the package manager" do + expect(detector.detect_package_manager).to eq("yarn") + end + end + + context "when pnpm lockfile exists and other lockfiles are absent" do + let(:lockfiles) { { pnpm: pnpm_lockfile } } + + it "returns pnpm as the package manager" do + expect(detector.detect_package_manager).to eq("pnpm") + end + end + + context "when no lockfile but packageManager attribute exists in package.json" do + let(:lockfiles) { {} } + + it "returns npm from packageManager attribute" do + expect(detector.detect_package_manager).to eq("npm") + end + end + + context "when no lockfile and packageManager attribute, but engines field exists" do + let(:lockfiles) { {} } + + context "when there is single package manager in engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "yarn" => "1" } } } + + it "returns yarn from engines field" do + expect(detector.detect_package_manager).to eq("yarn") + end + end + + context "when there are multiple package managers (npm, yarn, pnpm) in engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "npm" => "1", "yarn" => "1", "pnpm" => "1", "node" => "2" } } } + + it "returns first (npm) found valid package manager in order of (npm, yarn, pnpm)" do + expect(detector.detect_package_manager).to eq("npm") + end + end + + context "when there are multiple package managers (npm, yarn, pnpm) in engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "node" => "2", "yarn" => "1", "pnpm" => "1" } } } + + it "returns first (yarn) found valid package manager in order of (npm, yarn, pnpm)" do + expect(detector.detect_package_manager).to eq("yarn") + end + end + + context "when there are multiple package managers in engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "npm" => "1", "yarn" => "1", "pnpm" => "1", "unknown" => "2" } } } + + it "returns npm from engines field" do + expect(detector.detect_package_manager).to eq("npm") + end + end + + context "when there is zero package manager in engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => {} } } + + it "returns default (npm) when no package manager can be detected" do + expect(detector.detect_package_manager).to eq("npm") + end + end + + context "when there are unknown keys in the engines" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "node" => "1" } } } + + it "returns default (npm)" do + expect(detector.detect_package_manager).to eq("npm") + end + end + end + + context "when neither lockfile, packageManager, nor engines field exists" do + let(:lockfiles) { {} } + let(:package_json) { {} } + + it "returns default (npm)" do + expect(detector.detect_package_manager).to eq("npm") + end + end + end +end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb new file mode 100644 index 00000000000..a28675147b4 --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/package_manager_helper_spec.rb @@ -0,0 +1,121 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "dependabot/npm_and_yarn/helpers" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::PackageManagerHelper do + let(:npm_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "package-lock.json", + content: <<~LOCKFILE + { + "name": "example-npm-project", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-abc123" + } + } + } + LOCKFILE + ) + end + + let(:yarn_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "yarn.lock", + content: <<~LOCKFILE + # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. + # yarn lockfile v1 + + lodash@^4.17.20: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#abc123" + integrity sha512-abc123 + LOCKFILE + ) + end + + let(:pnpm_lockfile) do + instance_double( + Dependabot::DependencyFile, + name: "pnpm-lock.yaml", + content: <<~LOCKFILE + lockfileVersion: 5.4 + + dependencies: + lodash: + specifier: ^4.17.20 + version: 4.17.21 + resolution: + integrity: sha512-abc123 + tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz + LOCKFILE + ) + end + + let(:lockfiles) { { npm: npm_lockfile, yarn: yarn_lockfile, pnpm: pnpm_lockfile } } + let(:package_json) { { "packageManager" => "npm@7" } } + let(:helper) { described_class.new(package_json, lockfiles: lockfiles) } + + describe "#package_manager" do + context "when npm lockfile exists" do + it "returns an NpmPackageManager instance" do + allow(Dependabot::NpmAndYarn::Helpers).to receive(:npm_version_numeric).and_return("7") + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::NpmPackageManager) + end + end + + context "when only yarn lockfile exists" do + let(:lockfiles) { { yarn: yarn_lockfile } } + + it "returns a YarnPackageManager instance" do + allow(Dependabot::NpmAndYarn::Helpers).to receive(:yarn_version_numeric).and_return("1") + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::YarnPackageManager) + end + end + + context "when only pnpm lockfile exists" do + let(:lockfiles) { { pnpm: pnpm_lockfile } } + + it "returns a PNPMPackageManager instance" do + allow(Dependabot::NpmAndYarn::Helpers).to receive(:pnpm_version_numeric).and_return("7") + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::PNPMPackageManager) + end + end + + context "when no lockfile but packageManager attribute exists" do + let(:lockfiles) { {} } + + it "returns an NpmPackageManager instance based on the packageManager attribute" do + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::NpmPackageManager) + end + end + + context "when no lockfile and packageManager attribute, but engines field exists" do + let(:lockfiles) { {} } + let(:package_json) { { "engines" => { "yarn" => "1" } } } + + it "returns a YarnPackageManager instance from engines field" do + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::YarnPackageManager) + end + end + + context "when neither lockfile, packageManager, nor engines field exists" do + let(:lockfiles) { {} } + let(:package_json) { {} } + + it "returns default package manager" do + expect(helper.package_manager).to be_a(Dependabot::NpmAndYarn::NpmPackageManager) + end + end + end +end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb new file mode 100644 index 00000000000..e613c8c5669 --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/pnpm_package_manager_spec.rb @@ -0,0 +1,50 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "dependabot/ecosystem" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::PNPMPackageManager do + let(:package_manager) { described_class.new(version) } + + describe "#initialize" do + context "when version is a String" do + let(:version) { "9" } + + it "sets the version correctly" do + expect(package_manager.version).to eq(Dependabot::Version.new(version)) + end + + it "sets the name correctly" do + expect(package_manager.name).to eq(Dependabot::NpmAndYarn::PNPMPackageManager::NAME) + end + + it "sets the deprecated_versions correctly" do + expect(package_manager.deprecated_versions).to eq( + Dependabot::NpmAndYarn::PNPMPackageManager::DEPRECATED_VERSIONS + ) + end + + it "sets the supported_versions correctly" do + expect(package_manager.supported_versions).to eq(Dependabot::NpmAndYarn::PNPMPackageManager::SUPPORTED_VERSIONS) + end + end + end + + describe "#deprecated?" do + let(:version) { "7" } + + it "returns false" do + expect(package_manager.deprecated?).to be false + end + end + + describe "#unsupported?" do + let(:version) { "6" } + + it "returns true for unsupported versions" do + expect(package_manager.unsupported?).to be false + end + end +end diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb new file mode 100644 index 00000000000..d052bf9f2ee --- /dev/null +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_package_manager_spec.rb @@ -0,0 +1,50 @@ +# typed: false +# frozen_string_literal: true + +require "dependabot/npm_and_yarn/package_manager" +require "dependabot/ecosystem" +require "spec_helper" + +RSpec.describe Dependabot::NpmAndYarn::YarnPackageManager do + let(:package_manager) { described_class.new(version) } + + describe "#initialize" do + context "when version is a String" do + let(:version) { "2" } + + it "sets the version correctly" do + expect(package_manager.version).to eq(Dependabot::Version.new(version)) + end + + it "sets the name correctly" do + expect(package_manager.name).to eq(Dependabot::NpmAndYarn::YarnPackageManager::NAME) + end + + it "sets the deprecated_versions correctly" do + expect(package_manager.deprecated_versions).to eq( + Dependabot::NpmAndYarn::YarnPackageManager::DEPRECATED_VERSIONS + ) + end + + it "sets the supported_versions correctly" do + expect(package_manager.supported_versions).to eq(Dependabot::NpmAndYarn::YarnPackageManager::SUPPORTED_VERSIONS) + end + end + end + + describe "#deprecated?" do + let(:version) { "1" } + + it "returns false" do + expect(package_manager.deprecated?).to be false + end + end + + describe "#unsupported?" do + let(:version) { "4" } + + it "returns false for supported versions" do + expect(package_manager.unsupported?).to be false + end + end +end