diff --git a/Gemfile b/Gemfile index a5eeca3..995a004 100644 --- a/Gemfile +++ b/Gemfile @@ -33,6 +33,7 @@ gem 'rack-ssl-enforcer' gem 'fabrication', "~> 1.3.0" # Both for tests, and loading demo data gem 'rails_autolink', '~> 1.0.9' gem 'campy' +gem 'hipchat' # Please don't update this to airbrake - We override the send_notice method # to handle internal errors. diff --git a/Gemfile.lock b/Gemfile.lock index 1b06128..b20d5f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,10 +97,15 @@ GEM hashie (1.2.0) highline (1.6.13) hike (1.2.1) + hipchat (0.4.1) + httparty hoptoad_notifier (2.4.11) activesupport builder htmlentities (4.3.1) + httparty (0.9.0) + multi_json (~> 1.0) + multi_xml httpauth (0.1) i18n (0.6.1) inherited_resources (1.3.1) @@ -144,6 +149,7 @@ GEM rails (>= 3.0.0) railties (>= 3.0.0) multi_json (1.3.6) + multi_xml (0.5.1) multipart-post (1.1.5) net-scp (1.0.4) net-ssh (>= 1.99.1) @@ -309,6 +315,7 @@ DEPENDENCIES execjs fabrication (~> 1.3.0) haml + hipchat hoptoad_notifier (~> 2.4) htmlentities (~> 4.3.0) inherited_resources diff --git a/app/assets/images/hipchat_create.png b/app/assets/images/hipchat_create.png new file mode 100644 index 0000000..8deafab Binary files /dev/null and b/app/assets/images/hipchat_create.png differ diff --git a/app/assets/images/hipchat_goto.png b/app/assets/images/hipchat_goto.png new file mode 100644 index 0000000..8deafab Binary files /dev/null and b/app/assets/images/hipchat_goto.png differ diff --git a/app/assets/images/hipchat_inactive.png b/app/assets/images/hipchat_inactive.png new file mode 100644 index 0000000..f78c9ab Binary files /dev/null and b/app/assets/images/hipchat_inactive.png differ diff --git a/app/models/notice_observer.rb b/app/models/notice_observer.rb index 9dc211d..54dc357 100644 --- a/app/models/notice_observer.rb +++ b/app/models/notice_observer.rb @@ -2,13 +2,13 @@ class NoticeObserver < Mongoid::Observer observe :notice def after_create notice - return unless should_notify? notice - - # if the app has a notficiation service, fire it off + # if the app has a notification service, fire it off if notice.app.notification_service_configured? notice.app.notification_service.create_notification(notice.problem) end + return unless should_notify? notice + Mailer.err_notification(notice).deliver end diff --git a/app/models/notification_service.rb b/app/models/notification_service.rb index c5513cf..4f73adb 100644 --- a/app/models/notification_service.rb +++ b/app/models/notification_service.rb @@ -1,6 +1,9 @@ class NotificationService include Mongoid::Document + include Rails.application.routes.url_helpers + default_url_options[:host] = ActionMailer::Base.default_url_options[:host] + field :room_id, :type => String field :api_token, :type => String field :subdomain, :type => String diff --git a/app/models/notification_services/hipchat_service.rb b/app/models/notification_services/hipchat_service.rb new file mode 100644 index 0000000..7fb1a3b --- /dev/null +++ b/app/models/notification_services/hipchat_service.rb @@ -0,0 +1,29 @@ +class NotificationServices::HipchatService < NotificationService + Label = 'hipchat' + Fields = [ + [:api_token, { + :placeholder => "API Token" + }], + [:room_id, { + :placeholder => "Room ID", + :label => "Room ID" + }], + ] + + def check_params + if Fields.any? { |f, _| self[f].blank? } + errors.add :base, 'You must specify your Hipchat API token and Room ID' + end + end + + def create_notification(problem) + url = app_err_url problem.app, problem + message = <<-MSG.strip_heredoc + [#{ERB::Util.html_escape problem.app.name}]#{ERB::Util.html_escape notification_description(problem)}
+ #{url} + MSG + + client = HipChat::Client.new(api_token) + client[room_id].send('Errbit', message, :color => 'red') + end +end diff --git a/spec/fabricators/notification_service_fabricator.rb b/spec/fabricators/notification_service_fabricator.rb index e5f6810..a1c2ac0 100644 --- a/spec/fabricators/notification_service_fabricator.rb +++ b/spec/fabricators/notification_service_fabricator.rb @@ -5,6 +5,6 @@ Fabricator :notification_service do subdomain { sequence :word } end -%w(campfire).each do |t| +%w(campfire hipchat).each do |t| Fabricator "#{t}_notification_service".to_sym, :from => :notification_service, :class_name => "NotificationService::#{t.camelcase}Service" end diff --git a/spec/models/notice_observer_spec.rb b/spec/models/notice_observer_spec.rb index 3d3b62f..dca73fe 100644 --- a/spec/models/notice_observer_spec.rb +++ b/spec/models/notice_observer_spec.rb @@ -44,7 +44,7 @@ describe NoticeObserver do end describe "should send a notification if a notification service is configured" do - let(:app) { app = Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:campfire_notification_service))} + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:campfire_notification_service))} let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) } before do @@ -56,9 +56,6 @@ describe NoticeObserver do end it "should create a campfire notification" do - err.problem.stub(:notices_count) { 1 } - app.notification_service.stub!(:create_notification).and_return(true) - app.stub!(:notification_recipients => %w('ryan@system88.com')) app.notification_service.should_receive(:create_notification) Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'}, @@ -67,7 +64,7 @@ describe NoticeObserver do end describe "should not send a notification if a notification service is not configured" do - let(:app) { app = Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:notification_service))} + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:notification_service))} let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) } before do @@ -79,8 +76,6 @@ describe NoticeObserver do end it "should not create a campfire notification" do - err.problem.stub(:notices_count) { 1 } - app.stub!(:notification_recipients => %w('ryan@system88.com')) app.notification_service.should_not_receive(:create_notification) Notice.create!(:err => err, :message => 'FooError: Too Much Bar', :server_environment => {'environment-name' => 'production'}, @@ -88,4 +83,22 @@ describe NoticeObserver do end end + describe 'hipcat notifications' do + let(:app) { Fabricate(:app, :email_at_notices => [1], :notification_service => Fabricate(:hipchat_notification_service))} + let(:err) { Fabricate(:err, :problem => Fabricate(:problem, :app => app, :notices_count => 100)) } + + before do + Errbit::Config.per_app_email_at_notices = true + end + + after do + Errbit::Config.per_app_email_at_notices = false + end + + it 'creates a hipchat notification' do + app.notification_service.should_receive(:create_notification) + + Fabricate(:notice, :err => err) + end + end end diff --git a/spec/models/notification_service/hipchat_service_spec.rb b/spec/models/notification_service/hipchat_service_spec.rb new file mode 100644 index 0000000..6e4f9fc --- /dev/null +++ b/spec/models/notification_service/hipchat_service_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe NotificationServices::HipchatService do + let(:service) { Fabricate.build(:hipchat_notification_service) } + let(:problem) { Fabricate(:problem) } + let(:room) { double } + + before do + HipChat::Client.any_instance.stub(:[] => room) + end + + it 'sends message' do + room.should_receive(:send) + service.create_notification(problem) + end + + it 'escapes html in message' do + service.stub(:notification_description => '<3') + room.should_receive(:send) do |_, message| + message.should_not include('<3') + message.should include('<3') + end + service.create_notification(problem) + end +end -- libgit2 0.21.2