Commit f4f7de6dbc0e3045d2e49d43264eb95268075d1f
1 parent
fa4c7f79
Exists in
master
and in
1 other branch
got the issue tracker fogbugz integration mostly working
Showing
11 changed files
with
109 additions
and
28 deletions
Show diff stats
Gemfile
@@ -2,7 +2,7 @@ source 'http://rubygems.org' | @@ -2,7 +2,7 @@ source 'http://rubygems.org' | ||
2 | 2 | ||
3 | gem 'rails', '3.0.5' | 3 | gem 'rails', '3.0.5' |
4 | gem 'nokogiri' | 4 | gem 'nokogiri' |
5 | -gem 'mongoid', '2.0.0.rc.8' | 5 | +gem 'mongoid', '2.0.2' |
6 | gem 'haml' | 6 | gem 'haml' |
7 | gem 'will_paginate' | 7 | gem 'will_paginate' |
8 | gem 'devise', '~> 1.1.8' | 8 | gem 'devise', '~> 1.1.8' |
Gemfile.lock
@@ -45,7 +45,7 @@ GEM | @@ -45,7 +45,7 @@ GEM | ||
45 | addressable (2.2.5) | 45 | addressable (2.2.5) |
46 | arel (2.0.9) | 46 | arel (2.0.9) |
47 | bcrypt-ruby (2.1.4) | 47 | bcrypt-ruby (2.1.4) |
48 | - bson (1.3.0) | 48 | + bson (1.3.1) |
49 | bson_ext (1.3.0) | 49 | bson_ext (1.3.0) |
50 | builder (2.1.2) | 50 | builder (2.1.2) |
51 | crack (0.1.8) | 51 | crack (0.1.8) |
@@ -78,13 +78,12 @@ GEM | @@ -78,13 +78,12 @@ GEM | ||
78 | mime-types (~> 1.16) | 78 | mime-types (~> 1.16) |
79 | treetop (~> 1.4.8) | 79 | treetop (~> 1.4.8) |
80 | mime-types (1.16) | 80 | mime-types (1.16) |
81 | - mongo (1.3.0) | ||
82 | - bson (>= 1.3.0) | ||
83 | - mongoid (2.0.0.rc.8) | 81 | + mongo (1.3.1) |
82 | + bson (>= 1.3.1) | ||
83 | + mongoid (2.0.2) | ||
84 | activemodel (~> 3.0) | 84 | activemodel (~> 3.0) |
85 | - mongo (~> 1.2) | 85 | + mongo (~> 1.3) |
86 | tzinfo (~> 0.3.22) | 86 | tzinfo (~> 0.3.22) |
87 | - will_paginate (~> 3.0.pre) | ||
88 | mongoid_rails_migrations (0.0.10) | 87 | mongoid_rails_migrations (0.0.10) |
89 | activesupport (~> 3.0.0) | 88 | activesupport (~> 3.0.0) |
90 | bundler (>= 0.9.19) | 89 | bundler (>= 0.9.19) |
@@ -161,7 +160,7 @@ DEPENDENCIES | @@ -161,7 +160,7 @@ DEPENDENCIES | ||
161 | factory_girl_rails | 160 | factory_girl_rails |
162 | haml | 161 | haml |
163 | lighthouse-api | 162 | lighthouse-api |
164 | - mongoid (= 2.0.0.rc.8) | 163 | + mongoid (= 2.0.2) |
165 | mongoid_rails_migrations | 164 | mongoid_rails_migrations |
166 | nokogiri | 165 | nokogiri |
167 | pivotal-tracker | 166 | pivotal-tracker |
app/helpers/application_helper.rb
@@ -42,4 +42,8 @@ module ApplicationHelper | @@ -42,4 +42,8 @@ module ApplicationHelper | ||
42 | def pivotal_tracker? object | 42 | def pivotal_tracker? object |
43 | object.issue_tracker_type == "pivotal" | 43 | object.issue_tracker_type == "pivotal" |
44 | end | 44 | end |
45 | + | ||
46 | + def fogbugz_tracker? object | ||
47 | + object.issue_tracker_type == 'fogbugz' | ||
48 | + end | ||
45 | end | 49 | end |
app/models/app.rb
@@ -21,7 +21,7 @@ class App | @@ -21,7 +21,7 @@ class App | ||
21 | embeds_many :watchers | 21 | embeds_many :watchers |
22 | embeds_many :deploys | 22 | embeds_many :deploys |
23 | embeds_one :issue_tracker | 23 | embeds_one :issue_tracker |
24 | - references_many :errs, :dependent => :destroy | 24 | + has_many :errs, :dependent => :destroy |
25 | 25 | ||
26 | before_validation :generate_api_key, :on => :create | 26 | before_validation :generate_api_key, :on => :create |
27 | before_save :normalize_github_url | 27 | before_save :normalize_github_url |
@@ -35,7 +35,7 @@ class App | @@ -35,7 +35,7 @@ class App | ||
35 | accepts_nested_attributes_for :watchers, :allow_destroy => true, | 35 | accepts_nested_attributes_for :watchers, :allow_destroy => true, |
36 | :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } | 36 | :reject_if => proc { |attrs| attrs[:user_id].blank? && attrs[:email].blank? } |
37 | accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, | 37 | accepts_nested_attributes_for :issue_tracker, :allow_destroy => true, |
38 | - :reject_if => proc { |attrs| !%w(lighthouseapp redmine pivotal).include?(attrs[:issue_tracker_type]) } | 38 | + :reject_if => proc { |attrs| !%w(lighthouseapp redmine pivotal fogbugz).include?(attrs[:issue_tracker_type]) } |
39 | 39 | ||
40 | # Mongoid Bug: find(id) on association proxies returns an Enumerator | 40 | # Mongoid Bug: find(id) on association proxies returns an Enumerator |
41 | def self.find_by_id!(app_id) | 41 | def self.find_by_id!(app_id) |
app/models/err.rb
@@ -16,8 +16,8 @@ class Err | @@ -16,8 +16,8 @@ class Err | ||
16 | index :last_notice_at | 16 | index :last_notice_at |
17 | index :app_id | 17 | index :app_id |
18 | 18 | ||
19 | - referenced_in :app | ||
20 | - references_many :notices | 19 | + belongs_to :app, inverse_of: :errs |
20 | + has_many :notices | ||
21 | 21 | ||
22 | validates_presence_of :klass, :environment | 22 | validates_presence_of :klass, :environment |
23 | 23 |
app/models/issue_tracker.rb
@@ -12,6 +12,8 @@ class IssueTracker | @@ -12,6 +12,8 @@ class IssueTracker | ||
12 | field :account, :type => String | 12 | field :account, :type => String |
13 | field :api_token, :type => String | 13 | field :api_token, :type => String |
14 | field :project_id, :type => String | 14 | field :project_id, :type => String |
15 | + field :username, :type => String | ||
16 | + field :password, :type => String | ||
15 | field :issue_tracker_type, :type => String, :default => 'lighthouseapp' | 17 | field :issue_tracker_type, :type => String, :default => 'lighthouseapp' |
16 | 18 | ||
17 | def create_issue err | 19 | def create_issue err |
@@ -68,18 +70,20 @@ class IssueTracker | @@ -68,18 +70,20 @@ class IssueTracker | ||
68 | end | 70 | end |
69 | 71 | ||
70 | def create_fogbugz_issue err | 72 | def create_fogbugz_issue err |
71 | - fogbugz = Fogbugz::Interface.new(:email => email, :password => password, :uri => uri) | ||
72 | - fogbugz.account = account | ||
73 | - fogbugz.token = api_token | 73 | + fogbugz = Fogbugz::Interface.new(:email => username, :password => password, :uri => "https://#{account}.fogbugz.com") |
74 | + fogbugz.authenticate | ||
74 | 75 | ||
75 | issue = {} | 76 | issue = {} |
76 | issue['sTitle'] = issue_title err | 77 | issue['sTitle'] = issue_title err |
77 | - issue['sProject'] = project_id | 78 | + issue['sArea'] = project_id |
79 | + puts err.app.inspect | ||
80 | + puts app_err_url(err.app, err) | ||
78 | issue['sEvent'] = self.class.fogbugz_body_template.result(binding) | 81 | issue['sEvent'] = self.class.fogbugz_body_template.result(binding) |
79 | - issue['sTags'] << 'errbit' | 82 | + issue['sTags'] = ['errbit'].join(',') |
83 | + issue['cols'] = ['ixBug'].join(',') | ||
80 | 84 | ||
81 | - fogbugz.command( | ||
82 | - # err.update_attribute :issue_link, "#{FogBugz::Issue.site.to_s.sub(/#{FogBugz::Issue.site.path}$/, '')}#{FogBugz::Issue.element_path(issue.id, :project => project_id}".sub(/\.xml$/, '') | 85 | + # fb_resp = fogbugz.command(:new, issue) |
86 | + # err.update_attribute :issue_link, "https://#{account}.fogbugz.com/default.asp?#{fb_resp['case']['ixBug']}" | ||
83 | end | 87 | end |
84 | 88 | ||
85 | def issue_title err | 89 | def issue_title err |
@@ -87,19 +91,24 @@ class IssueTracker | @@ -87,19 +91,24 @@ class IssueTracker | ||
87 | end | 91 | end |
88 | 92 | ||
89 | def check_params | 93 | def check_params |
90 | - blank_flag_fields = %w(api_token project_id) | ||
91 | - blank_flag_fields << 'account' if %w(lighthouseapp redmine).include? issue_tracker_type | 94 | + blank_flag_fields = %w(project_id) |
95 | + if(%w(fogbugz).include?(issue_tracker_type)) | ||
96 | + blank_flag_fields += %w(username password) | ||
97 | + else | ||
98 | + blank_flag_fields << 'api_token' | ||
99 | + end | ||
100 | + blank_flag_fields << 'account' if(%w(fogbugz lighthouseapp redmine).include?(issue_tracker_type)) | ||
92 | blank_flags = blank_flag_fields.map {|m| self[m].blank? } | 101 | blank_flags = blank_flag_fields.map {|m| self[m].blank? } |
93 | if blank_flags.any? && !blank_flags.all? | 102 | if blank_flags.any? && !blank_flags.all? |
94 | message = case issue_tracker_type | 103 | message = case issue_tracker_type |
95 | when 'lighthouseapp' | 104 | when 'lighthouseapp' |
96 | - "You must specify your Lighthouseapp account, api token and project id" | 105 | + 'You must specify your Lighthouseapp account, api token and project id' |
97 | when 'redmine' | 106 | when 'redmine' |
98 | - "You must specify your Redmine url, api token and project id" | 107 | + 'You must specify your Redmine url, api token and project id' |
99 | when 'pivotal' | 108 | when 'pivotal' |
100 | - "You must specify your Pivotal Tracker api token and project id" | 109 | + 'You must specify your Pivotal Tracker api token and project id' |
101 | when 'fogbugz' | 110 | when 'fogbugz' |
102 | - "You must specify your FogBugz account, project id, username, and password" | 111 | + 'You must specify your FogBugz Area Name, Username, and Password' |
103 | end | 112 | end |
104 | errors.add(:base, message) | 113 | errors.add(:base, message) |
105 | end | 114 | end |
app/models/notice.rb
@@ -11,7 +11,7 @@ class Notice | @@ -11,7 +11,7 @@ class Notice | ||
11 | field :request, :type => Hash | 11 | field :request, :type => Hash |
12 | field :notifier, :type => Hash | 12 | field :notifier, :type => Hash |
13 | 13 | ||
14 | - referenced_in :err | 14 | + belongs_to :err |
15 | index :err_id | 15 | index :err_id |
16 | 16 | ||
17 | after_create :cache_last_notice_at | 17 | after_create :cache_last_notice_at |
app/views/apps/_fields.html.haml
@@ -45,13 +45,15 @@ | @@ -45,13 +45,15 @@ | ||
45 | = label_tag :issue_tracker_type_redmine, 'Redmine', :for => label_for_attr(w, 'issue_tracker_type_redmine') | 45 | = label_tag :issue_tracker_type_redmine, 'Redmine', :for => label_for_attr(w, 'issue_tracker_type_redmine') |
46 | = w.radio_button :issue_tracker_type, :pivotal | 46 | = w.radio_button :issue_tracker_type, :pivotal |
47 | = label_tag :issue_tracker_type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'issue_tracker_type_pivotal') | 47 | = label_tag :issue_tracker_type_pivotal, 'Pivotal Tracker', :for => label_for_attr(w, 'issue_tracker_type_pivotal') |
48 | + = w.radio_button :issue_tracker_type, :fogbugz | ||
49 | + = label_tag :issue_tracker_type_fogbugz, 'FogBugz', :for => label_for_attr(w, 'issue_tracker_type_fogbugz') | ||
48 | %div.tracker_params.lighthouseapp{:class => lighthouse_tracker?(w.object) ? 'chosen' : nil} | 50 | %div.tracker_params.lighthouseapp{:class => lighthouse_tracker?(w.object) ? 'chosen' : nil} |
49 | = w.label :account, "Account" | 51 | = w.label :account, "Account" |
50 | = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com" | 52 | = w.text_field :account, :placeholder => "abc from abc.lighthouseapp.com" |
51 | = w.label :api_token, "API token" | 53 | = w.label :api_token, "API token" |
52 | = w.text_field :api_token, :placeholder => "API Token for your account" | 54 | = w.text_field :api_token, :placeholder => "API Token for your account" |
53 | = w.label :project_id, "Project ID" | 55 | = w.label :project_id, "Project ID" |
54 | - = w.text_field :project_id, :placeholder => "123 from abc from abc.lighthouseapp.com/projects/123" | 56 | + = w.text_field :project_id, :placeholder => "123 from abc.lighthouseapp.com/projects/123" |
55 | %div.tracker_params.redmine{:class => redmine_tracker?(w.object) ? 'chosen' : nil} | 57 | %div.tracker_params.redmine{:class => redmine_tracker?(w.object) ? 'chosen' : nil} |
56 | = w.label :account, "Redmine URL" | 58 | = w.label :account, "Redmine URL" |
57 | = w.text_field :account, :placeholder => "like http://www.redmine.org/" | 59 | = w.text_field :account, :placeholder => "like http://www.redmine.org/" |
@@ -64,3 +66,12 @@ | @@ -64,3 +66,12 @@ | ||
64 | = w.text_field :project_id | 66 | = w.text_field :project_id |
65 | = w.label :api_token, "API token" | 67 | = w.label :api_token, "API token" |
66 | = w.text_field :api_token, :placeholder => "API Token for your account" | 68 | = w.text_field :api_token, :placeholder => "API Token for your account" |
69 | + %div.tracker_params.fogbugz{:class => fogbugz_tracker?(w.object) ? 'chosen' : nil} | ||
70 | + = w.label :project_id, "Area Name" | ||
71 | + = w.text_field :project_id | ||
72 | + = w.label :account, "FogBugz URL" | ||
73 | + = w.text_field :account, :placeholder => "abc from http://abc.fogbugz.com/" | ||
74 | + = w.label :username, 'account username' | ||
75 | + = w.text_field :username, :placeholder => 'Username/Email for your account' | ||
76 | + = w.label :password, 'account password' | ||
77 | + = w.password_field :password, :placeholder => 'Password for your account' |
@@ -0,0 +1,31 @@ | @@ -0,0 +1,31 @@ | ||
1 | +"See this exception on Errbit": <%= app_err_url(err.app, err) %> | ||
2 | +<% if notice = err.notices.first %> | ||
3 | + <%= notice.message %> | ||
4 | + | ||
5 | + Summary | ||
6 | + - Where | ||
7 | + <%= notice.err.where %> | ||
8 | + | ||
9 | + - Occured | ||
10 | + <%= notice.created_at.to_s(:micro) %> | ||
11 | + | ||
12 | + - Similar | ||
13 | + <%= (notice.err.notices_count - 1).to_s %> | ||
14 | + | ||
15 | + Params | ||
16 | + <%= pretty_hash(notice.params) %> | ||
17 | + | ||
18 | + Session | ||
19 | + <%= pretty_hash(notice.session) %> | ||
20 | + | ||
21 | + Backtrace | ||
22 | + <% for line in notice.backtrace %> | ||
23 | + <%= line['number'] %>: <%= line['file'].sub(/^\[PROJECT_ROOT\]/, '') %> | ||
24 | + <% end %> | ||
25 | + | ||
26 | + Environment | ||
27 | + <% for key, val in notice.env_vars %> | ||
28 | + <%= key %>: <%= val %> | ||
29 | + <% end %> | ||
30 | +<% end %> | ||
31 | + |
public/stylesheets/application.css
@@ -507,7 +507,7 @@ a.button.active { | @@ -507,7 +507,7 @@ a.button.active { | ||
507 | } | 507 | } |
508 | 508 | ||
509 | /* Watchers and Issue Tracker Forms */ | 509 | /* Watchers and Issue Tracker Forms */ |
510 | -div.nested.watcher .user, div.nested.watcher .email, div.issue_tracker.nested .lighthouseapp, div.issue_tracker.nested .redmine, div.issue_tracker.nested .pivotal { | 510 | +div.nested.watcher .user, div.nested.watcher .email, div.issue_tracker.nested .lighthouseapp, div.issue_tracker.nested .redmine, div.issue_tracker.nested .pivotal, div.issue_tracker.nested .fogbugz { |
511 | display: none; | 511 | display: none; |
512 | } | 512 | } |
513 | div.nested.watcher .choosen, div.nested.issue_tracker .chosen { | 513 | div.nested.watcher .choosen, div.nested.issue_tracker .chosen { |
spec/controllers/apps_controller_spec.rb
@@ -261,6 +261,33 @@ describe AppsController do | @@ -261,6 +261,33 @@ describe AppsController do | ||
261 | response.body.should match(/You must specify your Pivotal Tracker api token and project id/) | 261 | response.body.should match(/You must specify your Pivotal Tracker api token and project id/) |
262 | end | 262 | end |
263 | end | 263 | end |
264 | + | ||
265 | + context "fogbugz" do | ||
266 | + context 'with correct params' do | ||
267 | + before do | ||
268 | + put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | ||
269 | + :issue_tracker_type => 'fogbugz', :project_id => 'Service - Peon', :username => '1234', :password => '123123' } } | ||
270 | + @app.reload | ||
271 | + end | ||
272 | + | ||
273 | + subject {@app.issue_tracker} | ||
274 | + its(:issue_tracker_type) {should == 'fogbugz'} | ||
275 | + its(:project_id) {should == 'Service - Peon'} | ||
276 | + its(:username) {should == '1234'} | ||
277 | + its(:password) {should == '123123'} | ||
278 | + end | ||
279 | + | ||
280 | + context 'insufficient params' do | ||
281 | + it 'shows validation notice' do | ||
282 | + put :update, :id => @app.id, :app => { :issue_tracker_attributes => { | ||
283 | + :issue_tracker_type => 'fogbugz', :project_id => '1234' } } | ||
284 | + @app.reload | ||
285 | + | ||
286 | + @app.issue_tracker.should be_nil | ||
287 | + response.body.should match(/You must specify your FogBugz Area Name, Username, and Password/) | ||
288 | + end | ||
289 | + end | ||
290 | + end | ||
264 | end | 291 | end |
265 | end | 292 | end |
266 | 293 |