diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn.rb index c6ffd049146..3e36c2501e9 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn.rb @@ -130,12 +130,13 @@ module NpmAndYarn YARN_PACKAGE_NOT_FOUND = /MessageError: Couldn't find any versions for "(?.*?)" that matches "(?.*?)"/ YN0001_FILE_NOT_RESOLVED_CODES = T.let({ - FIND_PACKAGE_LOCATION: /YN0001: UsageError: Couldn't find the (?.*) state file/, - NO_CANDIDATE_FOUND: /YN0001: Error: (?.*): No candidates found/, - NO_SUPPORTED_RESOLVER: /YN0001:*.*Error: (?.*) isn't supported by any available resolver/, - WORKSPACE_NOT_FOUND: /YN0001: Error: (?.*): Workspace not found/, - ENOENT: /YN0001:*.*Thrown Error: (?.*) ENOENT/, - MANIFEST_NOT_FOUND: /YN0001: Error: (?.*): Manifest not found/ + FIND_PACKAGE_LOCATION: /YN0001:(.*?)UsageError: Couldn't find the (?.*) state file/, + NO_CANDIDATE_FOUND: /YN0001:(.*?)Error: (?.*): No candidates found/, + NO_SUPPORTED_RESOLVER: /YN0001:(.*?)Error: (?.*) isn't supported by any available resolver/, + WORKSPACE_NOT_FOUND: /YN0001:(.*?)Error: (?.*): Workspace not found/, + ENOENT: /YN0001:(.*?)Thrown Error: (?.*) ENOENT/, + MANIFEST_NOT_FOUND: /YN0001:(.*?)Error: (?.*): Manifest not found/, + LIBZIP_ERROR: /YN0001:(.*?)Libzip Error: Failed to open the cache entry for (?.*): Not a zip archive/ }.freeze, T::Hash[String, Regexp]) YN0001_AUTH_ERROR_CODES = T.let({ @@ -203,6 +204,12 @@ def self.sanitize_resolvability_message(error_message, dependencies, yarn_lock) Dependabot::DependencyFileNotResolvable.new(message) } }, + "YN0009" => { + message: "Build Failed", + handler: lambda { |message, _error, _params| + Dependabot::DependencyFileNotResolvable.new(message) + } + }, "YN0016" => { message: "Remote not found", handler: lambda { |message, _error, _params| @@ -228,6 +235,13 @@ def self.sanitize_resolvability_message(error_message, dependencies, yarn_lock) Dependabot::DependencyNotFound.new(message) } }, + "YN0041" => { + message: "Invalid authentication", + handler: lambda { |message, _error, _params| + url = T.must(URI.decode_www_form_component(message).split("https://").last).split("/").first + Dependabot::PrivateSourceAuthenticationFailure.new(url) + } + }, "YN0046" => { message: "Automerge failed to parse", handler: lambda { |message, _error, _params| @@ -252,6 +266,12 @@ def self.sanitize_resolvability_message(error_message, dependencies, yarn_lock) Dependabot::IncompatibleCPU.new(message) } }, + "YN0068" => { + message: "No matching package", + handler: lambda { |message, _error, _params| + Dependabot::DependencyFileNotResolvable.new(message) + } + }, "YN0071" => { message: "NM can't install external soft link", handler: lambda { |message, _error, _params| 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 24d994f2b7d..3a7ddf64866 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 @@ -180,7 +180,80 @@ expect do error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) end.to raise_error(Dependabot::DependencyFileNotResolvable, - "YN0001: Error: @mui/material@npm:>5.16.7: No candidates found") + "YN0001: │ Error: @mui/material@npm:>5.16.7: No candidates found") + end + end + + context "when the error message contains YN0001 response (Libzip Error)" do + let(:error_message) do + "➤ YN0001: │ Libzip Error: Failed to open the cache entry for @swc/core-darwin-arm64@npm:1.4.13:" \ + " Not a zip archive + at Wr.makeLibzipError (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:314:12847) + at new Wr (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:314:12288) + at T (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:429:3109) + at /home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:429:3173 + at Jx (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:390:11143) + at Sg.factory (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:429:3164) + at get baseFs [as baseFs] (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:314:41188) + at Sg.readFilePromise (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:314:38610) + at bo.readFilePromise (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:314:38617) + at VA.loadFile (/home/dependabot/.cache/node/corepack/yarn/3.6.0/yarn.js:390:32591) + ::endgroup::" + end + + it "raises a DependencyFileNotResolvable error with the correct message" do + expect do + error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) + end.to raise_error(Dependabot::DependencyFileNotResolvable, + "YN0001: │ Libzip Error: Failed to open the cache entry " \ + "for @swc/core-darwin-arm64@npm:1.4.13: Not a zip archive") + end + end + + context "when the error message contains YN0041 response (Invalid authentication)" do + let(:error_message) do + "[91m➤ YN0041: │ @cadence-group/conventional-changelog-angular-" \ + "jira@npm:0.0.7::__archiveUrl=https%3A%2F%2Fnpm.pkg.github.com%2" \ + "Fdownload%2F%40cadence-group%2Fconventional-changelog-angular-jira%2F0.0.7%2F04c2959b652882c4c017132" \ + "f65dbaa42b6e532a4: Invalid authentication (as an unknown user) + ::endgroup::" + end + + it "raises a PrivateSourceAuthenticationFailure error with the correct message" do + expect do + error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) + end.to raise_error(Dependabot::PrivateSourceAuthenticationFailure, + "The following source could not be reached as it requires " \ + "authentication (and any provided details were invalid or lacked the " \ + "required permissions): npm.pkg.github.com") + end + end + + context "when the error message contains YN0009 response (Build failed)" do + let(:error_message) do + "YN0009: │ @pact-foundation/pact@npm:10.0.0-beta.36 couldn't be built successfully" \ + " (exit code 127, logs can be found here: /tmp/xfs-c9e5e92d/build.log) + ➤ YN0000: └ Completed in 13s 325ms" + end + + it "raises a DependencyFileNotResolvable error with the correct message" do + expect do + error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) + end.to raise_error(Dependabot::DependencyFileNotResolvable) + end + end + + context "when the error message contains YN0068 response (No matching package)" do + let(:error_message) do + "YN0068: │ @cfaester/enzyme-adapter-react-18" \ + " ➤ dependencies ➤ function.prototype.name: " \ + "No matching package in the dependency tree;" + end + + it "raises a DependencyFileNotResolvable error with the correct message" do + expect do + error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) + end.to raise_error(Dependabot::DependencyFileNotResolvable) end end