Commit d3ace711 authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch 'label-jira-imported-issues' into 'master'

Label Jira imported issues with an auto-generated label

See merge request gitlab-org/gitlab!27718
parents f70a0ca3 8abaf9a8
......@@ -159,6 +159,11 @@ class Label < ApplicationRecord
on_project_boards(project_id).where(id: label_id).exists?
end
# Generate a hex color based on hex-encoded value
def self.color_for(value)
"##{Digest::MD5.hexdigest(value)[0..5]}"
end
def open_issues_count(user = nil)
issues_count(user, state: 'opened')
end
......
......@@ -9,8 +9,8 @@ module Gitlab
include Gitlab::Import::DatabaseHelpers
def perform(project_id, jira_issue_id, issue_attributes, waiter_key)
issue_id = insert_and_return_id(issue_attributes, Issue)
cache_issue_mapping(issue_id, jira_issue_id, project_id)
issue_id = create_issue(issue_attributes, project_id)
JiraImport.cache_issue_mapping(issue_id, jira_issue_id, project_id)
rescue => ex
# Todo: Record jira issue id(or better jira issue key),
# so that we can report the list of failed to import issues to the user
......@@ -27,9 +27,31 @@ module Gitlab
private
def cache_issue_mapping(issue_id, jira_issue_id, project_id)
cache_key = JiraImport.jira_issue_cache_key(project_id, jira_issue_id)
Gitlab::Cache::Import::Caching.write(cache_key, issue_id)
def create_issue(issue_attributes, project_id)
issue_id = insert_and_return_id(issue_attributes, Issue)
label_issue(project_id, issue_id)
issue_id
end
def label_issue(project_id, issue_id)
label_id = JiraImport.get_import_label_id(project_id)
return unless label_id
label_link_attrs = build_label_attrs(issue_id, label_id.to_i)
insert_and_return_id(label_link_attrs, LabelLink)
end
def build_label_attrs(issue_id, label_id)
time = Time.now
{
label_id: label_id,
target_id: issue_id,
target_type: 'Issue',
created_at: time,
updated_at: time
}
end
end
end
......
......@@ -9,10 +9,8 @@ module Gitlab
private
def import(project)
# fake labels import workers for now
# new job waiter will have zero jobs_remaining by default, so it will just pass on to next stage
fake_waiter = JobWaiter.new
Gitlab::JiraImport::AdvanceStageWorker.perform_async(project.id, { fake_waiter.key => fake_waiter.jobs_remaining }, :issues)
job_waiter = Gitlab::JiraImport::LabelsImporter.new(project).execute
Gitlab::JiraImport::AdvanceStageWorker.perform_async(project.id, { job_waiter.key => job_waiter.jobs_remaining }, :issues)
end
end
end
......
......@@ -6,6 +6,7 @@ module Gitlab
FAILED_ISSUES_COUNTER_KEY = 'jira-import/failed/%{project_id}/%{collection_type}'
NEXT_ITEMS_START_AT_KEY = 'jira-import/paginator/%{project_id}/%{collection_type}'
JIRA_IMPORT_LABEL = 'jira-import/import-label/%{project_id}'
ITEMS_MAPPER_CACHE_KEY = 'jira-import/items-mapper/%{project_id}/%{collection_type}/%{jira_isssue_id}'
ALREADY_IMPORTED_ITEMS_CACHE_KEY = 'jira-importer/already-imported/%{project}/%{collection_type}'
......@@ -25,23 +26,45 @@ module Gitlab
FAILED_ISSUES_COUNTER_KEY % { project_id: project_id, collection_type: :issues }
end
def self.import_label_cache_key(project_id)
JIRA_IMPORT_LABEL % { project_id: project_id }
end
def self.increment_issue_failures(project_id)
Gitlab::Cache::Import::Caching.increment(self.failed_issues_counter_cache_key(project_id))
cache_class.increment(self.failed_issues_counter_cache_key(project_id))
end
def self.get_issues_next_start_at(project_id)
Gitlab::Cache::Import::Caching.read(self.jira_issues_next_page_cache_key(project_id)).to_i
cache_class.read(self.jira_issues_next_page_cache_key(project_id)).to_i
end
def self.store_issues_next_started_at(project_id, value)
cache_key = self.jira_issues_next_page_cache_key(project_id)
Gitlab::Cache::Import::Caching.write(cache_key, value)
cache_class.write(cache_key, value)
end
def self.cache_issue_mapping(issue_id, jira_issue_id, project_id)
cache_key = JiraImport.jira_issue_cache_key(project_id, jira_issue_id)
cache_class.write(cache_key, issue_id)
end
def self.get_import_label_id(project_id)
cache_class.read(JiraImport.import_label_cache_key(project_id))
end
def self.cache_import_label_id(project_id, label_id)
cache_class.write(JiraImport.import_label_cache_key(project_id), label_id)
end
def self.cache_cleanup(project_id)
Gitlab::Cache::Import::Caching.expire(self.failed_issues_counter_cache_key(project_id), JIRA_IMPORT_CACHE_TIMEOUT)
Gitlab::Cache::Import::Caching.expire(self.jira_issues_next_page_cache_key(project_id), JIRA_IMPORT_CACHE_TIMEOUT)
Gitlab::Cache::Import::Caching.expire(self.already_imported_cache_key(:issues, project_id), JIRA_IMPORT_CACHE_TIMEOUT)
cache_class.expire(self.import_label_cache_key(project_id), JIRA_IMPORT_CACHE_TIMEOUT)
cache_class.expire(self.failed_issues_counter_cache_key(project_id), JIRA_IMPORT_CACHE_TIMEOUT)
cache_class.expire(self.jira_issues_next_page_cache_key(project_id), JIRA_IMPORT_CACHE_TIMEOUT)
cache_class.expire(self.already_imported_cache_key(:issues, project_id), JIRA_IMPORT_CACHE_TIMEOUT)
end
def self.cache_class
Gitlab::Cache::Import::Caching
end
end
end
# frozen_string_literal: true
module Gitlab
module JiraImport
class LabelsImporter < BaseImporter
attr_reader :job_waiter
def initialize(project)
super
@job_waiter = JobWaiter.new
end
def execute
create_import_label(project)
import_jira_labels
end
private
def create_import_label(project)
label = Labels::CreateService.new(build_label_attrs(project)).execute(project: project)
raise Projects::ImportService::Error, _('Failed to create import label for jira import.') unless label
JiraImport.cache_import_label_id(project.id, label.id)
end
def build_label_attrs(project)
import_start_time = project&.import_state&.last_update_started_at || Time.now
title = "jira-import-#{import_start_time.strftime('%Y-%m-%d-%H-%M-%S')}"
description = "Label for issues that were imported from jira on #{import_start_time.strftime('%Y-%m-%d %H:%M:%S')}"
color = "#{Label.color_for(title)}"
{ title: title, description: description, color: color }
end
def import_jira_labels
# todo: import jira labels, see https://gitlab.com/gitlab-org/gitlab/-/issues/212651
job_waiter
end
end
end
end
......@@ -8481,6 +8481,9 @@ msgstr ""
msgid "Failed to create a branch for this issue. Please try again."
msgstr ""
msgid "Failed to create import label for jira import."
msgstr ""
msgid "Failed to create repository"
msgstr ""
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::JiraImport::LabelsImporter do
let(:user) { create(:user) }
let(:jira_import_data) do
data = JiraImportData.new
data << JiraImportData::JiraProjectDetails.new('XX', Time.now.strftime('%Y-%m-%d %H:%M:%S'), { user_id: user.id, name: user.name })
data
end
let(:project) { create(:project, import_data: jira_import_data) }
let!(:jira_service) { create(:jira_service, project: project) }
subject { described_class.new(project).execute }
before do
stub_feature_flags(jira_issue_import: true)
end
describe '#execute', :clean_gitlab_redis_cache do
context 'when label creation failes' do
before do
allow_next_instance_of(Labels::CreateService) do |instance|
allow(instance).to receive(:execute).and_return(nil)
end
end
it 'raises error' do
expect { subject }.to raise_error(Projects::ImportService::Error, 'Failed to create import label for jira import.')
end
end
context 'when label is created successfully' do
it 'creates import label' do
expect { subject }.to change { Label.count }.by(1)
end
it 'caches import label' do
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.import_label_cache_key(project.id))).to be nil
subject
expect(Gitlab::JiraImport.get_import_label_id(project.id).to_i).to be > 0
end
end
end
end
......@@ -32,12 +32,28 @@ describe Gitlab::JiraImport::ImportIssueWorker do
end
context 'when record is successfully inserted' do
before do
subject.perform(project.id, 123, issue_attrs, 'some-key')
let(:label) { create(:label, project: project) }
context 'when import label does not exist' do
it 'does not record import failure' do
subject.perform(project.id, 123, issue_attrs, 'some-key')
expect(label.issues.count).to eq(0)
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.failed_issues_counter_cache_key(project.id)).to_i).to eq(0)
end
end
it 'does not record import failure' do
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.failed_issues_counter_cache_key(project.id)).to_i).to eq(0)
context 'when import label exists' do
before do
Gitlab::JiraImport.cache_import_label_id(project.id, label.id)
end
it 'does not record import failure' do
subject.perform(project.id, 123, issue_attrs, 'some-key')
expect(label.issues.count).to eq(1)
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.failed_issues_counter_cache_key(project.id)).to_i).to eq(0)
end
end
end
end
......
......@@ -3,6 +3,7 @@
require 'spec_helper'
describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
describe 'modules' do
......@@ -30,9 +31,24 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
end
context 'when import started' do
let(:jira_import_data) do
data = JiraImportData.new
data << JiraImportData::JiraProjectDetails.new('XX', Time.now.strftime('%Y-%m-%d %H:%M:%S'), { user_id: user.id, name: user.name })
data
end
let(:project) { create(:project, import_data: jira_import_data) }
let!(:jira_service) { create(:jira_service, project: project) }
let!(:import_state) { create(:import_state, status: :started, project: project) }
it_behaves_like 'advance to next stage', :issues
it 'executes labels importer' do
expect_next_instance_of(Gitlab::JiraImport::LabelsImporter) do |instance|
expect(instance).to receive(:execute).and_return(Gitlab::JobWaiter.new)
end
described_class.new.perform(project.id)
end
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment