summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorDrew Blessing <drew@gitlab.com>2016-01-14 08:20:23 -0600
committerFelipe Artur <felipefac@gmail.com>2016-10-26 15:02:16 -0200
commitf4bc18d237413ac55e32ce16a23b3d2ab35a6976 (patch)
tree0b9cf78efee768bdcaa3a5175199b7475c1188b0 /app
parent2fc359a506b5997cb65b6d5f2f5c85df98fd1c69 (diff)
downloadgitlab-ce-f4bc18d237413ac55e32ce16a23b3d2ab35a6976.tar.gz
Refactor JIRA service to use gem
Diffstat (limited to 'app')
-rw-r--r--app/controllers/concerns/service_params.rb2
-rw-r--r--app/models/project_services/jira_service.rb201
2 files changed, 97 insertions, 106 deletions
diff --git a/app/controllers/concerns/service_params.rb b/app/controllers/concerns/service_params.rb
index 4cb3be41064..c33d7eecb9f 100644
--- a/app/controllers/concerns/service_params.rb
+++ b/app/controllers/concerns/service_params.rb
@@ -18,7 +18,7 @@ module ServiceParams
:add_pusher, :send_from_committer_email, :disable_diffs,
:external_wiki_url, :notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
- :jira_issue_transition_id]
+ :jira_issue_transition_id, :url, :project_key]
# Parameters to ignore if no value is specified
FILTER_BLANK_PARAMS = [:password]
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index f81b66fd219..580adcfba99 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -1,15 +1,35 @@
+# == Schema Information
+#
+# Table name: services
+#
+# id :integer not null, primary key
+# type :string(255)
+# title :string(255)
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# active :boolean default(FALSE), not null
+# properties :text
+# template :boolean default(FALSE)
+# push_events :boolean default(TRUE)
+# issues_events :boolean default(TRUE)
+# merge_requests_events :boolean default(TRUE)
+# tag_push_events :boolean default(TRUE)
+# note_events :boolean default(TRUE), not null
+# build_events :boolean default(FALSE), not null
+#
+require 'jira'
+
class JiraService < IssueTrackerService
include HTTParty
- include Gitlab::Routing.url_helpers
+ include Gitlab::Application.routes.url_helpers
DEFAULT_API_VERSION = 2
- prop_accessor :username, :password, :api_url, :jira_issue_transition_id,
- :title, :description, :project_url, :issues_url, :new_issue_url
-
- validates :api_url, presence: true, url: true, if: :activated?
+ prop_accessor :username, :password, :url, :project_key,
+ :jira_issue_transition_id, :title, :description
- before_validation :set_api_url, :set_jira_issue_transition_id
+ before_validation :set_jira_issue_transition_id
before_update :reset_password
@@ -20,14 +40,34 @@ class JiraService < IssueTrackerService
def reset_password
# don't reset the password if a new one is provided
- if api_url_changed? && !password_touched?
+ if url_changed? && !password_touched?
self.password = nil
end
end
+ def options
+ url = URI.parse(self.url)
+ {
+ :username => self.username,
+ :password => self.password,
+ :site => URI.join(url, '/').to_s,
+ :context_path => url.path,
+ :auth_type => :basic,
+ :read_timeout => 120,
+ :use_ssl => url.scheme == 'https'
+ }
+ end
+
+ def client
+ @client ||= ::JIRA::Client.new(options)
+ end
+
+ def jira_project
+ @jira_project ||= client.Project.find(project_key)
+ end
+
def help
- 'Setting `project_url`, `issues_url` and `new_issue_url` will '\
- 'allow a user to easily navigate to the Jira issue tracker. See the '\
+ 'See the ' \
'[integration doc](http://doc.gitlab.com/ce/integration/external-issue-tracker.html) '\
'for details.'
end
@@ -53,12 +93,25 @@ class JiraService < IssueTrackerService
end
def fields
- super.push(
- { type: 'text', name: 'api_url', placeholder: 'https://jira.example.com/rest/api/2' },
+ [
+ { type: 'text', name: 'url', title: 'URL', placeholder: 'https://jira.example.com' },
+ { type: 'text', name: 'project_key', placeholder: 'PROJ' },
{ type: 'text', name: 'username', placeholder: '' },
{ type: 'password', name: 'password', placeholder: '' },
{ type: 'text', name: 'jira_issue_transition_id', placeholder: '2' }
- )
+ ]
+ end
+
+ def project_url
+ "#{url}/issues/?jql=project=#{project_key}"
+ end
+
+ def issues_url
+ "#{url}/browse/:id"
+ end
+
+ def new_issue_url
+ "#{url}/secure/CreateIssue.jspa"
end
def execute(push, issue = nil)
@@ -72,7 +125,7 @@ class JiraService < IssueTrackerService
end
def create_cross_reference_note(mentioned, noteable, author)
- issue_name = mentioned.id
+ issue_key = mentioned.id
project = self.project
noteable_name = noteable.class.name.underscore.downcase
noteable_id = if noteable.is_a?(Commit)
@@ -94,53 +147,25 @@ class JiraService < IssueTrackerService
},
entity: {
name: noteable_name.humanize.downcase,
- url: entity_url,
- title: noteable.title
+ url: entity_url
}
}
- add_comment(data, issue_name)
+ add_comment(data, issue_key)
end
def test_settings
- return unless api_url.present?
- result = JiraService.get(
- jira_api_test_url,
- headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Basic #{auth}"
- }
- )
+ return unless api_utrl.present?
+ # Test settings by getting the project
+ jira_project
- case result.code
- when 201, 200
- Rails.logger.info("#{self.class.name} SUCCESS #{result.code}: Successfully connected to #{api_url}.")
- true
- else
- Rails.logger.info("#{self.class.name} ERROR #{result.code}: #{result.parsed_response}")
- false
- end
- rescue Errno::ECONNREFUSED => e
- Rails.logger.info "#{self.class.name} ERROR: #{e.message}. API URL: #{api_url}."
+ rescue Errno::ECONNREFUSED, JIRA::HTTPError => e
+ Rails.logger.info "#{self.class.name} Test ERROR: #{url} - #{e.message}"
false
end
private
- def build_api_url_from_project_url
- server = URI(project_url)
- default_ports = [["http", 80], ["https", 443]].include?([server.scheme, server.port])
- server_url = "#{server.scheme}://#{server.host}"
- server_url.concat(":#{server.port}") unless default_ports
- "#{server_url}/rest/api/#{DEFAULT_API_VERSION}"
- rescue
- "" # looks like project URL was not valid
- end
-
- def set_api_url
- self.api_url = build_api_url_from_project_url if self.api_url.blank?
- end
-
def set_jira_issue_transition_id
self.jira_issue_transition_id ||= "2"
end
@@ -149,7 +174,7 @@ class JiraService < IssueTrackerService
commit_id = if entity.is_a?(Commit)
entity.id
elsif entity.is_a?(MergeRequest)
- entity.diff_head_sha
+ entity.last_commit.id
end
commit_url = build_entity_url(:commit, commit_id)
@@ -161,69 +186,47 @@ class JiraService < IssueTrackerService
end
def transition_issue(issue)
- message = {
- transition: {
- id: jira_issue_transition_id
- }
- }
- send_message(close_issue_url(issue.iid), message.to_json)
+ issue = client.Issue.find(issue.iid)
+ issue.transitions.build.save(transition: { id: jira_issue_transition_id })
end
def add_issue_solved_comment(issue, commit_id, commit_url)
- comment = {
- body: "Issue solved with [#{commit_id}|#{commit_url}]."
- }
-
- send_message(comment_url(issue.iid), comment.to_json)
+ comment = "Issue solved with [#{commit_id}|#{commit_url}]."
+ send_message(issue.iid, comment)
end
- def add_comment(data, issue_name)
- url = comment_url(issue_name)
+ def add_comment(data, issue_key)
user_name = data[:user][:name]
user_url = data[:user][:url]
entity_name = data[:entity][:name]
entity_url = data[:entity][:url]
- entity_title = data[:entity][:title]
project_name = data[:project][:name]
- message = {
- body: %Q{[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]:\n'#{entity_title}'}
- }
-
- unless existing_comment?(issue_name, message[:body])
- send_message(url, message.to_json)
- end
- end
+ message = "[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]."
- def auth
- require 'base64'
- Base64.urlsafe_encode64("#{self.username}:#{self.password}")
+ # unless existing_comment?(issue_name, message[:body])
+ send_message(issue_key, message)
+ # end
end
- def send_message(url, message)
+ def send_message(issue_key, message)
return unless api_url.present?
- result = JiraService.post(
- url,
- body: message,
- headers: {
- 'Content-Type' => 'application/json',
- 'Authorization' => "Basic #{auth}"
- }
- )
-
- message = case result.code
- when 201, 200, 204
- "#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}."
- when 401
- "#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again."
- else
- "#{self.class.name} ERROR #{result.code}: #{result.parsed_response}"
- end
+ issue = client.Issue.find(issue_key)
+ issue.comments.build.save!(body: message)
+
+ # message = case result.code
+ # when 201, 200, 204
+ # "#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}."
+ # when 401
+ # "#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again."
+ # else
+ # "#{self.class.name} ERROR #{result.code}: #{result.parsed_response}"
+ # end
Rails.logger.info(message)
message
rescue URI::InvalidURIError, Errno::ECONNREFUSED => e
- Rails.logger.info "#{self.class.name} ERROR: #{e.message}. Hostname: #{url}."
+ Rails.logger.info "#{self.class.name} Send message ERROR: #{url} - #{e.message}"
end
def existing_comment?(issue_name, new_comment)
@@ -267,16 +270,4 @@ class JiraService < IssueTrackerService
)
)
end
-
- def close_issue_url(issue_name)
- "#{self.api_url}/issue/#{issue_name}/transitions"
- end
-
- def comment_url(issue_name)
- "#{self.api_url}/issue/#{issue_name}/comment"
- end
-
- def jira_api_test_url
- "#{self.api_url}/myself"
- end
end