Commit 30b00acfc34c1db93d3f8dc1460452ea866ed0c0
1 parent
12640a49
Exists in
master
and in
1 other branch
Specs for lighthouse tracker integration.
Showing
11 changed files
with
203 additions
and
21 deletions
Show diff stats
Gemfile
app/controllers/apps_controller.rb
@@ -22,6 +22,7 @@ class AppsController < ApplicationController | @@ -22,6 +22,7 @@ class AppsController < ApplicationController | ||
22 | def new | 22 | def new |
23 | @app = App.new | 23 | @app = App.new |
24 | @app.watchers.build | 24 | @app.watchers.build |
25 | + @app.issue_tracker = IssueTracker.new | ||
25 | end | 26 | end |
26 | 27 | ||
27 | def edit | 28 | def edit |
app/controllers/errs_controller.rb
1 | class ErrsController < ApplicationController | 1 | class ErrsController < ApplicationController |
2 | 2 | ||
3 | before_filter :find_app, :except => [:index, :all] | 3 | before_filter :find_app, :except => [:index, :all] |
4 | + before_filter :find_err, :except => [:index, :all] | ||
4 | 5 | ||
5 | def index | 6 | def index |
6 | app_scope = current_user.admin? ? App.all : current_user.apps | 7 | app_scope = current_user.admin? ? App.all : current_user.apps |
@@ -20,16 +21,25 @@ class ErrsController < ApplicationController | @@ -20,16 +21,25 @@ class ErrsController < ApplicationController | ||
20 | end | 21 | end |
21 | 22 | ||
22 | def show | 23 | def show |
23 | - @err = @app.errs.find(params[:id]) | ||
24 | page = (params[:notice] || @err.notices.count) | 24 | page = (params[:notice] || @err.notices.count) |
25 | page = 1 if page.to_i.zero? | 25 | page = 1 if page.to_i.zero? |
26 | @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1) | 26 | @notices = @err.notices.ordered.paginate(:page => page, :per_page => 1) |
27 | @notice = @notices.first | 27 | @notice = @notices.first |
28 | end | 28 | end |
29 | + | ||
30 | + def create_issue | ||
31 | + if @app.issue_tracker | ||
32 | + @app.issue_tracker.create_issue @err | ||
33 | + else | ||
34 | + flash[:error] = "This up has no issue tracker setup." | ||
35 | + end | ||
36 | + redirect_to app_err_path(@app, @err) | ||
37 | + rescue ActiveResource::ConnectionError | ||
38 | + flash[:error] = "There was an error during issue creation. Check your tracker settings or try again later." | ||
39 | + redirect_to app_err_path(@app, @err) | ||
40 | + end | ||
29 | 41 | ||
30 | def resolve | 42 | def resolve |
31 | - @err = @app.errs.find(params[:id]) | ||
32 | - | ||
33 | # Deal with bug in mogoid where find is returning an Enumberable obj | 43 | # Deal with bug in mogoid where find is returning an Enumberable obj |
34 | @err = @err.first if @err.respond_to?(:first) | 44 | @err = @err.first if @err.respond_to?(:first) |
35 | 45 | ||
@@ -51,5 +61,9 @@ class ErrsController < ApplicationController | @@ -51,5 +61,9 @@ class ErrsController < ApplicationController | ||
51 | # apparently finding by 'watchers.email' and 'id' is broken | 61 | # apparently finding by 'watchers.email' and 'id' is broken |
52 | raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app) | 62 | raise(Mongoid::Errors::DocumentNotFound.new(App,@app.id)) unless current_user.admin? || current_user.watching?(@app) |
53 | end | 63 | end |
64 | + | ||
65 | + def find_err | ||
66 | + @err = @app.errs.find(params[:id]) | ||
67 | + end | ||
54 | 68 | ||
55 | end | 69 | end |
app/models/err.rb
@@ -9,6 +9,7 @@ class Err | @@ -9,6 +9,7 @@ class Err | ||
9 | field :fingerprint | 9 | field :fingerprint |
10 | field :last_notice_at, :type => DateTime | 10 | field :last_notice_at, :type => DateTime |
11 | field :resolved, :type => Boolean, :default => false | 11 | field :resolved, :type => Boolean, :default => false |
12 | + field :issue_link, :type => String | ||
12 | 13 | ||
13 | index :last_notice_at | 14 | index :last_notice_at |
14 | 15 |
app/models/issue_tracker.rb
1 | class IssueTracker | 1 | class IssueTracker |
2 | include Mongoid::Document | 2 | include Mongoid::Document |
3 | include Mongoid::Timestamps | 3 | include Mongoid::Timestamps |
4 | + include HashHelper | ||
5 | + include Rails.application.routes.url_helpers | ||
6 | + default_url_options[:host] = Errbit::Application.config.action_mailer.default_url_options[:host] | ||
4 | 7 | ||
5 | validate :check_lighthouseapp_params | 8 | validate :check_lighthouseapp_params |
6 | 9 | ||
@@ -15,11 +18,72 @@ class IssueTracker | @@ -15,11 +18,72 @@ class IssueTracker | ||
15 | Lighthouse.account = account | 18 | Lighthouse.account = account |
16 | Lighthouse.token = api_token | 19 | Lighthouse.token = api_token |
17 | 20 | ||
21 | + # updating lighthouse account | ||
22 | + Lighthouse::Ticket.site | ||
23 | + | ||
18 | ticket = Lighthouse::Ticket.new(:project_id => project_id) | 24 | ticket = Lighthouse::Ticket.new(:project_id => project_id) |
19 | - ticket.title = "[#{ err.where }] #{err.message.to_s.truncate(27)}" | ||
20 | - #ticket.body = err.backtrace.join("\n") | 25 | + ticket.title = "[#{ err.environment }][#{ err.where }] #{err.message.to_s.truncate(100)}" |
26 | + | ||
27 | + ticket.body = "" | ||
28 | + ticket.body += "[See this exception on Errbit](#{ app_err_url err.app, err } \"See this exception on Errbit\")" | ||
29 | + ticket.body += "\n" | ||
30 | + if notice = err.notices.first | ||
31 | + ticket.body += "# #{notice.message} #" | ||
32 | + ticket.body += "\n" | ||
33 | + ticket.body += "## Summary ##" | ||
34 | + ticket.body += "\n" | ||
35 | + if notice.request['url'].present? | ||
36 | + ticket.body += "### URL ###" | ||
37 | + ticket.body += "\n" | ||
38 | + ticket.body += "[#{notice.request['url']}](#{notice.request['url']})" | ||
39 | + ticket.body += "\n" | ||
40 | + end | ||
41 | + ticket.body += "### Where ###" | ||
42 | + ticket.body += "\n" | ||
43 | + ticket.body += notice.err.where | ||
44 | + ticket.body += "\n" | ||
45 | + | ||
46 | + ticket.body += "### Occured ###" | ||
47 | + ticket.body += "\n" | ||
48 | + ticket.body += notice.created_at.to_s(:micro) | ||
49 | + ticket.body += "\n" | ||
50 | + | ||
51 | + ticket.body += "### Similar ###" | ||
52 | + ticket.body += "\n" | ||
53 | + ticket.body += (notice.err.notices.count - 1).to_s | ||
54 | + ticket.body += "\n" | ||
55 | + | ||
56 | + ticket.body += "## Params ##" | ||
57 | + ticket.body += "\n" | ||
58 | + ticket.body += "<code>#{pretty_hash(notice.params)}</code>" | ||
59 | + ticket.body += "\n" | ||
60 | + | ||
61 | + ticket.body += "## Session ##" | ||
62 | + ticket.body += "\n" | ||
63 | + ticket.body += "<code>#{pretty_hash(notice.session)}</code>" | ||
64 | + ticket.body += "\n" | ||
65 | + | ||
66 | + ticket.body += "## Backtrace ##" | ||
67 | + ticket.body += "\n" | ||
68 | + ticket.body += "<code>" | ||
69 | + for line in notice.backtrace | ||
70 | + ticket.body += "#{line['number']}: #{line['file'].sub(/^\[PROJECT_ROOT\]/, '')} -> **#{line['method']}**" | ||
71 | + ticket.body += "\n" | ||
72 | + end | ||
73 | + ticket.body += "</code>" | ||
74 | + ticket.body += "\n" | ||
75 | + | ||
76 | + ticket.body += "## Environment ##" | ||
77 | + ticket.body += "\n" | ||
78 | + for key, val in notice.env_vars | ||
79 | + ticket.body += "#{key}: #{val}" | ||
80 | + end | ||
81 | + ticket.body += "\n" | ||
82 | + end | ||
83 | + | ||
21 | ticket.tags << "errbit" | 84 | ticket.tags << "errbit" |
22 | - ticket.save | 85 | + ticket.save! |
86 | + err.update_attribute :issue_link, "#{Lighthouse::Ticket.site.to_s.sub(/#{Lighthouse::Ticket.site.path}$/, '')}#{Lighthouse::Ticket.element_path(ticket.id, :project_id => project_id)}".sub(/\.xml$/, '') | ||
23 | end | 87 | end |
24 | 88 | ||
25 | protected | 89 | protected |
app/views/errs/show.html.haml
@@ -10,7 +10,13 @@ | @@ -10,7 +10,13 @@ | ||
10 | %strong Last Notice: | 10 | %strong Last Notice: |
11 | = last_notice_at(@err).to_s(:micro) | 11 | = last_notice_at(@err).to_s(:micro) |
12 | - content_for :action_bar do | 12 | - content_for :action_bar do |
13 | - %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' if @err.unresolved? | 13 | + - if @err.unresolved? |
14 | + - if @err.app.issue_tracker | ||
15 | + - if @err.issue_link.blank? | ||
16 | + %span= link_to 'create issue', create_issue_app_err_path(@app, @err), :method => :post, :class => 'create-issue' | ||
17 | + - else | ||
18 | + %span= link_to 'go to issue', @err.issue_link, :class => 'goto-issue' | ||
19 | + %span= link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => err_confirm, :class => 'resolve' | ||
14 | 20 | ||
15 | %h4= @notice.try(:message) | 21 | %h4= @notice.try(:message) |
16 | 22 |
config/environments/development.rb
@@ -16,6 +16,7 @@ Errbit::Application.configure do | @@ -16,6 +16,7 @@ Errbit::Application.configure do | ||
16 | 16 | ||
17 | # Don't care if the mailer can't send | 17 | # Don't care if the mailer can't send |
18 | config.action_mailer.raise_delivery_errors = false | 18 | config.action_mailer.raise_delivery_errors = false |
19 | + config.action_mailer.default_url_options = { :host => 'localhost:3000' } | ||
19 | 20 | ||
20 | # Print deprecation notices to the Rails logger | 21 | # Print deprecation notices to the Rails logger |
21 | config.active_support.deprecation = :log | 22 | config.active_support.deprecation = :log |
config/environments/test.rb
@@ -24,6 +24,7 @@ Errbit::Application.configure do | @@ -24,6 +24,7 @@ Errbit::Application.configure do | ||
24 | # The :test delivery method accumulates sent emails in the | 24 | # The :test delivery method accumulates sent emails in the |
25 | # ActionMailer::Base.deliveries array. | 25 | # ActionMailer::Base.deliveries array. |
26 | config.action_mailer.delivery_method = :test | 26 | config.action_mailer.delivery_method = :test |
27 | + config.action_mailer.default_url_options = { :host => 'test.host' } | ||
27 | 28 | ||
28 | # Use SQL instead of Active Record's schema dumper when creating the test database. | 29 | # Use SQL instead of Active Record's schema dumper when creating the test database. |
29 | # This is necessary if your schema can't be completely dumped by the schema dumper, | 30 | # This is necessary if your schema can't be completely dumped by the schema dumper, |
config/routes.rb
spec/controllers/errs_controller_spec.rb
@@ -123,6 +123,33 @@ describe ErrsController do | @@ -123,6 +123,33 @@ describe ErrsController do | ||
123 | get :show, :app_id => app.id, :id => err.id | 123 | get :show, :app_id => app.id, :id => err.id |
124 | response.should be_success | 124 | response.should be_success |
125 | end | 125 | end |
126 | + | ||
127 | + context "create issue button" do | ||
128 | + let(:button_matcher) { match(/create issue/) } | ||
129 | + | ||
130 | + it "should not exist for err's app without issue tracker" do | ||
131 | + err = Factory :err | ||
132 | + get :show, :app_id => err.app.id, :id => err.id | ||
133 | + | ||
134 | + response.body.should_not button_matcher | ||
135 | + end | ||
136 | + | ||
137 | + it "should exist for err's app with issue tracker" do | ||
138 | + tracker = Factory(:lighthouseapp_tracker) | ||
139 | + err = Factory(:err, :app => tracker.app) | ||
140 | + get :show, :app_id => err.app.id, :id => err.id | ||
141 | + | ||
142 | + response.body.should button_matcher | ||
143 | + end | ||
144 | + | ||
145 | + it "should not exist for err with issue_link" do | ||
146 | + tracker = Factory(:lighthouseapp_tracker) | ||
147 | + err = Factory(:err, :app => tracker.app, :issue_link => "http://some.host") | ||
148 | + get :show, :app_id => err.app.id, :id => err.id | ||
149 | + | ||
150 | + response.body.should_not button_matcher | ||
151 | + end | ||
152 | + end | ||
126 | end | 153 | end |
127 | 154 | ||
128 | context 'when logged in as a user' do | 155 | context 'when logged in as a user' do |
@@ -186,5 +213,83 @@ describe ErrsController do | @@ -186,5 +213,83 @@ describe ErrsController do | ||
186 | response.should redirect_to(errs_path) | 213 | response.should redirect_to(errs_path) |
187 | end | 214 | end |
188 | end | 215 | end |
189 | - | 216 | + |
217 | + describe "POST /apps/:app_id/errs/:id/create_issue" do | ||
218 | + render_views | ||
219 | + | ||
220 | + before(:each) do | ||
221 | + sign_in Factory(:admin) | ||
222 | + end | ||
223 | + | ||
224 | + context "successful issue creation" do | ||
225 | + context "lighthouseapp tracker" do | ||
226 | + let(:notice) { Factory :notice } | ||
227 | + let(:tracker) { Factory :lighthouseapp_tracker, :app => notice.err.app } | ||
228 | + let(:err) { notice.err } | ||
229 | + | ||
230 | + before(:each) do | ||
231 | + number = 5 | ||
232 | + @issue_link = "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets/#{number}.xml" | ||
233 | + body = "<ticket><number type=\"integer\">#{number}</number></ticket>" | ||
234 | + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 201, :headers => {'Location' => @issue_link}, :body => body ) | ||
235 | + | ||
236 | + post :create_issue, :app_id => err.app.id, :id => err.id | ||
237 | + err.reload | ||
238 | + end | ||
239 | + | ||
240 | + it "should make request to Lighthouseapp with err params" do | ||
241 | + requested = have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") | ||
242 | + WebMock.should requested.with(:headers => {'X-Lighthousetoken' => tracker.api_token}) | ||
243 | + WebMock.should requested.with(:body => /<tag>errbit<\/tag>/) | ||
244 | + WebMock.should requested.with(:body => /<title>\[#{ err.environment }\]\[#{err.where}\] #{err.message.to_s.truncate(100)}<\/title>/) | ||
245 | + WebMock.should requested.with(:body => /<body>.+<\/body>/m) | ||
246 | + end | ||
247 | + | ||
248 | + it "should redirect to err page" do | ||
249 | + response.should redirect_to( app_err_path(err.app, err) ) | ||
250 | + end | ||
251 | + | ||
252 | + it "should create issue link for err" do | ||
253 | + err.issue_link.should == @issue_link.sub(/\.xml$/, '') | ||
254 | + end | ||
255 | + end | ||
256 | + end | ||
257 | + | ||
258 | + context "absent issue tracker" do | ||
259 | + let(:err) { Factory :err } | ||
260 | + | ||
261 | + before(:each) do | ||
262 | + post :create_issue, :app_id => err.app.id, :id => err.id | ||
263 | + end | ||
264 | + | ||
265 | + it "should redirect to err page" do | ||
266 | + response.should redirect_to( app_err_path(err.app, err) ) | ||
267 | + end | ||
268 | + | ||
269 | + it "should set flash error message telling issue tracker of the app doesn't exist" do | ||
270 | + flash[:error].should == "This up has no issue tracker setup." | ||
271 | + end | ||
272 | + end | ||
273 | + | ||
274 | + context "error during request to a tracker" do | ||
275 | + context "lighthouseapp tracker" do | ||
276 | + let(:tracker) { Factory :lighthouseapp_tracker } | ||
277 | + let(:err) { Factory :err, :app => tracker.app } | ||
278 | + | ||
279 | + before(:each) do | ||
280 | + stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml").to_return(:status => 500) | ||
281 | + | ||
282 | + post :create_issue, :app_id => err.app.id, :id => err.id | ||
283 | + end | ||
284 | + | ||
285 | + it "should redirect to err page" do | ||
286 | + response.should redirect_to( app_err_path(err.app, err) ) | ||
287 | + end | ||
288 | + | ||
289 | + it "should notify of connection error" do | ||
290 | + flash[:error].should == "There was an error during issue creation. Check your tracker settings or try again later." | ||
291 | + end | ||
292 | + end | ||
293 | + end | ||
294 | + end | ||
190 | end | 295 | end |
spec/models/issue_tracker_spec.rb
@@ -2,16 +2,4 @@ | @@ -2,16 +2,4 @@ | ||
2 | require 'spec_helper' | 2 | require 'spec_helper' |
3 | 3 | ||
4 | describe IssueTracker do | 4 | describe IssueTracker do |
5 | - describe "#create_issue" do | ||
6 | - context "lighthouseapp tracker" do | ||
7 | - let(:tracker) { Factory :lighthouseapp_tracker } | ||
8 | - let(:err) { Factory :err } | ||
9 | - | ||
10 | - it "should make request to Lighthouseapp with err params" do | ||
11 | - stub_request(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") | ||
12 | - tracker.create_issue err | ||
13 | - WebMock.should have_requested(:post, "http://#{tracker.account}.lighthouseapp.com/projects/#{tracker.project_id}/tickets.xml") | ||
14 | - end | ||
15 | - end | ||
16 | - end | ||
17 | end | 5 | end |