diff --git a/.rubocop.yml b/.rubocop.yml index 3a9503f0..ed7f1565 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -14,7 +14,6 @@ AllCops: - "*/spec/fixtures/**/*" - "vendor/**/*" - "dry-run/**/*" - - "bundler/helpers/v1/patched_bundler" - "bundler/helpers/spec_helpers/*" NewCops: enable TargetRubyVersion: 3.1 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 64ea1d09..e7673987 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -9,7 +9,6 @@ # Offense count: 39 RSpec/AnyInstance: Exclude: - - 'bundler/helpers/v1/spec/shared_contexts.rb' - 'bundler/spec/dependabot/bundler/update_checker_spec.rb' - 'common/spec/dependabot/clients/codecommit_spec.rb' - 'common/spec/dependabot/file_fetchers/base_spec.rb' diff --git a/updater/lib/dependabot/dependency_snapshot.rb b/updater/lib/dependabot/dependency_snapshot.rb index b9c2c853..02b03c4e 100644 --- a/updater/lib/dependabot/dependency_snapshot.rb +++ b/updater/lib/dependabot/dependency_snapshot.rb @@ -241,8 +241,10 @@ def dependency_file_parser reject_external_code: job.reject_external_code?, options: job.experiments ) - # Add 'package_manager' to the depedency_snapshopt to use it in operations' + # Add 'package_manager' to the dependency_snapshot to use it in operations package_manager = parser.package_manager + # Raise an error if the package manager version is unsupported + package_manager&.raise_if_unsupported! @package_manager[@current_directory] = package_manager diff --git a/updater/lib/dependabot/notices_helpers.rb b/updater/lib/dependabot/notices_helpers.rb index b5a646c0..c8f52474 100644 --- a/updater/lib/dependabot/notices_helpers.rb +++ b/updater/lib/dependabot/notices_helpers.rb @@ -60,9 +60,6 @@ def log_notice(notice) sig { params(package_manager: T.nilable(PackageManagerBase)).returns(T.nilable(Dependabot::Notice)) } def create_deprecation_notice(package_manager) - # Feature flag check if deprecation notice should be added to notices. - return unless Dependabot::Experiments.enabled?(:add_deprecation_warn_to_pr_message) - return unless package_manager return unless package_manager.is_a?(PackageManagerBase) diff --git a/updater/lib/dependabot/update_files_command.rb b/updater/lib/dependabot/update_files_command.rb index b3cb91d7..d04b4abc 100644 --- a/updater/lib/dependabot/update_files_command.rb +++ b/updater/lib/dependabot/update_files_command.rb @@ -67,7 +67,7 @@ def base_commit_sha Environment.job_definition["base_commit_sha"] end - # rubocop:disable Metrics/AbcSize, Layout/LineLength + # rubocop:disable Metrics/AbcSize, Layout/LineLength, Metrics/MethodLength def handle_parser_error(error) # This happens if the repo gets removed after a job gets kicked off. # The service will handle the removal without any prompt from the updater, @@ -80,6 +80,16 @@ def handle_parser_error(error) # Check if the error is a known "run halting" state we should handle if (error_type = Updater::ErrorHandler::RUN_HALTING_ERRORS[error.class]) { "error-type": error_type } + elsif error.is_a?(ToolVersionNotSupported) + Dependabot.logger.error(error.message) + { + "error-type": "tool_version_not_supported", + "error-detail": { + "tool-name": error.tool_name, + "detected-version": error.detected_version, + "supported-versions": error.supported_versions + } + } else # If it isn't, then log all the details and let the application error # tracker know about it @@ -118,6 +128,6 @@ def handle_parser_error(error) error_details: error_details[:"error-detail"] ) end - # rubocop:enable Metrics/AbcSize, Layout/LineLength + # rubocop:enable Metrics/AbcSize, Layout/LineLength, Metrics/MethodLength end end diff --git a/updater/lib/dependabot/updater/group_update_creation.rb b/updater/lib/dependabot/updater/group_update_creation.rb index 9494698c..abf23f64 100644 --- a/updater/lib/dependabot/updater/group_update_creation.rb +++ b/updater/lib/dependabot/updater/group_update_creation.rb @@ -241,9 +241,6 @@ def compile_updates_for(dependency, dependency_files, group) # rubocop:disable M return [] end - # Raise an error if the package manager version is unsupported - dependency_snapshot.package_manager&.raise_if_unsupported! - checker.updated_dependencies( requirements_to_unlock: requirements_to_unlock ) diff --git a/updater/lib/dependabot/updater/operations/create_security_update_pull_request.rb b/updater/lib/dependabot/updater/operations/create_security_update_pull_request.rb index d10754aa..156a48f3 100644 --- a/updater/lib/dependabot/updater/operations/create_security_update_pull_request.rb +++ b/updater/lib/dependabot/updater/operations/create_security_update_pull_request.rb @@ -105,7 +105,6 @@ def check_and_create_pr_with_error_handling(dependency) # rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/PerceivedComplexity # rubocop:disable Metrics/MethodLength - # rubocop:disable Metrics/CyclomaticComplexity sig { params(dependency: Dependabot::Dependency).void } def check_and_create_pull_request(dependency) dependency = vulnerable_version(dependency) if dependency.metadata[:all_versions] @@ -146,9 +145,6 @@ def check_and_create_pull_request(dependency) log_requirements_for_update(requirements_to_unlock, checker) return record_security_update_not_possible_error(checker) if requirements_to_unlock == :update_not_possible - # Raise an error if the package manager version is unsupported - dependency_snapshot.package_manager&.raise_if_unsupported! - updated_deps = checker.updated_dependencies( requirements_to_unlock: requirements_to_unlock ) @@ -202,7 +198,6 @@ def check_and_create_pull_request(dependency) # rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/AbcSize # rubocop:enable Metrics/PerceivedComplexity - # rubocop:enable Metrics/CyclomaticComplexity sig { params(dependency: Dependabot::Dependency).returns(Dependabot::Dependency) } def vulnerable_version(dependency) return dependency if dependency.metadata[:all_versions].count == 1 diff --git a/updater/lib/dependabot/updater/operations/refresh_security_update_pull_request.rb b/updater/lib/dependabot/updater/operations/refresh_security_update_pull_request.rb index 6202dc7a..9acbffc8 100644 --- a/updater/lib/dependabot/updater/operations/refresh_security_update_pull_request.rb +++ b/updater/lib/dependabot/updater/operations/refresh_security_update_pull_request.rb @@ -54,9 +54,6 @@ def perform Dependabot.logger.info("Starting update job for #{job.source.repo}") Dependabot.logger.info("Checking and updating security pull requests...") - # Raise an error if the package manager version is unsupported - dependency_snapshot.package_manager&.raise_if_unsupported! - # Retrieve the list of initial notices from dependency snapshot @notices = dependency_snapshot.notices # More notices can be added during the update process @@ -132,7 +129,28 @@ def check_and_update_pull_request(dependencies) # Note: Gradle, Maven and Nuget dependency names can be case-insensitive # and the dependency name in the security advisory often doesn't match # what users have specified in their manifest. - lead_dep_name = job_dependencies.first&.downcase + # Dependabot::Experiments.register(:lead_security_dependency, true) + + if Dependabot::Experiments.enabled?(:lead_security_dependency) + lead_dep_name = security_advisory_dependency + + # telemetry data collection + Dependabot.logger.info( + "Security advisory dependency: #{lead_dep_name}\n" \ + "First dependency in list: #{job_dependencies.first&.downcase}" + ) + + if lead_dep_name != job_dependencies.first&.downcase + Dependabot.logger.info( + "Difference found between security-advisory (#{lead_dep_name}) and " \ + "first-dependency (#{job_dependencies.first&.downcase})" + ) + end + + else + lead_dep_name = job_dependencies.first&.downcase + end + lead_dependency = dependencies.find do |dep| dep.name.downcase == lead_dep_name end @@ -174,7 +192,9 @@ def check_and_update_pull_request(dependencies) # and the dependency name in the security advisory often doesn't match # what users have specified in their manifest. job_dependencies = job_dependencies.map(&:downcase) - if dependency_change.updated_dependencies.map { |x| x.name.downcase } != job_dependencies + changed_dependencies = dependency_change.updated_dependencies.map { |x| x.name.downcase } + + if changed_dependencies.sort_by(&:downcase) != job_dependencies.sort_by(&:downcase) # The dependencies being updated have changed. Close the existing # multi-dependency PR and try creating a new one. close_pull_request(reason: :dependencies_changed) @@ -288,6 +308,11 @@ def close_pull_request(reason:) service.close_pull_request(job_dependencies, reason) end + + sig { returns(String) } + def security_advisory_dependency + T.cast(job.security_advisories.first, T::Hash[String, String])["dependency-name"].to_s + end end end end diff --git a/updater/lib/dependabot/updater/operations/refresh_version_update_pull_request.rb b/updater/lib/dependabot/updater/operations/refresh_version_update_pull_request.rb index 4919c758..aafa2b2e 100644 --- a/updater/lib/dependabot/updater/operations/refresh_version_update_pull_request.rb +++ b/updater/lib/dependabot/updater/operations/refresh_version_update_pull_request.rb @@ -138,9 +138,6 @@ def check_and_update_pull_request(dependencies) return close_pull_request(reason: :update_no_longer_possible) end - # Raise an error if the package manager version is unsupported - dependency_snapshot.package_manager&.raise_if_unsupported! - updated_deps = checker.updated_dependencies( requirements_to_unlock: requirements_to_unlock ) diff --git a/updater/lib/dependabot/updater/operations/update_all_versions.rb b/updater/lib/dependabot/updater/operations/update_all_versions.rb index 40e63264..bdcc9a20 100644 --- a/updater/lib/dependabot/updater/operations/update_all_versions.rb +++ b/updater/lib/dependabot/updater/operations/update_all_versions.rb @@ -172,9 +172,6 @@ def check_and_create_pull_request(dependency) notices: @notices ) - # Raise an error if the package manager version is unsupported - dependency_snapshot.package_manager&.raise_if_unsupported! - if dependency_change.updated_dependency_files.empty? raise "UpdateChecker found viable dependencies to be updated, but FileUpdater failed to update any files" end diff --git a/updater/spec/dependabot/update_files_command_spec.rb b/updater/spec/dependabot/update_files_command_spec.rb index 20a31a06..db17767e 100644 --- a/updater/spec/dependabot/update_files_command_spec.rb +++ b/updater/spec/dependabot/update_files_command_spec.rb @@ -3,6 +3,7 @@ require "spec_helper" require "dependabot/update_files_command" +require "dependabot/bundler" require "tmpdir" RSpec.describe Dependabot::UpdateFilesCommand do @@ -112,6 +113,32 @@ end end + context "when there is an unsupported package manager version" do + let(:error) do + Dependabot::ToolVersionNotSupported.new( + "bundler", # tool name + "1.0.0", # detected version + ">= 2.0.0" # supported versions + ) + end + + it_behaves_like "a fast-failed job" + + it "records the unsupported version error with details" do + expect(service).to receive(:record_update_job_error).with( + error_type: "tool_version_not_supported", + error_details: { + "tool-name": "bundler", + "detected-version": "1.0.0", + "supported-versions": ">= 2.0.0" + } + ) + expect(service).to receive(:mark_job_as_processed) + + perform_job + end + end + context "with an update files error (cloud)" do let(:error) { StandardError.new("hell") } diff --git a/updater/spec/fixtures/bundler/original/Gemfile.lock b/updater/spec/fixtures/bundler/original/Gemfile.lock index 4fd8f37a..1f21c435 100644 --- a/updater/spec/fixtures/bundler/original/Gemfile.lock +++ b/updater/spec/fixtures/bundler/original/Gemfile.lock @@ -13,4 +13,4 @@ DEPENDENCIES dummy-pkg-b (~> 1.1.0) BUNDLED WITH - 1.14.6 + 2.4.13 diff --git a/updater/spec/fixtures/bundler/original/sub_dep.lock b/updater/spec/fixtures/bundler/original/sub_dep.lock index dae47db2..e6d6a5d0 100644 --- a/updater/spec/fixtures/bundler/original/sub_dep.lock +++ b/updater/spec/fixtures/bundler/original/sub_dep.lock @@ -13,4 +13,4 @@ DEPENDENCIES dummy-pkg-b (~> 1.1.0) BUNDLED WITH - 1.14.6 + 2.4.13 \ No newline at end of file diff --git a/updater/spec/fixtures/bundler/updated/Gemfile.lock b/updater/spec/fixtures/bundler/updated/Gemfile.lock index 0e7697ff..6397df8c 100644 --- a/updater/spec/fixtures/bundler/updated/Gemfile.lock +++ b/updater/spec/fixtures/bundler/updated/Gemfile.lock @@ -13,4 +13,4 @@ DEPENDENCIES dummy-pkg-b (~> 1.2.0) BUNDLED WITH - 1.14.6 + 2.4.13 diff --git a/updater/spec/fixtures/bundler_grouped/original/Gemfile.lock b/updater/spec/fixtures/bundler_grouped/original/Gemfile.lock index 48feef35..8dc7b0cd 100644 --- a/updater/spec/fixtures/bundler_grouped/original/Gemfile.lock +++ b/updater/spec/fixtures/bundler_grouped/original/Gemfile.lock @@ -15,4 +15,4 @@ DEPENDENCIES ungrouped-dummy-pkg-c (~> 1.0.0) BUNDLED WITH - 1.14.6 + 2.4.13 diff --git a/updater/spec/support/dummy_pkg_helpers.rb b/updater/spec/support/dummy_pkg_helpers.rb index 2f207f5f..2750b821 100644 --- a/updater/spec/support/dummy_pkg_helpers.rb +++ b/updater/spec/support/dummy_pkg_helpers.rb @@ -89,10 +89,8 @@ def deprecated? sig { override.returns(T::Boolean) } def unsupported? - # Check if the feature flag for Bundler v1 unsupported error is enabled. - return false unless name == "bundler" && Dependabot::Experiments.enabled?(:bundler_v1_unsupported_error) - - version < supported_versions.first + # Check if the version is not supported + supported_versions.all? { |supported| supported > version } end end end