2018-11-20 20:47:30 +05:30
# frozen_string_literal: true
2021-06-08 01:23:25 +05:30
class IssueTrackerService < Integration
2017-08-17 22:00:37 +05:30
validate :one_issue_tracker , if : :activated? , on : :manual_change
2015-04-26 12:48:37 +05:30
2019-12-04 20:38:33 +05:30
# TODO: we can probably just delegate as part of
2019-12-21 20:55:43 +05:30
# https://gitlab.com/gitlab-org/gitlab/issues/29404
2019-12-04 20:38:33 +05:30
data_field :project_url , :issues_url , :new_issue_url
2016-01-29 22:53:50 +05:30
default_value_for :category , 'issue_tracker'
2015-04-26 12:48:37 +05:30
2019-12-04 20:38:33 +05:30
before_validation :handle_properties
before_validation :set_default_data , on : :create
2019-09-30 21:07:59 +05:30
2016-11-03 12:29:30 +05:30
# Pattern used to extract links from comments
# Override this method on services that uses different patterns
2017-08-17 22:00:37 +05:30
# This pattern does not support cross-project references
# The other code assumes that this pattern is a superset of all
2019-02-15 15:39:39 +05:30
# overridden patterns. See ReferenceRegexes.external_pattern
2017-09-10 17:25:29 +05:30
def self . reference_pattern ( only_long : false )
if only_long
2020-04-08 14:13:33 +05:30
/ ( \ b[A-Z][A-Z0-9_]*-) #{ Gitlab :: Regex . issue } /
2017-09-10 17:25:29 +05:30
else
2020-04-08 14:13:33 +05:30
/ ( \ b[A-Z][A-Z0-9_]*-| #{ Issue . reference_prefix } ) #{ Gitlab :: Regex . issue } /
2017-09-10 17:25:29 +05:30
end
2016-11-03 12:29:30 +05:30
end
2019-09-30 21:07:59 +05:30
def handle_properties
2019-12-04 20:38:33 +05:30
# this has been moved from initialize_properties and should be improved
2019-12-21 20:55:43 +05:30
# as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
2019-12-04 20:38:33 +05:30
return unless properties
@legacy_properties_data = properties . dup
data_values = properties . slice! ( 'title' , 'description' )
data_values . reject! { | key | data_fields . changed . include? ( key ) }
2019-12-21 20:55:43 +05:30
data_values . slice! ( * data_fields . attributes . keys )
2019-12-04 20:38:33 +05:30
data_fields . assign_attributes ( data_values ) if data_values . present?
self . properties = { }
end
def legacy_properties_data
@legacy_properties_data || = { }
end
2019-12-21 20:55:43 +05:30
def supports_data_fields?
true
end
2019-12-04 20:38:33 +05:30
def data_fields
issue_tracker_data || self . build_issue_tracker_data
2019-09-30 21:07:59 +05:30
end
2015-04-26 12:48:37 +05:30
def default?
2016-01-29 22:53:50 +05:30
default
2015-04-26 12:48:37 +05:30
end
def issue_url ( iid )
2019-12-04 20:38:33 +05:30
issues_url . gsub ( ':id' , iid . to_s )
2015-04-26 12:48:37 +05:30
end
2017-09-10 17:25:29 +05:30
def issue_tracker_path
2015-04-26 12:48:37 +05:30
project_url
end
def new_issue_path
new_issue_url
end
def issue_path ( iid )
issue_url ( iid )
end
def fields
[
2021-06-08 01:23:25 +05:30
{ type : 'text' , name : 'project_url' , title : _ ( 'Project URL' ) , help : s_ ( 'IssueTracker|The URL to the project in the external issue tracker.' ) , required : true } ,
{ type : 'text' , name : 'issues_url' , title : s_ ( 'IssueTracker|Issue URL' ) , help : s_ ( 'IssueTracker|The URL to view an issue in the external issue tracker. Must contain %{colon_id}.' ) % { colon_id : '<code>:id</code>' . html_safe } , required : true } ,
{ type : 'text' , name : 'new_issue_url' , title : s_ ( 'IssueTracker|New issue URL' ) , help : s_ ( 'IssueTracker|The URL to create an issue in the external issue tracker.' ) , required : true }
2015-04-26 12:48:37 +05:30
]
end
2019-12-04 20:38:33 +05:30
def initialize_properties
{ }
end
2017-08-17 22:00:37 +05:30
# Initialize with default properties values
2019-12-04 20:38:33 +05:30
def set_default_data
return unless issues_tracker . present?
# we don't want to override if we have set something
return if project_url || issues_url || new_issue_url
data_fields . project_url = issues_tracker [ 'project_url' ]
data_fields . issues_url = issues_tracker [ 'issues_url' ]
data_fields . new_issue_url = issues_tracker [ 'new_issue_url' ]
2015-04-26 12:48:37 +05:30
end
2017-08-17 22:00:37 +05:30
def self . supported_events
2015-04-26 12:48:37 +05:30
%w( push )
end
def execute ( data )
return unless supported_events . include? ( data [ :object_kind ] )
message = " #{ self . type } was unable to reach #{ self . project_url } . Check the url and try again. "
result = false
begin
2018-03-26 14:24:53 +05:30
response = Gitlab :: HTTP . head ( self . project_url , verify : true )
2015-04-26 12:48:37 +05:30
2015-09-11 14:41:01 +05:30
if response
message = " #{ self . type } received response #{ response . code } when attempting to connect to #{ self . project_url } "
result = true
2015-04-26 12:48:37 +05:30
end
2018-03-26 14:24:53 +05:30
rescue Gitlab :: HTTP :: Error , Timeout :: Error , SocketError , Errno :: ECONNRESET , Errno :: ECONNREFUSED , OpenSSL :: SSL :: SSLError = > error
2015-04-26 12:48:37 +05:30
message = " #{ self . type } had an error when trying to connect to #{ self . project_url } : #{ error . message } "
end
2018-11-20 20:47:30 +05:30
log_info ( message )
2015-04-26 12:48:37 +05:30
result
end
2020-04-08 14:13:33 +05:30
def support_close_issue?
false
end
def support_cross_reference?
false
end
2015-04-26 12:48:37 +05:30
private
def enabled_in_gitlab_config
Gitlab . config . issues_tracker &&
2017-08-17 22:00:37 +05:30
Gitlab . config . issues_tracker . values . any? &&
issues_tracker
2015-04-26 12:48:37 +05:30
end
def issues_tracker
Gitlab . config . issues_tracker [ to_param ]
end
2017-08-17 22:00:37 +05:30
def one_issue_tracker
2020-04-22 19:07:51 +05:30
return if template? || instance?
2017-08-17 22:00:37 +05:30
return if project . blank?
2021-06-08 01:23:25 +05:30
if project . integrations . external_issue_trackers . where . not ( id : id ) . any?
2020-04-08 14:13:33 +05:30
errors . add ( :base , _ ( 'Another issue tracker is already in use. Only one issue tracker service can be active at a time' ) )
2017-08-17 22:00:37 +05:30
end
end
2015-04-26 12:48:37 +05:30
end
2019-12-04 20:38:33 +05:30
2021-06-08 01:23:25 +05:30
IssueTrackerService . prepend_mod_with ( 'IssueTrackerService' )