Commit e7595c10 authored by Sean McGivern's avatar Sean McGivern

Merge branch '37050-ext-issue-tracker' into 'master'

Display a link to external issue tracker when enabled

Closes #37050

See merge request gitlab-org/gitlab-ce!17030
parents 7da1a3d7 499d0501
...@@ -296,6 +296,10 @@ module ProjectsHelper ...@@ -296,6 +296,10 @@ module ProjectsHelper
nav_tabs << :pipelines nav_tabs << :pipelines
end end
if project.external_issue_tracker
nav_tabs << :external_issue_tracker
end
tab_ability_map.each do |tab, ability| tab_ability_map.each do |tab, ability|
if can?(current_user, ability, project) if can?(current_user, ability, project)
nav_tabs << tab nav_tabs << tab
......
...@@ -10,6 +10,8 @@ class JiraService < IssueTrackerService ...@@ -10,6 +10,8 @@ class JiraService < IssueTrackerService
before_update :reset_password before_update :reset_password
alias_method :project_url, :url
# This is confusing, but JiraService does not really support these events. # This is confusing, but JiraService does not really support these events.
# The values here are required to display correct options in the service # The values here are required to display correct options in the service
# configuration screen. # configuration screen.
......
...@@ -127,6 +127,19 @@ ...@@ -127,6 +127,19 @@
= link_to project_milestones_path(@project), title: 'Milestones' do = link_to project_milestones_path(@project), title: 'Milestones' do
%span %span
Milestones Milestones
- if project_nav_tab? :external_issue_tracker
= nav_link do
- issue_tracker = @project.external_issue_tracker
= link_to issue_tracker.issue_tracker_path, class: 'shortcuts-external_tracker' do
.nav-icon-container
= sprite_icon('issue-external')
%span.nav-item-name
= issue_tracker.title
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(html_options: { class: "fly-out-top-item" } ) do
= link_to issue_tracker.issue_tracker_path do
%strong.fly-out-top-item-name
= issue_tracker.title
- if project_nav_tab? :merge_requests - if project_nav_tab? :merge_requests
= nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
......
---
title: Display a link to external issue tracker when enabled
merge_request:
author:
type: changed
...@@ -11,11 +11,7 @@ in the table below. ...@@ -11,11 +11,7 @@ in the table below.
| `issues_url` | The URL to the issue in Bugzilla project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. | | `issues_url` | The URL to the issue in Bugzilla project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
| `new_issue_url` | This is the URL to create a new issue in Bugzilla for the project linked to this GitLab project. Note that the `new_issue_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. | | `new_issue_url` | This is the URL to create a new issue in Bugzilla for the project linked to this GitLab project. Note that the `new_issue_url` requires PRODUCT_NAME to be updated with the product/project name in Bugzilla. |
Once you have configured and enabled Bugzilla: Once you have configured and enabled Bugzilla you'll see the Bugzilla link on the GitLab project pages that takes you to the appropriate Bugzilla project.
- the **Issues** link on the GitLab project pages takes you to the appropriate
Bugzilla product page
- clicking **New issue** on the project dashboard takes you to Bugzilla for entering a new issue
## Referencing issues in Bugzilla ## Referencing issues in Bugzilla
......
...@@ -116,7 +116,7 @@ in the table below. ...@@ -116,7 +116,7 @@ in the table below.
| `Transition ID` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** | | `Transition ID` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). **Closing JIRA issues via commits or Merge Requests won't work if you don't set the ID correctly.** |
After saving the configuration, your GitLab project will be able to interact After saving the configuration, your GitLab project will be able to interact
with all JIRA projects in your JIRA instance. with all JIRA projects in your JIRA instance and you'll see the JIRA link on the GitLab project pages that takes you to the appropriate JIRA project.
![JIRA service page](img/jira_service_page.png) ![JIRA service page](img/jira_service_page.png)
......
...@@ -12,6 +12,8 @@ in the table below. ...@@ -12,6 +12,8 @@ in the table below.
| `issues_url` | The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. | | `issues_url` | The URL to the issue in Redmine project that is linked to this GitLab project. Note that the `issues_url` requires `:id` in the URL. This ID is used by GitLab as a placeholder to replace the issue number. |
| `new_issue_url` | This is the URL to create a new issue in Redmine for the project linked to this GitLab project. **This is currently not being used and will be removed in a future release.** | | `new_issue_url` | This is the URL to create a new issue in Redmine for the project linked to this GitLab project. **This is currently not being used and will be removed in a future release.** |
Once you have configured and enabled Redmine you'll see the Redmine link on the GitLab project pages that takes you to the appropriate Redmine project.
As an example, below is a configuration for a project named gitlab-ci. As an example, below is a configuration for a project named gitlab-ci.
![Redmine configuration](img/redmine_configuration.png) ![Redmine configuration](img/redmine_configuration.png)
......
require 'spec_helper'
describe 'User activates issue tracker', :js do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:url) { 'http://tracker.example.com' }
def fill_form(active = true)
check 'Active' if active
fill_in 'service_project_url', with: url
fill_in 'service_issues_url', with: "#{url}/:id"
fill_in 'service_new_issue_url', with: url
end
before do
project.add_master(user)
sign_in(user)
visit project_settings_integrations_path(project)
end
shared_examples 'external issue tracker activation' do |tracker:|
describe 'user sets and activates the Service' do
context 'when the connection test succeeds' do
before do
stub_request(:head, url).to_return(headers: { 'Content-Type' => 'application/json' })
click_link(tracker)
fill_form
click_button('Test settings and save changes')
wait_for_requests
end
it 'activates the service' do
expect(page).to have_content("#{tracker} activated.")
expect(current_path).to eq(project_settings_integrations_path(project))
end
it 'shows the link in the menu' do
page.within('.nav-sidebar') do
expect(page).to have_link(tracker, href: url)
end
end
end
context 'when the connection test fails' do
it 'activates the service' do
stub_request(:head, url).to_raise(HTTParty::Error)
click_link(tracker)
fill_form
click_button('Test settings and save changes')
wait_for_requests
expect(find('.flash-container-page')).to have_content 'Test failed.'
expect(find('.flash-container-page')).to have_content 'Save anyway'
find('.flash-alert .flash-action').click
wait_for_requests
expect(page).to have_content("#{tracker} activated.")
expect(current_path).to eq(project_settings_integrations_path(project))
end
end
end
describe 'user sets the service but keeps it disabled' do
before do
click_link(tracker)
fill_form(false)
click_button('Save changes')
end
it 'saves but does not activate the service' do
expect(page).to have_content("#{tracker} settings saved, but not activated.")
expect(current_path).to eq(project_settings_integrations_path(project))
end
it 'does not show the external tracker link in the menu' do
page.within('.nav-sidebar') do
expect(page).not_to have_link(tracker, href: url)
end
end
end
end
it_behaves_like 'external issue tracker activation', tracker: 'Redmine'
it_behaves_like 'external issue tracker activation', tracker: 'Bugzilla'
it_behaves_like 'external issue tracker activation', tracker: 'Custom Issue Tracker'
end
...@@ -3,7 +3,6 @@ require 'spec_helper' ...@@ -3,7 +3,6 @@ require 'spec_helper'
describe 'User activates Jira', :js do describe 'User activates Jira', :js do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project) } let(:project) { create(:project) }
let(:service) { project.create_jira_service }
let(:url) { 'http://jira.example.com' } let(:url) { 'http://jira.example.com' }
let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' } let(:test_url) { 'http://jira.example.com/rest/api/2/serverInfo' }
...@@ -26,7 +25,7 @@ describe 'User activates Jira', :js do ...@@ -26,7 +25,7 @@ describe 'User activates Jira', :js do
describe 'user sets and activates Jira Service' do describe 'user sets and activates Jira Service' do
context 'when Jira connection test succeeds' do context 'when Jira connection test succeeds' do
it 'activates the JIRA service' do before do
server_info = { key: 'value' }.to_json server_info = { key: 'value' }.to_json
WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info) WebMock.stub_request(:get, test_url).with(basic_auth: %w(username password)).to_return(body: server_info)
...@@ -34,10 +33,18 @@ describe 'User activates Jira', :js do ...@@ -34,10 +33,18 @@ describe 'User activates Jira', :js do
fill_form fill_form
click_button('Test settings and save changes') click_button('Test settings and save changes')
wait_for_requests wait_for_requests
end
it 'activates the JIRA service' do
expect(page).to have_content('JIRA activated.') expect(page).to have_content('JIRA activated.')
expect(current_path).to eq(project_settings_integrations_path(project)) expect(current_path).to eq(project_settings_integrations_path(project))
end end
it 'shows the JIRA link in the menu' do
page.within('.nav-sidebar') do
expect(page).to have_link('JIRA', href: url)
end
end
end end
context 'when Jira connection test fails' do context 'when Jira connection test fails' do
...@@ -75,14 +82,20 @@ describe 'User activates Jira', :js do ...@@ -75,14 +82,20 @@ describe 'User activates Jira', :js do
end end
describe 'user sets Jira Service but keeps it disabled' do describe 'user sets Jira Service but keeps it disabled' do
context 'when Jira connection test succeeds' do before do
it 'activates the JIRA service' do click_link('JIRA')
click_link('JIRA') fill_form(false)
fill_form(false) click_button('Save changes')
click_button('Save changes') end
expect(page).to have_content('JIRA settings saved, but not activated.') it 'saves but does not activate the JIRA service' do
expect(current_path).to eq(project_settings_integrations_path(project)) expect(page).to have_content('JIRA settings saved, but not activated.')
expect(current_path).to eq(project_settings_integrations_path(project))
end
it 'does not show the JIRA link in the menu' do
page.within('.nav-sidebar') do
expect(page).not_to have_link('JIRA', href: url)
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