summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYauhen Kotau <yauhen.kotau@psa-software.com>2019-02-18 20:08:36 +0300
committerYauhen Kotau <yauhen.kotau@psa-software.com>2019-02-18 20:08:36 +0300
commit04daa0b9701cd5b53c3c1fd6529aba05e4189114 (patch)
tree2680c1b9eca8317168018e2219d7fb718e32848f
parentfe10964a6884162b9272ec3a32a5736c2a997ab2 (diff)
downloadgitlab-ce-04daa0b9701cd5b53c3c1fd6529aba05e4189114.tar.gz
Added YouTrack integration
Fixes gitlab-org/gitlab-ce#42595
-rw-r--r--app/models/project.rb1
-rw-r--r--app/models/project_services/youtrack_service.rb36
-rw-r--r--app/models/service.rb1
-rw-r--r--doc/integration/external-issue-tracker.md5
-rw-r--r--doc/user/project/integrations/project_services.md1
-rw-r--r--doc/user/project/integrations/youtrack.md28
-rw-r--r--doc/user/project/issues/index.md2
-rw-r--r--lib/api/services.rb27
-rw-r--r--spec/factories/projects.rb15
-rw-r--r--spec/lib/banzai/filter/external_issue_reference_filter_spec.rb22
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml1
-rw-r--r--spec/lib/gitlab/import_export/project.json20
-rw-r--r--spec/models/project_services/youtrack_service_spec.rb41
13 files changed, 197 insertions, 3 deletions
diff --git a/app/models/project.rb b/app/models/project.rb
index c72d3a3b725..ec6b9b495d4 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -160,6 +160,7 @@ class Project < ActiveRecord::Base
has_one :pushover_service
has_one :jira_service
has_one :redmine_service
+ has_one :youtrack_service
has_one :custom_issue_tracker_service
has_one :bugzilla_service
has_one :gitlab_issue_tracker_service, inverse_of: :project
diff --git a/app/models/project_services/youtrack_service.rb b/app/models/project_services/youtrack_service.rb
new file mode 100644
index 00000000000..ed8c0635124
--- /dev/null
+++ b/app/models/project_services/youtrack_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+class YoutrackService < IssueTrackerService
+ validates :project_url, :issues_url, :new_issue_url, presence: true, public_url: true, if: :activated?
+
+ prop_accessor :title, :description, :project_url, :issues_url, :new_issue_url
+
+ # {PROJECT-KEY}-{NUMBER} Examples: YT-1, PRJ-1
+ def self.reference_pattern(only_long: false)
+ if only_long
+ /(?<issue>\b[A-Z][A-Z0-9_]*-\d+)/
+ else
+ /(?<issue>\b[A-Z][A-Z0-9_]*-\d+)|(#{Issue.reference_prefix}(?<issue>\d+))/
+ end
+ end
+
+ def title
+ if self.properties && self.properties['title'].present?
+ self.properties['title']
+ else
+ 'YouTrack'
+ end
+ end
+
+ def description
+ if self.properties && self.properties['description'].present?
+ self.properties['description']
+ else
+ 'YouTrack issue tracker'
+ end
+ end
+
+ def self.to_param
+ 'youtrack'
+ end
+end
diff --git a/app/models/service.rb b/app/models/service.rb
index 3461e0bfe70..da523bfa426 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -266,6 +266,7 @@ class Service < ActiveRecord::Base
prometheus
pushover
redmine
+ youtrack
slack_slash_commands
slack
teamcity
diff --git a/doc/integration/external-issue-tracker.md b/doc/integration/external-issue-tracker.md
index 075feaeead9..edd1af423ca 100644
--- a/doc/integration/external-issue-tracker.md
+++ b/doc/integration/external-issue-tracker.md
@@ -1,8 +1,8 @@
# External issue tracker
GitLab has a great issue tracker but you can also use an external one such as
-Jira, Redmine, or Bugzilla. Issue trackers are configurable per GitLab project and allow
-you to do the following:
+Jira, Redmine, YouTrack, or Bugzilla. Issue trackers are configurable per GitLab project
+and allow you to do the following:
- you can reference these external issues inside GitLab interface
(merge requests, commits, comments) and they will be automatically converted
@@ -20,6 +20,7 @@ To enable an external issue tracker you must configure the appropriate **Service
Visit the links below for details:
- [Redmine](../user/project/integrations/redmine.md)
+- [YouTrack](../user/project/integrations/youtrack.md)
- [Jira](../user/project/integrations/jira.md)
- [Bugzilla](../user/project/integrations/bugzilla.md)
- [Custom Issue Tracker](../user/project/integrations/custom_issue_tracker.md)
diff --git a/doc/user/project/integrations/project_services.md b/doc/user/project/integrations/project_services.md
index cec9018b67f..e2f23827360 100644
--- a/doc/user/project/integrations/project_services.md
+++ b/doc/user/project/integrations/project_services.md
@@ -50,6 +50,7 @@ Click on the service links to see further configuration instructions and details
| [Prometheus](prometheus.md) | Monitor the performance of your deployed apps |
| Pushover | Pushover makes it easy to get real-time notifications on your Android device, iPhone, iPad, and Desktop |
| [Redmine](redmine.md) | Redmine issue tracker |
+| [YouTrack](youtrack.md) | YouTrack issue tracker |
## Services templates
diff --git a/doc/user/project/integrations/youtrack.md b/doc/user/project/integrations/youtrack.md
new file mode 100644
index 00000000000..85c339d5fa9
--- /dev/null
+++ b/doc/user/project/integrations/youtrack.md
@@ -0,0 +1,28 @@
+# YouTrack Service
+
+1. To enable the YouTrack integration in a project, navigate to the
+[Integrations page](project_services.md#accessing-the-project-services), click
+the **YouTrack** service, and fill in the required details on the page as described
+in the table below.
+
+ | Field | Description |
+ | ----- | ----------- |
+ | `description` | A name for the issue tracker (to differentiate between instances, for example) |
+ | `project_url` | The URL to the project in YouTrack which is being linked to this GitLab project |
+ | `issues_url` | The URL to the issue in YouTrack 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 YouTrack 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 YouTrack you'll see the YouTrack link on the GitLab project pages that takes you to the appropriate YouTrack project.
+
+1. To disable the internal issue tracking system in a project, navigate to the General page, expand [Permissions](../settings/index.md#sharing-and-permissions), and slide the Issues switch invalid.
+
+ ![Issue configuration](img/issue_configuration.png)
+
+## Referencing issues in YouTrack
+
+Issues in YouTrack can be referenced as `<PROJECT>-<ID>` where `<PROJECT>`
+starts with a capital letter which is then followed by capital letters, numbers
+or underscores, and `<ID>` is a number (example `API_32-143`).
+
+`<PROJECT>` part is included into issue_id and links can point any YouTrack
+project (`issues_url` + issue_id)
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 5a3ac9c175b..907a305fe23 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -155,7 +155,7 @@ For further details, see [Importing issues from CSV](csv_import.md)
Alternatively to GitLab's built-in Issue Tracker, you can also use an [external
tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
-or Bugzilla.
+YouTrack, or Bugzilla.
### Issue API
diff --git a/lib/api/services.rb b/lib/api/services.rb
index 163c7505a65..fcaec06061b 100644
--- a/lib/api/services.rb
+++ b/lib/api/services.rb
@@ -592,6 +592,32 @@ module API
desc: 'The description of the tracker'
}
],
+ 'youtrack' => [
+ {
+ required: true,
+ name: :new_issue_url,
+ type: String,
+ desc: 'The new issue URL'
+ },
+ {
+ required: true,
+ name: :project_url,
+ type: String,
+ desc: 'The project URL'
+ },
+ {
+ required: true,
+ name: :issues_url,
+ type: String,
+ desc: 'The issues URL'
+ },
+ {
+ required: false,
+ name: :description,
+ type: String,
+ desc: 'The description of the tracker'
+ }
+ ],
'slack' => [
CHAT_NOTIFICATION_SETTINGS,
CHAT_NOTIFICATION_FLAGS,
@@ -665,6 +691,7 @@ module API
PrometheusService,
PushoverService,
RedmineService,
+ YoutrackService,
SlackService,
MattermostService,
MicrosoftTeamsService,
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index f7ef34d773b..0efb15337ed 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -313,6 +313,21 @@ FactoryBot.define do
end
end
+ factory :youtrack_project, parent: :project do
+ has_external_issue_tracker true
+
+ after :create do |project|
+ project.create_youtrack_service(
+ active: true,
+ properties: {
+ 'project_url' => 'http://youtrack/projects/project_guid_in_youtrack',
+ 'issues_url' => 'http://youtrack/issues/:id',
+ 'new_issue_url' => 'http://youtrack/newIssue'
+ }
+ )
+ end
+ end
+
factory :jira_project, parent: :project do
has_external_issue_tracker true
jira_service
diff --git a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
index a0270d93d50..e415bbcfc92 100644
--- a/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_issue_reference_filter_spec.rb
@@ -121,6 +121,28 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
end
end
+ context "youtrack project" do
+ let(:project) { create(:youtrack_project) }
+
+ before do
+ project.update!(issues_enabled: false)
+ end
+
+ context "with right markdown" do
+ let(:issue) { ExternalIssue.new("YT-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+
+ context "with a single-letter prefix" do
+ let(:issue) { ExternalIssue.new("T-123", project) }
+ let(:reference) { issue.to_reference }
+
+ it_behaves_like "external issue tracker"
+ end
+ end
+
context "jira project" do
let(:project) { create(:jira_project) }
let(:reference) { issue.to_reference }
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index c15b360b563..46d78b92b21 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -232,6 +232,7 @@ project:
- pushover_service
- jira_service
- redmine_service
+- youtrack_service
- custom_issue_tracker_service
- bugzilla_service
- gitlab_issue_tracker_service
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 1327f414498..773651dd226 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -6630,6 +6630,26 @@
"deploy_keys": [],
"services": [
{
+ "id": 101,
+ "title": "YouTrack",
+ "project_id": 5,
+ "created_at": "2016-06-14T15:01:51.327Z",
+ "updated_at": "2016-06-14T15:01:51.327Z",
+ "active": false,
+ "properties": {},
+ "template": false,
+ "push_events": true,
+ "issues_events": true,
+ "merge_requests_events": true,
+ "tag_push_events": true,
+ "note_events": true,
+ "job_events": true,
+ "type": "YoutrackService",
+ "category": "issue_tracker",
+ "default": false,
+ "wiki_page_events": true
+ },
+ {
"id": 100,
"title": "JetBrains TeamCity CI",
"project_id": 5,
diff --git a/spec/models/project_services/youtrack_service_spec.rb b/spec/models/project_services/youtrack_service_spec.rb
new file mode 100644
index 00000000000..26591b09d0d
--- /dev/null
+++ b/spec/models/project_services/youtrack_service_spec.rb
@@ -0,0 +1,41 @@
+require 'spec_helper'
+
+describe YoutrackService do
+ describe 'Associations' do
+ it { is_expected.to belong_to :project }
+ it { is_expected.to have_one :service_hook }
+ end
+
+ describe 'Validations' do
+ context 'when service is active' do
+ before do
+ subject.active = true
+ end
+
+ it { is_expected.to validate_presence_of(:project_url) }
+ it { is_expected.to validate_presence_of(:issues_url) }
+ it { is_expected.to validate_presence_of(:new_issue_url) }
+ it_behaves_like 'issue tracker service URL attribute', :project_url
+ it_behaves_like 'issue tracker service URL attribute', :issues_url
+ it_behaves_like 'issue tracker service URL attribute', :new_issue_url
+ end
+
+ context 'when service is inactive' do
+ before do
+ subject.active = false
+ end
+
+ it { is_expected.not_to validate_presence_of(:project_url) }
+ it { is_expected.not_to validate_presence_of(:issues_url) }
+ it { is_expected.not_to validate_presence_of(:new_issue_url) }
+ end
+ end
+
+ describe '.reference_pattern' do
+ it_behaves_like 'allows project key on reference pattern'
+
+ it 'does allow project prefix on the reference' do
+ expect(described_class.reference_pattern.match('YT-123')[:issue]).to eq('YK-123')
+ end
+ end
+end