diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb index 8bef8d1a10..04878262b1 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb @@ -45,6 +45,12 @@ def updated_pnpm_lock_content(pnpm_lock) MISSING_PACKAGE = /ERR_PNPM_FETCH_404[ [^:print:]]+GET (?.*): (?:Not Found)? - 404/ UNAUTHORIZED_PACKAGE = /ERR_PNPM_FETCH_401[ [^:print:]]+GET (?.*): Unauthorized - 401/ + # ERR_PNPM_FETCH ERROR CODES + ERR_PNPM_FETCH_401 = /ERR_PNPM_FETCH_401.*GET (?.*): - 401/ + ERR_PNPM_FETCH_403 = /ERR_PNPM_FETCH_403.*GET (?.*): - 403/ + ERR_PNPM_FETCH_500 = /ERR_PNPM_FETCH_500.*GET (?.*): - 500/ + ERR_PNPM_FETCH_502 = /ERR_PNPM_FETCH_502.*GET (?.*): - 502/ + def run_pnpm_update(pnpm_lock:) SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do File.write(".npmrc", npmrc_content(pnpm_lock)) @@ -107,12 +113,12 @@ def handle_pnpm_lock_updater_error(error, pnpm_lock) raise Dependabot::GitDependenciesNotReachable, url end - [FORBIDDEN_PACKAGE, MISSING_PACKAGE, UNAUTHORIZED_PACKAGE].each do |regexp| + [FORBIDDEN_PACKAGE, MISSING_PACKAGE, UNAUTHORIZED_PACKAGE, ERR_PNPM_FETCH_401, + ERR_PNPM_FETCH_403, ERR_PNPM_FETCH_500, ERR_PNPM_FETCH_502].each do |regexp| next unless error_message.match?(regexp) dependency_url = error_message.match(regexp).named_captures["dependency_url"] - - raise_package_access_error(dependency_url, pnpm_lock) + raise_package_access_error(error_message, dependency_url, pnpm_lock) end raise @@ -125,7 +131,7 @@ def raise_resolvability_error(error_message, pnpm_lock) raise Dependabot::DependencyFileNotResolvable, msg end - def raise_package_access_error(dependency_url, pnpm_lock) + def raise_package_access_error(error_message, dependency_url, pnpm_lock) package_name = RegistryParser.new(resolved_url: dependency_url, credentials: credentials).dependency_name missing_dep = lockfile_dependencies(pnpm_lock) .find { |dep| dep.name == package_name } @@ -136,7 +142,7 @@ def raise_package_access_error(dependency_url, pnpm_lock) credentials: credentials, npmrc_file: npmrc_file ).registry - + Dependabot.logger.warn("Error while accessing #{reg}. Response (truncated) - #{error_message[0..500]}...") raise PrivateSourceAuthenticationFailure, reg end diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb index 21d869b5c7..3bc4f835d0 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb @@ -633,7 +633,7 @@ def handle_yarn_error(error, params) ).void end def handle_group_patterns(error, usage_error_message, params) # rubocop:disable Metrics/PerceivedComplexity - error_message = error.message + error_message = error.message.gsub(/\e\[\d+(;\d+)*m/, "") VALIDATION_GROUP_PATTERNS.each do |group| patterns = group[:patterns] matchfn = group[:matchfn] @@ -645,8 +645,8 @@ def handle_group_patterns(error, usage_error_message, params) # rubocop:disable message = usage_error_message.empty? ? error_message : usage_error_message if in_usage && pattern_in_message(patterns, usage_error_message) raise create_error(handler, message, error, params) - elsif !in_usage && pattern_in_message(patterns, error.message) - raise create_error(handler, error.message, error, params) + elsif !in_usage && pattern_in_message(patterns, error_message) + raise create_error(handler, error_message, error, params) end raise create_error(handler, message, error, params) if matchfn&.call(usage_error_message, error_message) diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater_spec.rb index 6c4fb015be..521e1e0e50 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater_spec.rb @@ -131,6 +131,15 @@ end end + context "when there is a private repo we don't have access to and returns a 4xx error" do + let(:project_name) { "pnpm/private_repo_no_access" } + + it "raises a helpful error" do + expect { updated_pnpm_lock_content } + .to raise_error(Dependabot::PrivateSourceAuthenticationFailure) + end + end + context "with a private git dep we don't have access to" do let(:dependency_name) { "cross-fetch" } let(:version) { "4.0.0" } @@ -167,6 +176,15 @@ end end + context "when there is a private repo returns a 5xx error" do + let(:project_name) { "pnpm/private_repo_with_server_error" } + + it "raises a helpful error" do + expect { updated_pnpm_lock_content } + .to raise_error(Dependabot::PrivateSourceAuthenticationFailure) + end + end + context "with a private git dep we don't have access to in PNPM v8" do let(:dependency_name) { "cross-fetch" } let(:version) { "4.0.0" } diff --git a/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_error_handler_spec.rb b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_error_handler_spec.rb index 6a5df08d0d..fde58a3845 100644 --- a/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_error_handler_spec.rb +++ b/npm_and_yarn/spec/dependabot/npm_and_yarn/yarn_error_handler_spec.rb @@ -113,12 +113,13 @@ context "when the error message contains a node version not satisfy regex and versions are extracted" do let(:error_message) do - "➤ YN0000: ┌ Project validation\n" \ + "\e[94m➤\e[39m YN0000: · Yarn 4.0.2\n\e[94m➤\e[39m \e[90mYN0000\e[39m: ┌ Project validation\n" \ "::group::Project validation\n" \ - "➤ YN0000: │ The current Node version v20.15.1 does not satisfy the required version 14.21.3.\n" \ - "::endgroup::\n" \ - "➤ YN0000: └ Completed\n" \ - "➤ YN0000: Failed with errors in 0s 6ms" + "\e[91m➤\e[39m YN0000: │ \e[31mThe current \e[32mNode\e[39m\e[31m version \e[36m20.13.1\e[39m\e[31m does" \ + " not satisfy the required version \e[36m20.11.0\e[39m\e[31m.\e[39m\n::endgroup::\n\e[91m➤\e[39m YN0000:" \ + " \e[31mThe current \e[32mNode\e[39m\e[31m version \e[36m20.13.1\e[39m\e[31m does not satisfy the required " \ + "version \e[36m20.11.0\e[39m\e[31m.\e[39m\n" \ + "\e[94m➤\e[39m \e[90mYN0000\e[39m: └ Completed\n\e[91m➤\e[39m YN0000: · Failed with errors in 0s 3ms" end it "raises a ToolVersionNotSupported error with the correct versions" do @@ -126,8 +127,8 @@ error_handler.handle_error(error, { yarn_lock: yarn_lock }) end.to raise_error(Dependabot::ToolVersionNotSupported) do |e| # rubocop:disable Style/MultilineBlockChain expect(e.tool_name).to eq("Yarn") - expect(e.detected_version).to eq("v20.15.1") - expect(e.supported_versions).to eq("14.21.3") + expect(e.detected_version).to eq("20.13.1") + expect(e.supported_versions).to eq("20.11.0") end end end diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/.npmrc b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/.npmrc new file mode 100644 index 0000000000..66848d2f31 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/.npmrc @@ -0,0 +1,2 @@ +@dsp-testing:registry=https://npm.pkg.github.com +//npm.pkg.github.com/:_authToken=${NPM_TOKEN} \ No newline at end of file diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/package.json b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/package.json new file mode 100644 index 0000000000..7a8e3ffc03 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@dsp-testing/node": "1.0.3" + } +} diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/pnpm-lock.yaml b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/pnpm-lock.yaml new file mode 100644 index 0000000000..bdbdd096f7 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_no_access/pnpm-lock.yaml @@ -0,0 +1,16 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@dsp-testing/node-sass': + specifier: 1.0.3 + version: 1.0.3 + +packages: + + /@dsp-testing/node-sass@1.0.3: + resolution: {integrity: sha512-5Kt5AHgt2qE9YFlRnqizh36k1lcuTdGQP3UsxJgxVUo1Uxh4Z7vDgr7wDBm2hp4PjZ6soE4zupSyfaCbYguQqg==, tarball: https://npm.pkg.github.com/download/@dsp-testing/inner-source-top-secret-npm-2/1.0.3/0a19a66110450848d0a88b1be211cadae740a86f0c1c1658ed89c9f391b8f605} + dev: false diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/.npmrc b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/.npmrc new file mode 100644 index 0000000000..df53680151 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/.npmrc @@ -0,0 +1 @@ +@dsp-testing:registry=https://npm.pkg.github.com diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/package.json b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/package.json new file mode 100644 index 0000000000..617c9e0810 --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "@dsp-testing/is-positive": "3.1.0" + } +} diff --git a/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/pnpm-lock.yaml b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/pnpm-lock.yaml new file mode 100644 index 0000000000..85b377bf6e --- /dev/null +++ b/npm_and_yarn/spec/fixtures/projects/pnpm/private_repo_with_server_error/pnpm-lock.yaml @@ -0,0 +1,26 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@dsp-testing/node-sass': + specifier: 1.0.3 + version: 1.0.3 + +packages: + + /@dsp-testing/node-sass@2.0.3: + resolution: {integrity: sha512-5Kt5AHgt2qE9YFlRnqizh36k1lcuTdGQP3UsxJgxVUo1Uxh4Z7vDgr7wDBm2hp4PjZ6soE4zupSyfaCbYguQqg==, tarball: https://npm.pkg.github.com/download/@dsp-testing/inner-source-top-secret-npm-2/1.0.3/0a19a66110450848d0a88b1be211cadae740a86f0c1c1658ed89c9f391b8f605} + dev: false + + /is-positive@3.1.0: + resolution: {integrity: sha512-8ND1j3y9/HP94TOvGzr69/FgbkX2ruOldhLEsTWwcJVfo4oRjwemJmJxt7RJkKYH8tz7vYBP9JcKQY8CLuJ90Q==} + engines: {node: '>=0.10.0'} + dev: false + + /left-pad@1.0.1: + resolution: {integrity: sha512-Q6Zx9Ntd6ORhdi3F0jYodrEU+Nrp/mRAOSnj6oHy+WEF67GiIIs/TjsQhY6+L67VVSwzl+qhqwHj7JfRrXV8dw==} + deprecated: use String.prototype.padStart() + dev: false