diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-05-20 17:34:42 +0300 |
commit | 9f46488805e86b1bc341ea1620b866016c2ce5ed (patch) | |
tree | f9748c7e287041e37d6da49e0a29c9511dc34768 /lib/gitlab/jira_import | |
parent | dfc92d081ea0332d69c8aca2f0e745cb48ae5e6d (diff) |
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'lib/gitlab/jira_import')
-rw-r--r-- | lib/gitlab/jira_import/base_importer.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/jira_import/handle_labels_service.rb | 39 | ||||
-rw-r--r-- | lib/gitlab/jira_import/issue_serializer.rb | 62 | ||||
-rw-r--r-- | lib/gitlab/jira_import/issues_importer.rb | 2 | ||||
-rw-r--r-- | lib/gitlab/jira_import/labels_importer.rb | 26 | ||||
-rw-r--r-- | lib/gitlab/jira_import/metadata_collector.rb | 57 | ||||
-rw-r--r-- | lib/gitlab/jira_import/user_mapper.rb | 53 |
7 files changed, 200 insertions, 44 deletions
diff --git a/lib/gitlab/jira_import/base_importer.rb b/lib/gitlab/jira_import/base_importer.rb index 5381812186d..306736df30f 100644 --- a/lib/gitlab/jira_import/base_importer.rb +++ b/lib/gitlab/jira_import/base_importer.rb @@ -3,12 +3,13 @@ module Gitlab module JiraImport class BaseImporter - attr_reader :project, :client, :formatter, :jira_project_key + attr_reader :project, :client, :formatter, :jira_project_key, :running_import def initialize(project) project.validate_jira_import_settings! - @jira_project_key = project.latest_jira_import&.jira_project_key + @running_import = project.latest_jira_import + @jira_project_key = running_import&.jira_project_key raise Projects::ImportService::Error, _('Unable to find Jira project to import data from.') unless @jira_project_key diff --git a/lib/gitlab/jira_import/handle_labels_service.rb b/lib/gitlab/jira_import/handle_labels_service.rb new file mode 100644 index 00000000000..1b00515cced --- /dev/null +++ b/lib/gitlab/jira_import/handle_labels_service.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + class HandleLabelsService + def initialize(project, jira_labels) + @project = project + @jira_labels = jira_labels + end + + def execute + return if jira_labels.blank? + + existing_labels = LabelsFinder.new(nil, project: project, title: jira_labels) + .execute(skip_authorization: true).select(:id, :name) + new_labels = create_missing_labels(existing_labels) + + label_ids = existing_labels.map(&:id) + label_ids += new_labels if new_labels.present? + label_ids + end + + private + + attr_reader :project, :jira_labels + + def create_missing_labels(existing_labels) + labels_to_create = jira_labels - existing_labels.map(&:name) + return if labels_to_create.empty? + + new_labels_hash = labels_to_create.map do |title| + { project_id: project.id, title: title, type: 'ProjectLabel' } + end + + Label.insert_all(new_labels_hash).rows.flatten + end + end + end +end diff --git a/lib/gitlab/jira_import/issue_serializer.rb b/lib/gitlab/jira_import/issue_serializer.rb index cdcb62ac6e9..df57680073e 100644 --- a/lib/gitlab/jira_import/issue_serializer.rb +++ b/lib/gitlab/jira_import/issue_serializer.rb @@ -3,15 +3,14 @@ module Gitlab module JiraImport class IssueSerializer - attr_reader :jira_issue, :project, :params, :formatter - attr_accessor :metadata + attr_reader :jira_issue, :project, :import_owner_id, :params, :formatter - def initialize(project, jira_issue, params = {}) + def initialize(project, jira_issue, import_owner_id, params = {}) @jira_issue = jira_issue @project = project + @import_owner_id = import_owner_id @params = params @formatter = Gitlab::ImportFormatter.new - @metadata = [] end def execute @@ -23,7 +22,9 @@ module Gitlab state_id: map_status(jira_issue.status.statusCategory), updated_at: jira_issue.updated, created_at: jira_issue.created, - author_id: project.creator_id # TODO: map actual author: https://gitlab.com/gitlab-org/gitlab/-/issues/210580 + author_id: reporter, + assignee_ids: assignees, + label_ids: label_ids } end @@ -35,10 +36,8 @@ module Gitlab def description body = [] - body << formatter.author_line(jira_issue.reporter.displayName) - body << formatter.assignee_line(jira_issue.assignee.displayName) if jira_issue.assignee body << jira_issue.description - body << add_metadata + body << MetadataCollector.new(jira_issue).execute body.join end @@ -52,48 +51,33 @@ module Gitlab end end - def add_metadata - add_field(%w(issuetype name), 'Issue type') - add_field(%w(priority name), 'Priority') - add_labels - add_field('environment', 'Environment') - add_field('duedate', 'Due date') - add_parent - add_versions - - return if metadata.empty? - - metadata.join("\n").prepend("\n\n---\n\n**Issue metadata**\n\n") + def map_user_id(jira_user) + Gitlab::JiraImport::UserMapper.new(project, jira_user).execute&.id end - def add_field(keys, field_label) - value = fields.dig(*keys) - return if value.blank? - - metadata << "- #{field_label}: #{value}" + def reporter + map_user_id(jira_issue.reporter&.attrs) || import_owner_id end - def add_labels - return if fields['labels'].blank? - - metadata << "- Labels: #{fields['labels'].join(', ')}" - end + def assignees + found_user_id = map_user_id(jira_issue.assignee&.attrs) - def add_parent - parent_issue_key = fields.dig('parent', 'key') - return if parent_issue_key.blank? + return unless found_user_id - metadata << "- Parent issue: [#{parent_issue_key}] #{fields['parent']['fields']['summary']}" + [found_user_id] end - def add_versions - return if fields['fixVersions'].blank? + # We already create labels in Gitlab::JiraImport::LabelsImporter stage but + # there is a possibility it may fail or + # new labels were created on the Jira in the meantime + def label_ids + return if jira_issue.fields['labels'].blank? - metadata << "- Fix versions: #{fields['fixVersions'].map { |version| version['name'] }.join(', ')}" + Gitlab::JiraImport::HandleLabelsService.new(project, jira_issue.fields['labels']).execute end - def fields - jira_issue.fields + def logger + @logger ||= Gitlab::Import::Logger.build end end end diff --git a/lib/gitlab/jira_import/issues_importer.rb b/lib/gitlab/jira_import/issues_importer.rb index 6543b633ddf..8c18e58d9df 100644 --- a/lib/gitlab/jira_import/issues_importer.rb +++ b/lib/gitlab/jira_import/issues_importer.rb @@ -57,7 +57,7 @@ module Gitlab # For such cases we exit early if issue was already imported. next if already_imported?(jira_issue.id) - issue_attrs = IssueSerializer.new(project, jira_issue, { iid: next_iid }).execute + issue_attrs = IssueSerializer.new(project, jira_issue, running_import.user_id, { iid: next_iid }).execute Gitlab::JiraImport::ImportIssueWorker.perform_async(project.id, jira_issue.id, issue_attrs, job_waiter.key) job_waiter.jobs_remaining += 1 diff --git a/lib/gitlab/jira_import/labels_importer.rb b/lib/gitlab/jira_import/labels_importer.rb index 35c434e48a4..6e6842e06bf 100644 --- a/lib/gitlab/jira_import/labels_importer.rb +++ b/lib/gitlab/jira_import/labels_importer.rb @@ -5,6 +5,8 @@ module Gitlab class LabelsImporter < BaseImporter attr_reader :job_waiter + MAX_LABELS = 500 + def initialize(project) super @job_waiter = JobWaiter.new @@ -19,15 +21,35 @@ module Gitlab def cache_import_label(project) label = project.jira_imports.by_jira_project_key(jira_project_key).last.label - raise Projects::ImportService::Error, _('Failed to find import label for jira import.') unless label + raise Projects::ImportService::Error, _('Failed to find import label for Jira import.') unless label JiraImport.cache_import_label_id(project.id, label.id) end def import_jira_labels - # todo: import jira labels, see https://gitlab.com/gitlab-org/gitlab/-/issues/212651 + start_at = 0 + loop do + break if process_jira_page(start_at) + + start_at += MAX_LABELS + end + job_waiter end + + def process_jira_page(start_at) + request = "/rest/api/2/label?maxResults=#{MAX_LABELS}&startAt=#{start_at}" + response = client.get(request) + + return true if response['values'].blank? + return true unless response.key?('isLast') + + Gitlab::JiraImport::HandleLabelsService.new(project, response['values']).execute + + response['isLast'] + rescue => e + Gitlab::ErrorTracking.track_exception(e, project_id: project.id, request: request) + end end end end diff --git a/lib/gitlab/jira_import/metadata_collector.rb b/lib/gitlab/jira_import/metadata_collector.rb new file mode 100644 index 00000000000..4551f38ba98 --- /dev/null +++ b/lib/gitlab/jira_import/metadata_collector.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + class MetadataCollector + attr_accessor :jira_issue, :metadata + + def initialize(jira_issue) + @jira_issue = jira_issue + @metadata = [] + end + + def execute + add_field(%w(issuetype name), 'Issue type') + add_field(%w(priority name), 'Priority') + add_field('environment', 'Environment') + add_field('duedate', 'Due date') + add_parent + add_versions + + return if metadata.empty? + + metadata.join("\n").prepend("\n\n---\n\n**Issue metadata**\n\n") + end + + private + + def add_field(keys, field_label) + value = fields.dig(*keys) + return if value.blank? + + metadata << "- #{field_label}: #{value}" + end + + def add_parent + parent_issue_key = fields.dig('parent', 'key') + + return if parent_issue_key.blank? + + parent_summary_key = fields.dig('parent', 'fields', 'summary') + + metadata << "- Parent issue: [#{parent_issue_key}] #{parent_summary_key}".strip + end + + def add_versions + return if fields['fixVersions'].blank? || !fields['fixVersions'].is_a?(Array) + + versions = fields['fixVersions'].map { |version| version['name'] }.compact.join(', ') + metadata << "- Fix versions: #{versions}" + end + + def fields + jira_issue.fields + end + end + end +end diff --git a/lib/gitlab/jira_import/user_mapper.rb b/lib/gitlab/jira_import/user_mapper.rb new file mode 100644 index 00000000000..208ee49b724 --- /dev/null +++ b/lib/gitlab/jira_import/user_mapper.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + class UserMapper + include ::Gitlab::Utils::StrongMemoize + + def initialize(project, jira_user) + @project = project + @jira_user = jira_user + end + + def execute + return unless jira_user + + email = jira_user['emailAddress'] + + # We also include emails that are not yet confirmed + users = User.by_any_email(email).to_a + + user = users.first + + # this event should never happen but we should log it in case we have invalid data + log_user_mapping_message('Multiple users found for an email address', email) if users.count > 1 + + unless project.project_member(user) || project.group&.group_member(user) + log_user_mapping_message('Jira user not found', email) + + return + end + + user + end + + private + + attr_reader :project, :jira_user, :params + + def log_user_mapping_message(message, email) + logger.info( + project_id: project.id, + project_path: project.full_path, + user_email: email, + message: message + ) + end + + def logger + @logger ||= Gitlab::Import::Logger.build + end + end + end +end |