Commit 85515aae09ce10cb32ad8e442096c554ecd6b438
Exists in
master
and in
1 other branch
Merge pull request #516 from xenji-feature/jira-issue-tracker
Conflicts: Gemfile.lock
Showing
9 changed files
with
143 additions
and
0 deletions
Show diff stats
Gemfile
| ... | ... | @@ -50,6 +50,9 @@ gem 'bitbucket_rest_api', :require => false |
| 50 | 50 | gem "taskmapper", "~> 0.8.0" |
| 51 | 51 | gem "taskmapper-unfuddle", "~> 0.7.0" |
| 52 | 52 | |
| 53 | +# Jira | |
| 54 | +gem 'jira-ruby', :require => 'jira' | |
| 55 | + | |
| 53 | 56 | # Notification services |
| 54 | 57 | # --------------------------------------- |
| 55 | 58 | # Campfire ( We can't upgrade to 1.0 because drop support of ruby 1.8 | ... | ... |
Gemfile.lock
| ... | ... | @@ -151,6 +151,10 @@ GEM |
| 151 | 151 | multi_xml (>= 0.5.2) |
| 152 | 152 | httpauth (0.2.0) |
| 153 | 153 | i18n (0.6.1) |
| 154 | + jira-ruby (0.1.2) | |
| 155 | + activesupport | |
| 156 | + oauth | |
| 157 | + railties | |
| 154 | 158 | journey (1.0.4) |
| 155 | 159 | jquery-rails (2.1.4) |
| 156 | 160 | railties (>= 3.0, < 5.0) |
| ... | ... | @@ -204,6 +208,7 @@ GEM |
| 204 | 208 | nokogiri (1.5.10) |
| 205 | 209 | nokogiri-happymapper (0.5.7) |
| 206 | 210 | nokogiri (~> 1.5) |
| 211 | + oauth (0.4.7) | |
| 207 | 212 | oauth2 (0.8.1) |
| 208 | 213 | faraday (~> 0.8) |
| 209 | 214 | httpauth (~> 0.1) |
| ... | ... | @@ -407,6 +412,7 @@ DEPENDENCIES |
| 407 | 412 | hoptoad_notifier (~> 2.4) |
| 408 | 413 | htmlentities |
| 409 | 414 | httparty |
| 415 | + jira-ruby | |
| 410 | 416 | jquery-rails (~> 2.1.4) |
| 411 | 417 | kaminari (>= 0.14.1) |
| 412 | 418 | launchy | ... | ... |
1.97 KB
1.97 KB
1.97 KB
1.91 KB
app/models/issue_tracker.rb
| ... | ... | @@ -17,6 +17,14 @@ class IssueTracker |
| 17 | 17 | field :subdomain, :type => String |
| 18 | 18 | field :milestone_id, :type => String |
| 19 | 19 | |
| 20 | + # Is there any better way to enhance the props? Putting them into the subclass leads to | |
| 21 | + # an error while rendering the form fields -.- | |
| 22 | + field :base_url, :type => String | |
| 23 | + field :context_path, :type => String | |
| 24 | + field :issue_type, :type => String | |
| 25 | + field :issue_component, :type => String | |
| 26 | + field :issue_priority, :type => String | |
| 27 | + | |
| 20 | 28 | validate :check_params |
| 21 | 29 | |
| 22 | 30 | # Subclasses are responsible for overwriting this method. | ... | ... |
| ... | ... | @@ -0,0 +1,109 @@ |
| 1 | +if defined? JIRA | |
| 2 | + class IssueTrackers::JiraTracker < IssueTracker | |
| 3 | + Label = 'jira' | |
| 4 | + | |
| 5 | + Fields = [ | |
| 6 | + [:base_url, { | |
| 7 | + :label => 'Jira URL without trailing slash', | |
| 8 | + :placeholder => 'https://jira.example.org/' | |
| 9 | + }], | |
| 10 | + [:context_path, { | |
| 11 | + :optional => true, | |
| 12 | + :label => 'Context Path (Just "/" if empty otherwise with leading slash)', | |
| 13 | + :placeholder => "/jira" | |
| 14 | + }], | |
| 15 | + [:username, { | |
| 16 | + :optional => true, | |
| 17 | + :label => 'HTTP Basic Auth User', | |
| 18 | + :placeholder => 'johndoe' | |
| 19 | + }], | |
| 20 | + [:password, { | |
| 21 | + :optional => true, | |
| 22 | + :label => 'HTTP Basic Auth Password', | |
| 23 | + :placeholder => 'p@assW0rd' | |
| 24 | + }], | |
| 25 | + [:project_id, { | |
| 26 | + :label => 'Project Key', | |
| 27 | + :placeholder => 'The project Key where the issue will be created' | |
| 28 | + }], | |
| 29 | + [:account, { | |
| 30 | + :optional => true, | |
| 31 | + :label => 'Assign to this user. If empty, Jira takes the project default.', | |
| 32 | + :placeholder => "username" | |
| 33 | + }], | |
| 34 | + [:issue_component, { | |
| 35 | + :label => 'Issue category', | |
| 36 | + :placeholder => 'Website - Other' | |
| 37 | + }], | |
| 38 | + [:issue_type, { | |
| 39 | + :label => 'Issue type', | |
| 40 | + :placeholder => 'Bug' | |
| 41 | + }], | |
| 42 | + [:issue_priority, { | |
| 43 | + :label => 'Priority', | |
| 44 | + :placeholder => 'Normal' | |
| 45 | + }] | |
| 46 | + ] | |
| 47 | + | |
| 48 | + def check_params | |
| 49 | + if Fields.detect { |f| self[f[0]].blank? && !f[1][:optional] } | |
| 50 | + errors.add :base, 'You must specify all non optional values!' | |
| 51 | + end | |
| 52 | + end | |
| 53 | + | |
| 54 | + | |
| 55 | + # | |
| 56 | + # @param problem Problem | |
| 57 | + def create_issue(problem, reported_by = nil) | |
| 58 | + options = { | |
| 59 | + :username => username, | |
| 60 | + :password => password, | |
| 61 | + :site => base_url, | |
| 62 | + :context_path => context_path, | |
| 63 | + :auth_type => :basic | |
| 64 | + } | |
| 65 | + client = JIRA::Client.new(options) | |
| 66 | + | |
| 67 | + issue = { | |
| 68 | + :fields => { | |
| 69 | + :project => { | |
| 70 | + :key => project_id | |
| 71 | + }, | |
| 72 | + :summary => issue_title(problem), | |
| 73 | + :description => body_template.result(binding), | |
| 74 | + :issuetype => { | |
| 75 | + :name => issue_type | |
| 76 | + }, | |
| 77 | + :priority => { | |
| 78 | + :name => issue_priority, | |
| 79 | + }, | |
| 80 | + | |
| 81 | + :components => [{:name => issue_component}] | |
| 82 | + } | |
| 83 | + } | |
| 84 | + | |
| 85 | + issue[:fields][:assignee] = {:name => account} if account | |
| 86 | + | |
| 87 | + issue_build = client.Issue.build | |
| 88 | + issue_build.save(issue) | |
| 89 | + issue_build.fetch | |
| 90 | + | |
| 91 | + problem.update_attributes( | |
| 92 | + :issue_link => "#{base_url}#{context_path}browse/#{issue_build.key}", | |
| 93 | + :issue_type => Label | |
| 94 | + ) | |
| 95 | + | |
| 96 | + # Maybe in a later version? | |
| 97 | + #remote_link = { | |
| 98 | + # :url => app_problem_url(problem.app, problem), | |
| 99 | + # :name => "Link to Errbit Issue" | |
| 100 | + #} | |
| 101 | + #remote_link_build = issue_build.remotelink.build | |
| 102 | + #remote_link_build.save(remote_link) | |
| 103 | + end | |
| 104 | + | |
| 105 | + def body_template | |
| 106 | + @@body_template ||= ERB.new(File.read(Rails.root + "app/views/issue_trackers/jira_body.txt.erb")) | |
| 107 | + end | |
| 108 | + end | |
| 109 | +end | |
| 0 | 110 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | +<% if notice = problem.notices.first %> | |
| 2 | +h2. Summary | |
| 3 | +<% if notice.request['url'].present? %> | |
| 4 | +h3. URL | |
| 5 | + | |
| 6 | +"<%= notice.request['url'] %>":<%= notice.request['url'] %> | |
| 7 | +<% end %> | |
| 8 | +h3. Where | |
| 9 | + | |
| 10 | +<%= notice.where %> | |
| 11 | + | |
| 12 | +h3. When | |
| 13 | + | |
| 14 | +<%= notice.created_at.to_s(:micro) %> | |
| 15 | + | |
| 16 | +"More Details on Errbit":<%= app_problem_url problem.app, problem %> | |
| 17 | +<% end %> | |
| 0 | 18 | \ No newline at end of file | ... | ... |