From 477363e860f0a6773a6221177857a55ee18d3044 Mon Sep 17 00:00:00 2001 From: "S.Sandhu" <167903774+sachin-sandhu@users.noreply.github.com> Date: Wed, 12 Feb 2025 11:48:52 -0500 Subject: [PATCH 1/3] Handlers for yarn errors (#11562) --- npm_and_yarn/lib/dependabot/npm_and_yarn.rb | 11 ++++++++++ .../npm_and_yarn/yarn_error_handler_spec.rb | 22 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/npm_and_yarn/lib/dependabot/npm_and_yarn.rb b/npm_and_yarn/lib/dependabot/npm_and_yarn.rb index 0702144c88..c982f1053b 100644 --- a/npm_and_yarn/lib/dependabot/npm_and_yarn.rb +++ b/npm_and_yarn/lib/dependabot/npm_and_yarn.rb @@ -169,6 +169,10 @@ module NpmAndYarn REQUIREMENT_NOT_PROVIDED: /(?.*)(.*?)doesn't provide (?.*)(.*?), requested by (?.*)/ }.freeze, T::Hash[String, Regexp]) + YN0001_INVALID_TYPE_ERRORS = T.let({ + INVALID_URL: /TypeError: (?.*): Invalid URL/ + }.freeze, T::Hash[String, Regexp]) + YN0086_DEPS_RESOLUTION_FAILED = /peer dependencies are incorrectly met/ # registry returns malformed response @@ -239,6 +243,13 @@ def self.sanitize_resolvability_message(error_message, dependencies, yarn_lock) end end + YN0001_INVALID_TYPE_ERRORS.each do |(_yn0001_key, yn0001_regex)| + if (msg = message.match(yn0001_regex)) + + return Dependabot::DependencyFileNotResolvable.new(msg) + end + end + Dependabot::DependabotError.new(message) } }, 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 93c3b25026..400f386dac 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 @@ -616,6 +616,28 @@ end end + context "when error message doesn't match any YN0001.* regex patterns" do + let(:error_message) do + "[YN0001]: Exception error, Detail: ➤ YN0000: · Yarn 4.0.2" \ + "➤ YN0000: ┌ Resolution step" \ + "::group::Resolution step" \ + "➤ YN0001: │ TypeError: @moonpig/common-logging-sqs-lambda@npm:1.1.2: Invalid URL" \ + "at new URL (node:internal/url:806:29)" \ + "at Q1t (/home/dependabot/dependabot-updater/repo/.yarn/releases/yarn-4.0.2.cjs:676:20388)" \ + "at /home/dependabot/dependabot-updater/repo/.yarn/releases/yarn-4.0.2.cjs:676:18667" \ + "at Object.ol (/home/dependabot/dependabot-updater/repo/.yarn/releases/yarn-4.0.2.cjs:140:53564)" \ + "at KC (/home/dependabot/dependabot-updater/repo/.yarn/releases/yarn-4.0.2.cjs:676:18561)" + end + + it "raises error with the raw message" do + expect do + error_handler.handle_yarn_error(error, { yarn_lock: yarn_lock }) + end.to raise_error( + Dependabot::DependencyFileNotResolvable + ) + end + end + context "when out of diskspace error" do let(:error_message) do "fatal: sha1 file '/home/dependabot/dependabot-updater/repo/.git/index.lock' write error. Out of diskspace" From b654ec4d65a0d8d90088508f290b2015b4a6e4f4 Mon Sep 17 00:00:00 2001 From: "S.Sandhu" <167903774+sachin-sandhu@users.noreply.github.com> Date: Wed, 12 Feb 2025 12:12:41 -0500 Subject: [PATCH 2/3] Error handlers for terraform exceptions (#11565) --- .../lib/dependabot/terraform/file_updater.rb | 19 +++++++++++++++++++ .../dependabot/terraform/file_updater_spec.rb | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/terraform/lib/dependabot/terraform/file_updater.rb b/terraform/lib/dependabot/terraform/file_updater.rb index 3af6d720b9..35e35e6247 100644 --- a/terraform/lib/dependabot/terraform/file_updater.rb +++ b/terraform/lib/dependabot/terraform/file_updater.rb @@ -294,6 +294,9 @@ def update_lockfile_declaration(updated_manifest_files) # rubocop:disable Metric content.sub!(declaration_regex, updated_dependency) end rescue SharedHelpers::HelperSubprocessFailed => e + error_handler = FileUpdaterErrorHandler.new + error_handler.handle_helper_subprocess_failed_error(e) + if @retrying_lock && e.message.match?(MODULE_NOT_INSTALLED_ERROR) mod = T.must(e.message.match(MODULE_NOT_INSTALLED_ERROR)).named_captures.fetch("mod") raise Dependabot::DependencyFileNotResolvable, "Attempt to install module #{mod} failed" @@ -425,6 +428,22 @@ def lockfile_declaration_regex(provider_source) /mix end end + + class FileUpdaterErrorHandler + extend T::Sig + + RESOLVE_ERROR = /Could not retrieve providers for locking/ + CONSTRAINTS_ERROR = /no available releases match/ + + # Handles errors with specific to yarn error codes + sig { params(error: SharedHelpers::HelperSubprocessFailed).void } + def handle_helper_subprocess_failed_error(error) + return unless error.message.match?(RESOLVE_ERROR) && error.message.match?(CONSTRAINTS_ERROR) + + raise Dependabot::DependencyFileNotResolvable, "Error while updating lockfile, " \ + "no matching constraints found." + end + end end end diff --git a/terraform/spec/dependabot/terraform/file_updater_spec.rb b/terraform/spec/dependabot/terraform/file_updater_spec.rb index 83e1ef8f9f..c3e603cc48 100644 --- a/terraform/spec/dependabot/terraform/file_updater_spec.rb +++ b/terraform/spec/dependabot/terraform/file_updater_spec.rb @@ -1709,5 +1709,23 @@ module "caf" { specify { expect(updated_dependency_files).to all(be_a(Dependabot::DependencyFile)) } specify { expect(updated_dependency_files.length).to eq(1) } end + + describe "#error_handler" do + subject(:error_handler) { Dependabot::Terraform::FileUpdaterErrorHandler.new } + + let(:error) { instance_double(Dependabot::SharedHelpers::HelperSubprocessFailed, message: error_message) } + + context "when the error message contains no resolvable releases" do + let(:error_message) do + "Could not retrieve providers for locking, no available releases match" + end + + it "raises a DependencyFileNotResolvable error with the correct message" do + expect do + error_handler.handle_helper_subprocess_failed_error(error) + end.to raise_error(Dependabot::DependencyFileNotResolvable) + end + end + end end end From 6481a9537798c966c13f53b660c567bb52b7af7d Mon Sep 17 00:00:00 2001 From: Alfred Mazimbe Date: Wed, 12 Feb 2025 18:06:17 +0000 Subject: [PATCH 3/3] Return nil when fetching latest tag results in a JSON::ParserError (#11552) Co-authored-by: AbdulFattaah Popoola --- .../lib/dependabot/docker/update_checker.rb | 4 ++++ .../dependabot/docker/update_checker_spec.rb | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docker/lib/dependabot/docker/update_checker.rb b/docker/lib/dependabot/docker/update_checker.rb index adb021aadb..9118f8190a 100644 --- a/docker/lib/dependabot/docker/update_checker.rb +++ b/docker/lib/dependabot/docker/update_checker.rb @@ -294,6 +294,10 @@ def fetch_digest_of(tag) rescue RestClient::ServerBrokeConnection, RestClient::TooManyRequests raise PrivateSourceBadResponse, registry_hostname + rescue JSON::ParserError + Dependabot.logger.info \ + "docker_registry_client.manifest_digest(#{docker_repo_name}, #{tag}) returned an empty string" + nil end sig { returns(T::Array[T.class_of(StandardError)]) } diff --git a/docker/spec/dependabot/docker/update_checker_spec.rb b/docker/spec/dependabot/docker/update_checker_spec.rb index 257903311d..ab420b125b 100644 --- a/docker/spec/dependabot/docker/update_checker_spec.rb +++ b/docker/spec/dependabot/docker/update_checker_spec.rb @@ -426,6 +426,28 @@ def stub_tag_with_no_digest(tag) it { is_expected.to eq("17.04") } end + context "when fetching the latest tag results in a JSON parser error" do + let(:tags_fixture_name) { "ubuntu.json" } + let(:version) { "12.10" } + + let(:headers_response) do + fixture("docker", "registry_manifest_headers", "generic.json") + end + + before do + stub_request(:head, repo_url + "manifests/17.10") + .and_return( + status: 200, + body: "", + headers: JSON.parse(headers_response) + ) + + stub_request(:head, repo_url + "manifests/latest").to_raise(JSON::ParserError) + end + + it { is_expected.to eq("17.10") } + end + context "when the dependency's version has a prefix" do let(:version) { "artful-20170826" }