From 7653370eb5c283ee23fc63fb7e6f591e845cde24 Mon Sep 17 00:00:00 2001 From: Barry Gordon Date: Mon, 22 May 2023 15:06:16 +0100 Subject: [PATCH] Extract group pr creation into class --- .../create_group_update_pull_request.rb | 71 +++++++++++++++++++ .../operations/group_update_all_versions.rb | 53 ++++++-------- 2 files changed, 92 insertions(+), 32 deletions(-) create mode 100644 updater/lib/dependabot/updater/operations/create_group_update_pull_request.rb diff --git a/updater/lib/dependabot/updater/operations/create_group_update_pull_request.rb b/updater/lib/dependabot/updater/operations/create_group_update_pull_request.rb new file mode 100644 index 000000000000..e62c19e32908 --- /dev/null +++ b/updater/lib/dependabot/updater/operations/create_group_update_pull_request.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require "dependabot/updater/group_update_creation" + +# This class implements our strategy for creating a single Pull Request which +# updates all outdated Dependencies within a specific project folder that match +# a specificed Dependency Group. +# +# This will always post a new Pull Request to Dependabot API and does not check +# to see if any exists for the group or any of the dependencies involved. +# +module Dependabot + class Updater + module Operations + class CreateGroupUpdatePullRequest + include GroupUpdateCreation + + # We do not invoke this class directly for any jobs, so let's return false in the event this + # check is called. + def self.applies_to?(*) + false + end + + def self.tag_name + :create_version_group_pr + end + + # Since this class is not invoked generically based on the job definition, this class accepts a `group` argument + # which is expected to be a prepopulated DependencyGroup object. + def initialize(service:, job:, dependency_snapshot:, error_handler:, group:) + @service = service + @job = job + @dependency_snapshot = dependency_snapshot + @error_handler = error_handler + @group = group + end + + def perform + Dependabot.logger.info("Starting update group for '#{group.name}'") + + dependency_change = compile_all_dependency_changes_for(group) + + if dependency_change.updated_dependencies.any? + Dependabot.logger.info("Creating a pull request for '#{group.name}'") + begin + service.create_pull_request(dependency_change, dependency_snapshot.base_commit_sha) + rescue StandardError => e + raise if ErrorHandler::RUN_HALTING_ERRORS.keys.any? { |err| e.is_a?(err) } + + # FIXME: This will result in us reporting a the group name as a dependency name + # + # In future we should modify this method to accept both dependency and group + # so the downstream error handling can tag things appropriately. + error_handler.handle_dependabot_error(error: e, dependency: group) + end + else + Dependabot.logger.info("Nothing to update for Dependency Group: '#{group.name}'") + end + end + + private + + attr_reader :job, + :service, + :dependency_snapshot, + :error_handler, + :group + end + end + end +end diff --git a/updater/lib/dependabot/updater/operations/group_update_all_versions.rb b/updater/lib/dependabot/updater/operations/group_update_all_versions.rb index 0b074dd3e679..180e444948f5 100644 --- a/updater/lib/dependabot/updater/operations/group_update_all_versions.rb +++ b/updater/lib/dependabot/updater/operations/group_update_all_versions.rb @@ -1,24 +1,22 @@ # frozen_string_literal: true +require "dependabot/updater/operations/create_group_update_pull_request" require "dependabot/updater/operations/update_all_versions" -require "dependabot/updater/group_update_creation" -# This class implements our strategy for creating Pull Requests for Dependency -# Groups defined for a given folder before handling any un-grouped Dependencies -# via Dependabot::Updater::Operations::UpdateAllVersions. +# This class is responsible for coordinating the creation and upkeep of Pull Requests for +# a given folder's defined DependencyGroups. # -# **Note:** This is currently an experimental feature which is not supported -# in the service or as an integration point. +# - If there is no Pull Request already open for a DependencyGroup, it will be delegated +# to Dependabot::Updater::Operations::CreateGroupUpdatePullRequest. +# - If there is an open Pull Request for a DependencyGroup, it will skip over that group +# as the service is responsible for refreshing it in a separate job. +# - Any ungrouped Dependencies will be handled individually by delegation to +# Dependabot::Updater::Operations::UpdateAllVersions. # -# Some limitations of the current implementation: -# - It has no superseding logic for groups - every time this strategy runs for a -# repo it will create a new Pull Request regardless of any existing, open PR module Dependabot class Updater module Operations class GroupUpdateAllVersions - include GroupUpdateCreation - def self.applies_to?(job:) return false if job.security_updates_only? return false if job.updating_a_pull_request? @@ -28,7 +26,7 @@ def self.applies_to?(job:) end def self.tag_name - :grouped_updates_prototype + :group_update_all_versions end def initialize(service:, job:, dependency_snapshot:, error_handler:) @@ -81,26 +79,7 @@ def run_grouped_dependency_updates # rubocop:disable Metrics/AbcSize next end - Dependabot.logger.info("Starting update group for '#{group.name}'") - - dependency_change = compile_all_dependency_changes_for(group) - - if dependency_change.updated_dependencies.any? - Dependabot.logger.info("Creating a pull request for '#{group.name}'") - begin - service.create_pull_request(dependency_change, dependency_snapshot.base_commit_sha) - rescue StandardError => e - raise if ErrorHandler::RUN_HALTING_ERRORS.keys.any? { |err| e.is_a?(err) } - - # FIXME: This will result in us reporting a the group name as a dependency name - # - # In future we should modify this method to accept both dependency and group - # so the downstream error handling can tag things appropriately. - error_handler.handle_dependabot_error(error: e, dependency: group) - end - else - Dependabot.logger.info("Nothing to update for Dependency Group: '#{group.name}'") - end + run_update_for(group) end end @@ -108,6 +87,16 @@ def pr_exists_for_dependency_group?(group) job.existing_group_pull_requests&.any? { |pr| pr["dependency-group-name"] == group.name } end + def run_update_for(group) + Dependabot::Updater::Operations::CreateGroupUpdatePullRequest.new( + service: service, + job: job, + dependency_snapshot: dependency_snapshot, + error_handler: error_handler, + group: group + ).perform + end + def run_ungrouped_dependency_updates Dependabot::Updater::Operations::UpdateAllVersions.new( service: service,