PageRenderTime 71ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/services/you_track.rb

https://gitlab.com/Rockyspade/github-services
Ruby | 155 lines | 123 code | 28 blank | 4 comment | 15 complexity | 67ac82874c05bdd783328ac9825ec22b MD5 | raw file
  1. class Service::YouTrack < Service
  2. string :base_url, :committers, :username, :branch
  3. boolean :process_distinct
  4. password :password
  5. white_list :base_url, :username, :committers, :branch
  6. default_events :push, :pull_request
  7. url 'http://http://www.jetbrains.com/youtrack'
  8. logo_url 'http://www.jetbrains.com/img/logos/YouTrack_logo_press_materials.gif'
  9. maintained_by :github => 'anna239'
  10. supported_by :web => 'http://www.jetbrains.com/support/youtrack',
  11. :email => 'youtrack-feedback@jetbrains.com',
  12. :twitter => 'youtrack'
  13. def receive_push
  14. # If branch is defined by user setting, process commands only if commits
  15. # are on that branch. If branch is not defined, process regardless of branch.
  16. return unless active_branch?
  17. http.ssl[:verify] = false
  18. http.url_prefix = data['base_url']
  19. payload['commits'].each { |c| process_commit(c) }
  20. end
  21. def receive_pull_request
  22. return unless payload['action'] == 'closed'
  23. http.ssl[:verify] = false
  24. http.url_prefix = data['base_url']
  25. process_pull_request
  26. end
  27. def active_branch?
  28. pushed_branch = payload['ref'].to_s[/refs\/heads\/(.*)/, 1]
  29. active_branch = data['branch'].to_s
  30. active_branch.empty? or active_branch.split(' ').include?(pushed_branch)
  31. end
  32. def login
  33. @logged_in ||= begin
  34. api_key = data['api_key']
  35. if api_key.nil?
  36. res = http_post 'rest/user/login' do |req|
  37. req.params.update \
  38. :login => data['username'],
  39. :password => data['password']
  40. req.headers['Content-Length'] = '0'
  41. end
  42. verify_response(res)
  43. http.headers['Cookie'] = res.headers['set-cookie']
  44. else
  45. http.headers['X-YouTrack-ApiKey'] = api_key
  46. end
  47. http.headers['Cache-Control'] = 'no-cache'
  48. true
  49. end
  50. end
  51. def process_commit(commit)
  52. author = nil
  53. #If only distinct commits should be processed, check this
  54. return unless commit['distinct'] or config_boolean_false?('process_distinct')
  55. commit['message'].split("\n").each { |commit_line|
  56. issue_id, command = parse_message(commit_line)
  57. next if issue_id.nil?
  58. login
  59. # lazily load author
  60. author ||= find_user_by_email(commit['author']['email'])
  61. return if author.nil?
  62. command = 'comment' if command.nil?
  63. comment_string = "Commit made by '''" + commit['author']['name'] + "''' on ''" + commit['timestamp'] + "''\n" + commit['url'] + "\n\n{quote}" + commit['message'].to_s + '{quote}'
  64. execute_command(author, issue_id, command, comment_string)
  65. }
  66. end
  67. def process_pull_request
  68. login
  69. sender = payload['sender']
  70. author = find_user_by_email(sender['email'])
  71. return if author.nil?
  72. request = payload['pull_request']
  73. request['body'].split("\n").each { |line|
  74. issue_id, command = parse_message(line)
  75. next if issue_id.nil?
  76. comment = "Pull request accepted by '''" + sender['login'] + "'''\n" + request['html_url'] + "\n\n{quote}" + request['body'].to_s + '{quote}'
  77. execute_command(author, issue_id, command, comment)
  78. }
  79. end
  80. def find_user_by_email(email)
  81. counter = 0
  82. found_user = nil
  83. while true
  84. body = ''
  85. res = http_get 'rest/admin/user', :q => email, :group => data['committers'], :start => counter
  86. verify_response(res)
  87. xml_body = REXML::Document.new(res.body)
  88. xml_body.root.each_element do |user_ref|
  89. res = http_get "rest/admin/user/#{user_ref.attributes['login']}"
  90. verify_response(res)
  91. attributes = REXML::Document.new(res.body).root.attributes
  92. if attributes['email'].upcase == email.upcase || (attributes['jabber'] ? attributes['jabber'].upcase == email.upcase : false)
  93. return if !found_user.nil?
  94. found_user = user_ref.attributes['login']
  95. end
  96. end
  97. return found_user if xml_body.root.elements.size < 10
  98. counter += 10
  99. end
  100. end
  101. def execute_command(author, issue_id, command, comment_string)
  102. res = http_post "rest/issue/#{issue_id}/execute" do |req|
  103. req.params[:command] = command unless command.nil?
  104. req.params[:comment] = comment_string
  105. req.params[:runAs] = author
  106. end
  107. verify_response(res)
  108. end
  109. def verify_response(res)
  110. case res.status
  111. when 200..299
  112. when 403, 401, 422 then
  113. raise_config_error('Invalid Credentials')
  114. when 404, 301, 302 then
  115. raise_config_error('Invalid YouTrack URL')
  116. else
  117. raise_config_error("HTTP: #{res.status}")
  118. end
  119. end
  120. def parse_message(message)
  121. issue_id = message[/( |^)#(\w+-\d+)\b/, 2]
  122. return nil, nil if issue_id.nil?
  123. command = message[/( |^)#\w+-\d+ (.+)/, 2]
  124. command.strip! unless command.nil?
  125. return issue_id, command
  126. end
  127. end