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