diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 15:09:13 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-03-18 15:09:13 +0300 |
commit | 1363ca12f1f07c634647cf55c4c16b7401098673 (patch) | |
tree | d932caf09c8148322edb51ae954ed159ff7d00f8 /app | |
parent | 6763d2787670bc03a36a8eb601703e88fc70dece (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
30 files changed, 412 insertions, 95 deletions
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue index be70bfc7399..03766c4877e 100644 --- a/app/assets/javascripts/repository/components/breadcrumbs.vue +++ b/app/assets/javascripts/repository/components/breadcrumbs.vue @@ -1,6 +1,6 @@ <script> import { GlDropdown, GlDropdownDivider, GlDropdownHeader, GlDropdownItem } from '@gitlab/ui'; -import { joinPaths } from '~/lib/utils/url_utility'; +import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility'; import { __ } from '../../locale'; import Icon from '../../vue_shared/components/icon.vue'; import getRefMixin from '../mixins/get_ref'; @@ -103,7 +103,7 @@ export default { .filter(p => p !== '') .reduce( (acc, name, i) => { - const path = joinPaths(i > 0 ? acc[i].path : '', encodeURIComponent(name)); + const path = joinPaths(i > 0 ? acc[i].path : '', escapeFileUrl(name)); return acc.concat({ name, diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue index b81e6a38b4c..f3e6e3686a3 100644 --- a/app/assets/javascripts/repository/components/table/row.vue +++ b/app/assets/javascripts/repository/components/table/row.vue @@ -1,7 +1,7 @@ <script> import { escapeRegExp } from 'lodash'; import { GlBadge, GlLink, GlSkeletonLoading, GlTooltipDirective, GlLoadingIcon } from '@gitlab/ui'; -import { visitUrl } from '~/lib/utils/url_utility'; +import { visitUrl, escapeFileUrl } from '~/lib/utils/url_utility'; import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import Icon from '~/vue_shared/components/icon.vue'; import { getIconName } from '../../utils/icon'; @@ -92,7 +92,7 @@ export default { computed: { routerLinkTo() { return this.isFolder - ? { path: `/-/tree/${escape(this.ref)}/${encodeURIComponent(this.path)}` } + ? { path: `/-/tree/${escape(this.ref)}/${escapeFileUrl(this.path)}` } : null; }, iconName() { diff --git a/app/controllers/projects/import/jira_controller.rb b/app/controllers/projects/import/jira_controller.rb index c74c180fa20..d38d9e27347 100644 --- a/app/controllers/projects/import/jira_controller.rb +++ b/app/controllers/projects/import/jira_controller.rb @@ -42,11 +42,13 @@ module Projects def schedule_import(params) import_data = @project.create_or_update_import_data(data: {}).becomes(JiraImportData) - import_data << JiraImportData::JiraProjectDetails.new( + jira_project_details = JiraImportData::JiraProjectDetails.new( params[:jira_project_key], Time.now.strftime('%Y-%m-%d %H:%M:%S'), { user_id: current_user.id, name: current_user.name } ) + import_data << jira_project_details + import_data.force_import! @project.import_type = 'jira' @project.import_state.schedule if @project.save diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index cc5ae32856a..4debf66db64 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -344,8 +344,8 @@ module BlobHelper def show_suggest_pipeline_creation_celebration? experiment_enabled?(:suggest_pipeline) && - @blob.auxiliary_viewer.valid?(project: @project, sha: @commit.sha, user: current_user) && @blob.path == Gitlab::FileDetector::PATTERNS[:gitlab_ci] && + @blob.auxiliary_viewer.valid?(project: @project, sha: @commit.sha, user: current_user) && @project.uses_default_ci_config? && cookies[suggest_pipeline_commit_cookie_name].present? end diff --git a/app/helpers/ci_variables_helper.rb b/app/helpers/ci_variables_helper.rb index 3f4c04070b5..b271f069778 100644 --- a/app/helpers/ci_variables_helper.rb +++ b/app/helpers/ci_variables_helper.rb @@ -45,6 +45,6 @@ module CiVariablesHelper end def ci_variable_maskable_regex - Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/') + Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/') end end diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb index 0e50265c7ba..1e1dd68ee6c 100644 --- a/app/models/ci/group_variable.rb +++ b/app/models/ci/group_variable.rb @@ -3,9 +3,9 @@ module Ci class GroupVariable < ApplicationRecord extend Gitlab::Ci::Model - include HasVariable + include Ci::HasVariable include Presentable - include Maskable + include Ci::Maskable belongs_to :group, class_name: "::Group" diff --git a/app/models/ci/job_variable.rb b/app/models/ci/job_variable.rb index f2968c037c7..7eea8a37150 100644 --- a/app/models/ci/job_variable.rb +++ b/app/models/ci/job_variable.rb @@ -3,7 +3,7 @@ module Ci class JobVariable < ApplicationRecord extend Gitlab::Ci::Model - include NewHasVariable + include Ci::NewHasVariable include BulkInsertSafe belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb index be6e5e76c31..adef9911ae1 100644 --- a/app/models/ci/pipeline_schedule_variable.rb +++ b/app/models/ci/pipeline_schedule_variable.rb @@ -3,7 +3,7 @@ module Ci class PipelineScheduleVariable < ApplicationRecord extend Gitlab::Ci::Model - include HasVariable + include Ci::HasVariable belongs_to :pipeline_schedule diff --git a/app/models/ci/pipeline_variable.rb b/app/models/ci/pipeline_variable.rb index 51a6272e1ff..84ca4833cd7 100644 --- a/app/models/ci/pipeline_variable.rb +++ b/app/models/ci/pipeline_variable.rb @@ -3,7 +3,7 @@ module Ci class PipelineVariable < ApplicationRecord extend Gitlab::Ci::Model - include HasVariable + include Ci::HasVariable belongs_to :pipeline diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 760872d3e6b..08d39595c61 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -3,9 +3,9 @@ module Ci class Variable < ApplicationRecord extend Gitlab::Ci::Model - include HasVariable + include Ci::HasVariable include Presentable - include Maskable + include Ci::Maskable prepend HasEnvironmentScope belongs_to :project diff --git a/app/models/concerns/ci/has_variable.rb b/app/models/concerns/ci/has_variable.rb new file mode 100644 index 00000000000..9bf2b409080 --- /dev/null +++ b/app/models/concerns/ci/has_variable.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Ci + module HasVariable + extend ActiveSupport::Concern + + included do + enum variable_type: { + env_var: 1, + file: 2 + } + + validates :key, + presence: true, + length: { maximum: 255 }, + format: { with: /\A[a-zA-Z0-9_]+\z/, + message: "can contain only letters, digits and '_'." } + + scope :order_key_asc, -> { reorder(key: :asc) } + + attr_encrypted :value, + mode: :per_attribute_iv_and_salt, + insecure_mode: true, + key: Settings.attr_encrypted_db_key_base, + algorithm: 'aes-256-cbc' + + def key=(new_key) + super(new_key.to_s.strip) + end + end + + def to_runner_variable + { key: key, value: value, public: false, file: file? } + end + end +end diff --git a/app/models/concerns/ci/maskable.rb b/app/models/concerns/ci/maskable.rb new file mode 100644 index 00000000000..15bc48bf964 --- /dev/null +++ b/app/models/concerns/ci/maskable.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Ci + module Maskable + extend ActiveSupport::Concern + + # * Single line + # * No escape characters + # * No variables + # * No spaces + # * Minimal length of 8 characters + # * Characters must be from the Base64 alphabet (RFC4648) with the addition of @ and : + # * Absolutely no fun is allowed + REGEX = /\A[a-zA-Z0-9_+=\/@:-]{8,}\z/.freeze + + included do + validates :masked, inclusion: { in: [true, false] } + validates :value, format: { with: REGEX }, if: :masked? + end + + def to_runner_variable + super.merge(masked: masked?) + end + end +end diff --git a/app/models/concerns/ci/new_has_variable.rb b/app/models/concerns/ci/new_has_variable.rb new file mode 100644 index 00000000000..546d243e5de --- /dev/null +++ b/app/models/concerns/ci/new_has_variable.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Ci + module NewHasVariable + extend ActiveSupport::Concern + include Ci::HasVariable + + included do + attr_encrypted :value, + mode: :per_attribute_iv, + algorithm: 'aes-256-gcm', + key: Settings.attr_encrypted_db_key_base_32, + insecure_mode: false + end + end +end diff --git a/app/models/concerns/has_variable.rb b/app/models/concerns/has_variable.rb deleted file mode 100644 index b4e99569071..00000000000 --- a/app/models/concerns/has_variable.rb +++ /dev/null @@ -1,34 +0,0 @@ -# frozen_string_literal: true - -module HasVariable - extend ActiveSupport::Concern - - included do - enum variable_type: { - env_var: 1, - file: 2 - } - - validates :key, - presence: true, - length: { maximum: 255 }, - format: { with: /\A[a-zA-Z0-9_]+\z/, - message: "can contain only letters, digits and '_'." } - - scope :order_key_asc, -> { reorder(key: :asc) } - - attr_encrypted :value, - mode: :per_attribute_iv_and_salt, - insecure_mode: true, - key: Settings.attr_encrypted_db_key_base, - algorithm: 'aes-256-cbc' - - def key=(new_key) - super(new_key.to_s.strip) - end - end - - def to_runner_variable - { key: key, value: value, public: false, file: file? } - end -end diff --git a/app/models/concerns/maskable.rb b/app/models/concerns/maskable.rb deleted file mode 100644 index d70e47bc4ff..00000000000 --- a/app/models/concerns/maskable.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -module Maskable - extend ActiveSupport::Concern - - # * Single line - # * No escape characters - # * No variables - # * No spaces - # * Minimal length of 8 characters - # * Characters must be from the Base64 alphabet (RFC4648) with the addition of @ and : - # * Absolutely no fun is allowed - REGEX = /\A[a-zA-Z0-9_+=\/@:-]{8,}\z/.freeze - - included do - validates :masked, inclusion: { in: [true, false] } - validates :value, format: { with: REGEX }, if: :masked? - end - - def to_runner_variable - super.merge(masked: masked?) - end -end diff --git a/app/models/concerns/new_has_variable.rb b/app/models/concerns/new_has_variable.rb deleted file mode 100644 index 429bf496872..00000000000 --- a/app/models/concerns/new_has_variable.rb +++ /dev/null @@ -1,14 +0,0 @@ -# frozen_string_literal: true - -module NewHasVariable - extend ActiveSupport::Concern - include HasVariable - - included do - attr_encrypted :value, - mode: :per_attribute_iv, - algorithm: 'aes-256-gcm', - key: Settings.attr_encrypted_db_key_base_32, - insecure_mode: false - end -end diff --git a/app/models/jira_import_data.rb b/app/models/jira_import_data.rb index 3f882deb24d..63be190aa0d 100644 --- a/app/models/jira_import_data.rb +++ b/app/models/jira_import_data.rb @@ -3,17 +3,40 @@ class JiraImportData < ProjectImportData JiraProjectDetails = Struct.new(:key, :scheduled_at, :scheduled_by) + FORCE_IMPORT_KEY = 'force-import' + def projects return [] unless data - projects = data.dig('jira', 'projects').map do |p| + projects = data.dig('jira', 'projects')&.map do |p| JiraProjectDetails.new(p['key'], p['scheduled_at'], p['scheduled_by']) end - projects.sort_by { |jp| jp.scheduled_at } + + projects&.sort_by { |jp| jp.scheduled_at } || [] end def <<(project) - self.data ||= { jira: { projects: [] } } - self.data['jira']['projects'] << project.to_h.deep_stringify_keys! + self.data ||= { 'jira' => { 'projects' => [] } } + self.data['jira'] ||= { 'projects' => [] } + self.data['jira']['projects'] = [] if data['jira']['projects'].blank? || !data['jira']['projects'].is_a?(Array) + + self.data['jira']['projects'] << project.to_h + self.data.deep_stringify_keys! + end + + def force_import! + self.data ||= {} + self.data.deep_merge!({ 'jira' => { FORCE_IMPORT_KEY => true } }) + self.data.deep_stringify_keys! + end + + def force_import? + !!data&.dig('jira', FORCE_IMPORT_KEY) && !projects.blank? + end + + def finish_import! + return if data&.dig('jira', FORCE_IMPORT_KEY).nil? + + data['jira'].delete(FORCE_IMPORT_KEY) end end diff --git a/app/models/project.rb b/app/models/project.rb index 4892c5310ec..7e006e734c5 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -868,6 +868,8 @@ class Project < ApplicationRecord elsif gitlab_project_import? # Do not retry on Import/Export until https://gitlab.com/gitlab-org/gitlab-foss/issues/26189 is solved. RepositoryImportWorker.set(retry: false).perform_async(self.id) + elsif jira_import? + Gitlab::JiraImport::Stage::StartImportWorker.perform_async(self.id) else RepositoryImportWorker.perform_async(self.id) end @@ -900,7 +902,7 @@ class Project < ApplicationRecord # This method is overridden in EE::Project model def remove_import_data - import_data&.destroy + import_data&.destroy unless jira_import? end def ci_config_path=(value) @@ -947,7 +949,7 @@ class Project < ApplicationRecord end def import? - external_import? || forked? || gitlab_project_import? || bare_repository_import? + external_import? || forked? || gitlab_project_import? || jira_import? || bare_repository_import? end def external_import? @@ -962,6 +964,14 @@ class Project < ApplicationRecord import_type == 'bare_repository' end + def jira_import? + import_type == 'jira' && Feature.enabled?(:jira_issue_import, self) + end + + def jira_force_import? + jira_import? && import_data&.becomes(JiraImportData)&.force_import? + end + def gitlab_project_import? import_type == 'gitlab_project' end diff --git a/app/services/milestones/transfer_service.rb b/app/services/milestones/transfer_service.rb index 213c6f8f1dd..18d7e41adc7 100644 --- a/app/services/milestones/transfer_service.rb +++ b/app/services/milestones/transfer_service.rb @@ -46,7 +46,7 @@ module Milestones Milestone.joins(:issues) .where( issues: { project_id: project.id }, - group_id: old_group.id + group_id: old_group.self_and_ancestors ) end # rubocop: enable CodeReuse/ActiveRecord @@ -56,7 +56,7 @@ module Milestones Milestone.joins(:merge_requests) .where( merge_requests: { target_project_id: project.id }, - group_id: old_group.id + group_id: old_group.self_and_ancestors ) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml index 3df86e3314d..dd0eeaa9359 100644 --- a/app/workers/all_queues.yml +++ b/app/workers/all_queues.yml @@ -528,6 +528,55 @@ :resource_boundary: :unknown :weight: 2 :idempotent: +- :name: jira_importer:jira_import_advance_stage + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_finish_import + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_import_attachments + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_import_issues + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_import_labels + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_import_notes + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: +- :name: jira_importer:jira_import_stage_start_import + :feature_category: :importers + :has_external_dependencies: + :urgency: :low + :resource_boundary: :unknown + :weight: 1 + :idempotent: - :name: mail_scheduler:mail_scheduler_issue_due :feature_category: :issue_tracking :has_external_dependencies: diff --git a/app/workers/concerns/gitlab/jira_import/import_worker.rb b/app/workers/concerns/gitlab/jira_import/import_worker.rb new file mode 100644 index 00000000000..7cc650bfc29 --- /dev/null +++ b/app/workers/concerns/gitlab/jira_import/import_worker.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module ImportWorker + extend ActiveSupport::Concern + + included do + include ApplicationWorker + include Gitlab::JiraImport::QueueOptions + end + + def perform(project_id) + project = Project.find_by(id: project_id) # rubocop: disable CodeReuse/ActiveRecord + + return unless can_import?(project) + + import(project) + end + + private + + def import(project) + raise NotImplementedError + end + + def can_import?(project) + return false unless project + return false if Feature.disabled?(:jira_issue_import, project) + + project.import_state.started? + end + end + end +end diff --git a/app/workers/concerns/gitlab/jira_import/queue_options.rb b/app/workers/concerns/gitlab/jira_import/queue_options.rb new file mode 100644 index 00000000000..bc1148f7d3b --- /dev/null +++ b/app/workers/concerns/gitlab/jira_import/queue_options.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module QueueOptions + extend ActiveSupport::Concern + + included do + queue_namespace :jira_importer + feature_category :importers + + sidekiq_options retry: 5 + end + end + end +end diff --git a/app/workers/gitlab/github_import/advance_stage_worker.rb b/app/workers/gitlab/github_import/advance_stage_worker.rb index 8fbf88a1762..8bbfb10ed6e 100644 --- a/app/workers/gitlab/github_import/advance_stage_worker.rb +++ b/app/workers/gitlab/github_import/advance_stage_worker.rb @@ -13,8 +13,6 @@ module Gitlab sidekiq_options dead: false feature_category :importers - private - # The known importer stages and their corresponding Sidekiq workers. STAGES = { issues_and_diff_notes: Stage::ImportIssuesAndDiffNotesWorker, @@ -23,6 +21,8 @@ module Gitlab finish: Stage::FinishImportWorker }.freeze + private + def next_stage_worker(next_stage) STAGES.fetch(next_stage.to_sym) end diff --git a/app/workers/gitlab/jira_import/advance_stage_worker.rb b/app/workers/gitlab/jira_import/advance_stage_worker.rb new file mode 100644 index 00000000000..1b6fc54151e --- /dev/null +++ b/app/workers/gitlab/jira_import/advance_stage_worker.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + class AdvanceStageWorker # rubocop:disable Scalability/IdempotentWorker + include ApplicationWorker + include QueueOptions + include ::Gitlab::Import::AdvanceStage + + # The known importer stages and their corresponding Sidekiq workers. + STAGES = { + labels: Gitlab::JiraImport::Stage::ImportLabelsWorker, + issues: Gitlab::JiraImport::Stage::ImportIssuesWorker, + attachments: Gitlab::JiraImport::Stage::ImportAttachmentsWorker, + notes: Gitlab::JiraImport::Stage::ImportNotesWorker, + finish: Gitlab::JiraImport::Stage::FinishImportWorker + }.freeze + + private + + def next_stage_worker(next_stage) + STAGES.fetch(next_stage.to_sym) + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/finish_import_worker.rb b/app/workers/gitlab/jira_import/stage/finish_import_worker.rb new file mode 100644 index 00000000000..5b1661d68c6 --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/finish_import_worker.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class FinishImportWorker # rubocop:disable Scalability/IdempotentWorker + include Gitlab::JiraImport::ImportWorker + + private + + def import(project) + project.after_import + ensure + project.import_data.becomes(JiraImportData).finish_import! + project.import_data.save! + end + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/import_attachments_worker.rb b/app/workers/gitlab/jira_import/stage/import_attachments_worker.rb new file mode 100644 index 00000000000..3b209a279b5 --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/import_attachments_worker.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class ImportAttachmentsWorker # rubocop:disable Scalability/IdempotentWorker + include Gitlab::JiraImport::ImportWorker + + private + + def import(project) + # fake a attahcments 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 + + project.import_state.refresh_jid_expiration + Gitlab::JiraImport::AdvanceStageWorker.perform_async(project.id, { fake_waiter.key => fake_waiter.jobs_remaining }, :notes) + end + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/import_issues_worker.rb b/app/workers/gitlab/jira_import/stage/import_issues_worker.rb new file mode 100644 index 00000000000..79ed8e1f2da --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/import_issues_worker.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class ImportIssuesWorker # rubocop:disable Scalability/IdempotentWorker + include Gitlab::JiraImport::ImportWorker + + private + + def import(project) + # fake issues import workers for now + # new job waiter will have zero jobs_remaining by default, so it will just pass on to next stage + jobs_waiter = JobWaiter.new + project.import_state.refresh_jid_expiration + + Gitlab::JiraImport::AdvanceStageWorker.perform_async(project.id, { jobs_waiter.key => jobs_waiter.jobs_remaining }, :attachments) + end + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/import_labels_worker.rb b/app/workers/gitlab/jira_import/stage/import_labels_worker.rb new file mode 100644 index 00000000000..b96bb1bbdda --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/import_labels_worker.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class ImportLabelsWorker # rubocop:disable Scalability/IdempotentWorker + include Gitlab::JiraImport::ImportWorker + + 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) + end + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/import_notes_worker.rb b/app/workers/gitlab/jira_import/stage/import_notes_worker.rb new file mode 100644 index 00000000000..9eef0d31a8c --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/import_notes_worker.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class ImportNotesWorker # rubocop:disable Scalability/IdempotentWorker + include Gitlab::JiraImport::ImportWorker + + private + + def import(project) + # fake notes import workers for now + # new job waiter will have zero jobs_remaining by default, so it will just pass on to next stage + jobs_waiter = JobWaiter.new + project.import_state.refresh_jid_expiration + + Gitlab::JiraImport::AdvanceStageWorker.perform_async(project.id, { jobs_waiter.key => jobs_waiter.jobs_remaining }, :finish) + end + end + end + end +end diff --git a/app/workers/gitlab/jira_import/stage/start_import_worker.rb b/app/workers/gitlab/jira_import/stage/start_import_worker.rb new file mode 100644 index 00000000000..8abbfab647b --- /dev/null +++ b/app/workers/gitlab/jira_import/stage/start_import_worker.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module Gitlab + module JiraImport + module Stage + class StartImportWorker # rubocop:disable Scalability/IdempotentWorker + include ApplicationWorker + include ProjectStartImport + include ProjectImportOptions + include Gitlab::JiraImport::QueueOptions + + attr_reader :project + + def perform(project_id) + @project = Project.find_by(id: project_id) # rubocop: disable CodeReuse/ActiveRecord + + return unless start_import + + Gitlab::Import::SetAsyncJid.set_jid(project) + + Gitlab::JiraImport::Stage::ImportLabelsWorker.perform_async(project.id) + end + + private + + def start_import + return false unless project + return false if Feature.disabled?(:jira_issue_import, project) + return true if start(project.import_state) + + Gitlab::Import::Logger.info( + { + project_id: project.id, + project_path: project.full_path, + state: project&.import_status, + message: 'inconsistent state while importing' + } + ) + false + end + end + end + end +end |