Commit 56661a3e authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '208907-jira-import' into 'master'

Kickoff Iteration: Add Import Jira Issues button to issues list page

See merge request gitlab-org/gitlab!26835
parents 5271e41b 4a68f2ce
# frozen_string_literal: true
module Projects
module Import
class JiraController < Projects::ApplicationController
before_action :jira_import_enabled?
before_action :jira_integration_configured?
def show
unless @project.import_state&.in_progress?
jira_client = @project.jira_service.client
@jira_projects = jira_client.Project.all.map { |p| ["#{p.name} (#{p.key})", p.key] }
end
flash[:notice] = _("Import %{status}") % { status: @project.import_state.status } if @project.import_state.present? && !@project.import_state.none?
end
def import
import_state = @project.import_state || @project.create_import_state
schedule_import(jira_import_params) unless import_state.in_progress?
redirect_to project_import_jira_path(@project)
end
private
def jira_import_enabled?
return if Feature.enabled?(:jira_issue_import, @project)
redirect_to project_issues_path(@project)
end
def jira_integration_configured?
return if @project.jira_service
flash[:notice] = _("Configure the Jira integration first on your project's %{strong_start} Settings > Integrations > Jira%{strong_end} page." %
{ strong_start: '<strong>'.html_safe, strong_end: '</strong>'.html_safe })
redirect_to project_issues_path(@project)
end
def schedule_import(params)
import_data = @project.create_or_update_import_data(data: {}).becomes(JiraImportData)
import_data << 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 }
)
@project.import_type = 'jira'
@project.import_state.schedule if @project.save
end
def jira_import_params
params.permit(:jira_project_key)
end
end
end
end
# frozen_string_literal: true
class JiraImportData < ProjectImportData
JiraProjectDetails = Struct.new(:key, :scheduled_at, :scheduled_by)
def projects
return [] unless data
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 }
end
def <<(project)
self.data ||= { jira: { projects: [] } }
self.data['jira']['projects'] << project.to_h.deep_stringify_keys!
end
end
- title = _('Jira Issue Import')
- page_title title
- breadcrumb_title title
- header_title _("Projects"), root_path
= render 'import/shared/errors'
- if @project.import_state&.in_progress?
%h3.page-title.d-flex.align-items-center
= sprite_icon('issues', size: 16, css_class: 'mr-1')
= _('Import in progress')
- else
%h3.page-title.d-flex.align-items-center
= sprite_icon('issues', size: 16, css_class: 'mr-1')
= _('Import issues from Jira')
= form_tag import_project_import_jira_path(@project), method: :post do
.form-group.row
= label_tag :jira_project_key, _('From project'), class: 'col-form-label col-md-2'
.col-md-4
= select_tag :jira_project_key, options_for_select(@jira_projects, ''), { class: 'select2' }
.form-actions
= submit_tag _('Import issues'), class: 'btn btn-success'
= link_to _('Cancel'), project_issues_path(@project), class: 'btn btn-cancel'
...@@ -7,3 +7,5 @@ ...@@ -7,3 +7,5 @@
- else - else
= _('Import CSV') = _('Import CSV')
- if Feature.enabled?(:jira_issue_import, @project)
= link_to _("Import Jira issues"), project_import_jira_path(@project), class: "btn btn-default"
...@@ -295,6 +295,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -295,6 +295,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
draw :repository_scoped draw :repository_scoped
draw :repository draw :repository
draw :wiki draw :wiki
namespace :import do
resource :jira, only: [:show], controller: :jira do
post :import
end
end
end end
# End of the /-/ scope. # End of the /-/ scope.
......
...@@ -5154,6 +5154,9 @@ msgstr "" ...@@ -5154,6 +5154,9 @@ msgstr ""
msgid "Configure the %{link} integration." msgid "Configure the %{link} integration."
msgstr "" msgstr ""
msgid "Configure the Jira integration first on your project's %{strong_start} Settings > Integrations > Jira%{strong_end} page."
msgstr ""
msgid "Configure the way a user creates a new account." msgid "Configure the way a user creates a new account."
msgstr "" msgstr ""
...@@ -8962,6 +8965,9 @@ msgstr "" ...@@ -8962,6 +8965,9 @@ msgstr ""
msgid "From merge request merge until deploy to production" msgid "From merge request merge until deploy to production"
msgstr "" msgstr ""
msgid "From project"
msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list" msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr "" msgstr ""
...@@ -10608,9 +10614,15 @@ msgstr "" ...@@ -10608,9 +10614,15 @@ msgstr ""
msgid "Import" msgid "Import"
msgstr "" msgstr ""
msgid "Import %{status}"
msgstr ""
msgid "Import CSV" msgid "Import CSV"
msgstr "" msgstr ""
msgid "Import Jira issues"
msgstr ""
msgid "Import Projects from Gitea" msgid "Import Projects from Gitea"
msgstr "" msgstr ""
...@@ -10632,6 +10644,9 @@ msgstr "" ...@@ -10632,6 +10644,9 @@ msgstr ""
msgid "Import issues" msgid "Import issues"
msgstr "" msgstr ""
msgid "Import issues from Jira"
msgstr ""
msgid "Import members" msgid "Import members"
msgstr "" msgstr ""
...@@ -11144,6 +11159,9 @@ msgstr "" ...@@ -11144,6 +11159,9 @@ msgstr ""
msgid "January" msgid "January"
msgstr "" msgstr ""
msgid "Jira Issue Import"
msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled." msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "" msgstr ""
......
# frozen_string_literal: true
require 'spec_helper'
describe Projects::Import::JiraController do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
context 'with anonymous user' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'get show' do
it 'redirects to issues page' do
get :show, params: { namespace_id: project.namespace, project_id: project }
expect(response).to redirect_to(new_user_session_path)
end
end
context 'post import' do
it 'redirects to issues page' do
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' }
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'with logged in user' do
before do
sign_in(user)
project.add_maintainer(user)
end
context 'when feature flag not enabled' do
before do
stub_feature_flags(jira_issue_import: false)
end
context 'get show' do
it 'redirects to issues page' do
get :show, params: { namespace_id: project.namespace, project_id: project }
expect(response).to redirect_to(project_issues_path(project))
end
end
context 'post import' do
it 'redirects to issues page' do
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' }
expect(response).to redirect_to(project_issues_path(project))
end
end
end
context 'when feature flag enabled' do
before do
stub_feature_flags(jira_issue_import: true)
end
context 'when jira service is enabled for the project' do
let_it_be(:jira_service) { create(:jira_service, project: project) }
context 'when running jira import first time' do
context 'get show' do
it 'renders show template' do
allow(JIRA::Resource::Project).to receive(:all).and_return([])
expect(project.import_state).to be_nil
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(response).to render_template :show
end
end
context 'post import' do
it 'creates import state' do
expect(project.import_state).to be_nil
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' }
project.reload
jira_project = project.import_data.data.dig('jira', 'projects').first
expect(project.import_type).to eq 'jira'
expect(project.import_state.status).to eq 'scheduled'
expect(jira_project['key']).to eq 'Test'
expect(response).to redirect_to(project_import_jira_path(project))
end
end
end
context 'when import state is scheduled' do
let_it_be(:import_state) { create(:import_state, project: project, status: :scheduled) }
context 'get show' do
it 'renders import status' do
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(project.import_state.status).to eq 'scheduled'
expect(flash.now[:notice]).to eq 'Import scheduled'
end
end
context 'post import' do
before do
project.reload
project.create_import_data(
data: {
'jira': {
'projects': [{ 'key': 'Test', scheduled_at: 5.days.ago, scheduled_by: { user_id: user.id, name: user.name } }]
}
}
)
end
it 'uses the existing import data' do
expect(controller).not_to receive(:schedule_import)
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
expect(response).to redirect_to(project_import_jira_path(project))
end
end
end
context 'when jira import ran before' do
let_it_be(:import_state) { create(:import_state, project: project, status: :finished) }
context 'get show' do
it 'renders import status' do
allow(JIRA::Resource::Project).to receive(:all).and_return([])
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
expect(project.import_state.status).to eq 'finished'
expect(flash.now[:notice]).to eq 'Import finished'
end
end
context 'post import' do
before do
project.reload
project.create_import_data(
data: {
'jira': {
'projects': [{ 'key': 'Test', scheduled_at: 5.days.ago, scheduled_by: { user_id: user.id, name: user.name } }]
}
}
)
end
it 'uses the existing import data' do
expect(controller).to receive(:schedule_import).and_call_original
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
project.reload
expect(project.import_state.status).to eq 'scheduled'
jira_imported_projects = project.import_data.data.dig('jira', 'projects')
expect(jira_imported_projects.size).to eq 2
expect(jira_imported_projects.first['key']).to eq 'Test'
expect(jira_imported_projects.last['key']).to eq 'New Project'
expect(response).to redirect_to(project_import_jira_path(project))
end
end
end
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