Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve maintainability of labeler class using polymorphism #3311

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion common/lib/dependabot/pull_request_creator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class PullRequestCreator
require "dependabot/pull_request_creator/message_builder"
require "dependabot/pull_request_creator/branch_namer"
require "dependabot/pull_request_creator/labeler"
require "dependabot/pull_request_creator/labelers/factory"

class RepoNotFound < StandardError; end

Expand Down Expand Up @@ -225,7 +226,7 @@ def branch_namer

def labeler
@labeler ||=
Labeler.new(
Dependabot::PullRequestCreator::Labelers::Factory.for_source(
source: source,
custom_labels: custom_labels,
credentials: credentials,
Expand Down
198 changes: 18 additions & 180 deletions common/lib/dependabot/pull_request_creator/labeler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

require "octokit"
require "dependabot/pull_request_creator"

module Dependabot
class PullRequestCreator
class Labeler
Expand All @@ -26,12 +27,11 @@ def register_label_details(package_manager, label_details)
end
end

def initialize(source:, custom_labels:, credentials:, dependencies:,
def initialize(source:, custom_labels:, dependencies:,
includes_security_fixes:, label_language:,
automerge_candidate:)
@source = source
@custom_labels = custom_labels
@credentials = credentials
@dependencies = dependencies
@includes_security_fixes = includes_security_fixes
@label_language = label_language
Expand All @@ -53,29 +53,13 @@ def labels_for_pr
].compact.uniq
end

def label_pull_request(pull_request_number)
create_default_labels_if_required

return if labels_for_pr.none?
raise "Only GitHub!" unless source.provider == "github"

github_client_for_source.add_labels_to_an_issue(
source.repo,
pull_request_number,
labels_for_pr
)
rescue Octokit::UnprocessableEntity, Octokit::NotFound
retry_count ||= 0
retry_count += 1
raise if retry_count > 10

sleep(rand(1..1.99))
retry
def label_pull_request(_pull_request_number)
raise "Only GitHub!"
end

private

attr_reader :source, :custom_labels, :credentials, :dependencies
attr_reader :source, :custom_labels, :dependencies

def label_language?
@label_language
Expand Down Expand Up @@ -226,183 +210,37 @@ def language_label_exists?
end

def language_label
label_name =
self.class.label_details_for_package_manager(package_manager).
fetch(:name)
labels.find { |l| l.casecmp(label_name).zero? }
labels.find { |l| l.casecmp(language_name).zero? }
end

def labels
@labels ||=
case source.provider
when "github" then fetch_github_labels
when "gitlab" then fetch_gitlab_labels
when "azure" then fetch_azure_labels
else raise "Unsupported provider #{source.provider}"
end
end

def fetch_github_labels
client = github_client_for_source

labels =
client.
labels(source.repo, per_page: 100).
map(&:name)

next_link = client.last_response.rels[:next]

while next_link
next_page = next_link.get
labels += next_page.data.map(&:name)
next_link = next_page.rels[:next]
end

labels
end

def fetch_gitlab_labels
gitlab_client_for_source.
labels(source.repo, per_page: 100).
auto_paginate.
map(&:name)
end

def fetch_azure_labels
langauge_name =
self.class.label_details_for_package_manager(package_manager).
fetch(:name)

@labels = [
*@labels,
DEFAULT_DEPENDENCIES_LABEL,
DEFAULT_SECURITY_LABEL,
langauge_name
].uniq
raise "Unsupported provider #{source.provider}"
end

def create_dependencies_label
case source.provider
when "github" then create_github_dependencies_label
when "gitlab" then create_gitlab_dependencies_label
when "azure" then @labels # Azure does not have centralised labels
else raise "Unsupported provider #{source.provider}"
end
raise "Unsupported provider #{source.provider}"
end

def create_security_label
case source.provider
when "github" then create_github_security_label
when "gitlab" then create_gitlab_security_label
when "azure" then @labels # Azure does not have centralised labels
else raise "Unsupported provider #{source.provider}"
end
raise "Unsupported provider #{source.provider}"
end

def create_language_label
case source.provider
when "github" then create_github_language_label
when "gitlab" then create_gitlab_language_label
when "azure" then @labels # Azure does not have centralised labels
else raise "Unsupported provider #{source.provider}"
end
end

def create_github_dependencies_label
github_client_for_source.add_label(
source.repo, DEFAULT_DEPENDENCIES_LABEL, "0366d6",
description: "Pull requests that update a dependency file",
accept: "application/vnd.github.symmetra-preview+json"
)
@labels = [*@labels, DEFAULT_DEPENDENCIES_LABEL].uniq
rescue Octokit::UnprocessableEntity => e
raise unless e.errors.first.fetch(:code) == "already_exists"

@labels = [*@labels, DEFAULT_DEPENDENCIES_LABEL].uniq
end

def create_gitlab_dependencies_label
gitlab_client_for_source.create_label(
source.repo, DEFAULT_DEPENDENCIES_LABEL, "#0366d6",
description: "Pull requests that update a dependency file"
)
@labels = [*@labels, DEFAULT_DEPENDENCIES_LABEL].uniq
end

def create_github_security_label
github_client_for_source.add_label(
source.repo, DEFAULT_SECURITY_LABEL, "ee0701",
description: "Pull requests that address a security vulnerability",
accept: "application/vnd.github.symmetra-preview+json"
)
@labels = [*@labels, DEFAULT_SECURITY_LABEL].uniq
rescue Octokit::UnprocessableEntity => e
raise unless e.errors.first.fetch(:code) == "already_exists"

@labels = [*@labels, DEFAULT_SECURITY_LABEL].uniq
end

def create_gitlab_security_label
gitlab_client_for_source.create_label(
source.repo, DEFAULT_SECURITY_LABEL, "#ee0701",
description: "Pull requests that address a security vulnerability"
)
@labels = [*@labels, DEFAULT_SECURITY_LABEL].uniq
end

def create_github_language_label
langauge_name =
self.class.label_details_for_package_manager(package_manager).
fetch(:name)
github_client_for_source.add_label(
source.repo,
langauge_name,
self.class.label_details_for_package_manager(package_manager).
fetch(:colour),
description: "Pull requests that update #{langauge_name.capitalize} "\
"code",
accept: "application/vnd.github.symmetra-preview+json"
)
@labels = [*@labels, langauge_name].uniq
rescue Octokit::UnprocessableEntity => e
raise unless e.errors.first.fetch(:code) == "already_exists"

@labels = [*@labels, langauge_name].uniq
end

def create_gitlab_language_label
langauge_name =
self.class.label_details_for_package_manager(package_manager).
fetch(:name)
gitlab_client_for_source.create_label(
source.repo,
langauge_name,
"#" + self.class.label_details_for_package_manager(package_manager).
fetch(:colour)
)
@labels = [*@labels, langauge_name].uniq
end

def github_client_for_source
@github_client_for_source ||=
Dependabot::Clients::GithubWithRetries.for_source(
source: source,
credentials: credentials
)
end

def gitlab_client_for_source
@gitlab_client_for_source ||=
Dependabot::Clients::GitlabWithRetries.for_source(
source: source,
credentials: credentials
)
raise "Unsupported provider #{source.provider}"
end

def package_manager
@package_manager ||= dependencies.first.package_manager
end

def language_name
@language_name ||= self.class.label_details_for_package_manager(package_manager).fetch(:name)
end

def colour
@colour ||= self.class.label_details_for_package_manager(package_manager).fetch(:colour)
end

def version_class
Utils.version_class_for_package_manager(package_manager)
end
Expand Down
34 changes: 34 additions & 0 deletions common/lib/dependabot/pull_request_creator/labelers/azure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

require "dependabot/pull_request_creator/labeler"

module Dependabot
class PullRequestCreator
module Labelers
class Azure < Labeler
@package_manager_labels = {}

# Azure does not have centralised labels
def labels
@labels ||= [
DEFAULT_DEPENDENCIES_LABEL,
DEFAULT_SECURITY_LABEL,
language_name
]
end

def create_dependencies_label
labels
end

def create_security_label
labels
end

def create_language_label
labels
end
end
end
end
end
77 changes: 77 additions & 0 deletions common/lib/dependabot/pull_request_creator/labelers/factory.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

module Dependabot
class PullRequestCreator
module Labelers
class Factory
class << self
def for_source(source:, custom_labels:, credentials:, includes_security_fixes:, dependencies:,
label_language:, automerge_candidate:)
labeler_params = {
custom_labels: custom_labels,
includes_security_fixes: includes_security_fixes,
dependencies: dependencies,
label_language: label_language,
automerge_candidate: automerge_candidate
}

case source.provider
when "github" then github_labeler(source, credentials, labeler_params)
when "gitlab" then gitlab_labeler(source, credentials, labeler_params)
when "azure" then azure_labeler(source, labeler_params)
when "bitbucket" then base_labeler(source, labeler_params)
when "codecommit" then base_labeler(source, labeler_params)
else raise "Unsupported provider '#{source.provider}'."
end
end

private

def github_labeler(source, credentials, labeler_params)
require "dependabot/pull_request_creator/labelers/github"
require "dependabot/clients/github_with_retries"
client = Dependabot::Clients::GithubWithRetries.for_source(
source: source,
credentials: credentials
)
Dependabot::PullRequestCreator::Labelers::Github.new(
source: source,
client: client,
**labeler_params
)
end

def gitlab_labeler(source, credentials, labeler_params)
require "dependabot/pull_request_creator/labelers/gitlab"
require "dependabot/clients/gitlab_with_retries"
client = Dependabot::Clients::GitlabWithRetries.for_source(
source: source,
credentials: credentials
)
Dependabot::PullRequestCreator::Labelers::Gitlab.new(
source: source,
client: client,
**labeler_params
)
end

def azure_labeler(source, labeler_params)
require "dependabot/pull_request_creator/labelers/azure"
Dependabot::PullRequestCreator::Labelers::Azure.new(
source: source,
**labeler_params
)
end

def base_labeler(source, labeler_params)
require "dependabot/pull_request_creator/labeler"
Dependabot::PullRequestCreator.Labeler.new(
source: source,
**labeler_params
)
end
end
end
end
end
end
Loading