Commit cab34dfb authored by Marin Jankovski's avatar Marin Jankovski

When JIRA issue is mentioned, add a reference comment to the issue.

parent 768bb0a5
...@@ -169,7 +169,9 @@ class Note < ActiveRecord::Base ...@@ -169,7 +169,9 @@ class Note < ActiveRecord::Base
# eg. mentioning a commit in MR comments which exists inside a MR # eg. mentioning a commit in MR comments which exists inside a MR
# should not create "mentioned in" note. # should not create "mentioned in" note.
def cross_reference_disallowed?(noteable, mentioner) def cross_reference_disallowed?(noteable, mentioner)
if mentioner.kind_of?(MergeRequest) if noteable.is_a?(ExternalIssue)
true
elsif mentioner.kind_of?(MergeRequest)
mentioner.commits.map(&:id).include? noteable.id mentioner.commits.map(&:id).include? noteable.id
end end
end end
......
...@@ -36,6 +36,10 @@ class IssueTrackerService < Service ...@@ -36,6 +36,10 @@ class IssueTrackerService < Service
# implement inside child # implement inside child
end end
def create_cross_reference_note
# implement inside child
end
def issue_url(iid) def issue_url(iid)
self.issues_url.gsub(':id', iid.to_s) self.issues_url.gsub(':id', iid.to_s)
end end
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
class JiraService < IssueTrackerService class JiraService < IssueTrackerService
include HTTParty include HTTParty
include Rails.application.routes.url_helpers
prop_accessor :username, :password, :api_version, :jira_issue_transition_id, prop_accessor :username, :password, :api_version, :jira_issue_transition_id,
:title, :description, :project_url, :issues_url, :new_issue_url :title, :description, :project_url, :issues_url, :new_issue_url
...@@ -49,13 +50,29 @@ class JiraService < IssueTrackerService ...@@ -49,13 +50,29 @@ class JiraService < IssueTrackerService
) )
end end
def execute(push, issue = nil) def execute(push, issue = nil)
close_issue(push, issue) if issue close_issue(push, issue) if issue
end end
def create_cross_reference_note def create_cross_reference_note(mentioned, noteable, author, project)
# TODO implement issue_name = mentioned.id
data = {
user: {
name: author.name,
url: resource_url(user_path(author)),
},
project: {
name: project.path_with_namespace,
url: resource_url(project_path(project))
},
entity: {
name: noteable.class.name.underscore.humanize.downcase,
url: resource_url(polymorphic_url([project, noteable], routing_type: :path))
}
}
add_comment(data, issue_name)
end end
private private
...@@ -84,30 +101,72 @@ class JiraService < IssueTrackerService ...@@ -84,30 +101,72 @@ class JiraService < IssueTrackerService
'transition' => { 'transition' => {
'id' => jira_issue_transition_id 'id' => jira_issue_transition_id
} }
} }.to_json
json_body = message.to_json send_message(url, message)
Rails.logger.info("#{self.class.name}: sending POST with body #{json_body} to #{url}") end
JiraService.post( def add_comment(data, issue_name)
url, url = add_comment_url(issue_name)
body: json_body, user_name = data[:user][:name]
headers: { user_url = data[:user][:url]
'Content-Type' => 'application/json', entity_name = data[:entity][:name]
'Authorization' => "Basic #{auth}" entity_url = data[:entity][:url]
} entity_iid = data[:entity][:iid]
) project_name = data[:project][:name]
project_url = data[:project][:url]
message = {
body: "[#{user_name}|#{user_url}] mentioned #{issue_name} in #{entity_name} of [#{project_name}|#{entity_url}]."
}.to_json
send_message(url, message)
end end
def close_issue_url(issue_name) def close_issue_url(issue_name)
"#{server_url}/rest/api/#{self.api_version}/issue/#{issue_name}/transitions" "#{server_url}/rest/api/#{self.api_version}/issue/#{issue_name}/transitions"
end end
def add_comment_url(issue_name)
"#{server_url}/rest/api/#{self.api_version}/issue/#{issue_name}/comment"
end
def auth def auth
require 'base64' require 'base64'
Base64.urlsafe_encode64("#{self.username}:#{self.password}") Base64.urlsafe_encode64("#{self.username}:#{self.password}")
end end
def send_message(url, message)
begin
result = JiraService.post(
url,
body: message,
headers: {
'Content-Type' => 'application/json',
'Authorization' => "Basic #{auth}"
}
)
rescue URI::InvalidURIError => e
result = e.message
end
message = if result.is_a?(String)
"#{self.class.name} ERROR: #{result}. Hostname: #{url}."
else
case result.code
when 201
"#{self.class.name} SUCCESS 201: Sucessfully 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
end
Rails.logger.info(message)
message
end
def server_url def server_url
server = URI(project_url) server = URI(project_url)
default_ports = [80, 443].include?(server.port) default_ports = [80, 443].include?(server.port)
...@@ -115,4 +174,8 @@ class JiraService < IssueTrackerService ...@@ -115,4 +174,8 @@ class JiraService < IssueTrackerService
server_url.concat(":#{server.port}") unless default_ports server_url.concat(":#{server.port}") unless default_ports
return server_url return server_url
end end
def resource_url(resource)
"#{Settings.gitlab['url'].chomp("/")}#{resource}"
end
end end
...@@ -16,7 +16,7 @@ module Notes ...@@ -16,7 +16,7 @@ module Notes
# issue, merge request, or commit. # issue, merge request, or commit.
note.references.each do |mentioned| note.references.each do |mentioned|
if mentioned.is_a?(ExternalIssue) if mentioned.is_a?(ExternalIssue)
note.project.issues_tracker.create_cross_reference_note note.project.issues_tracker.create_cross_reference_note(mentioned, note.noteable, note.author, note.project)
else else
Note.create_cross_reference_note(mentioned, note.noteable, note.author, note.project) Note.create_cross_reference_note(mentioned, note.noteable, note.author, note.project)
end end
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
- elsif type == 'select' - elsif type == 'select'
= f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" } = f.select name, options_for_select(choices, value ? value : default_choice), {}, { class: "form-control" }
- elsif type == 'password' - elsif type == 'password'
= f.password_field name, value: value, class: 'form-control' = f.password_field name, placeholder: value, class: 'form-control'
.form-actions .form-actions
= f.submit 'Save', class: 'btn btn-save' = f.submit 'Save', class: 'btn btn-save'
......
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