Commit 5d56e80523035f6895d568ff4a737d588fbf14ce
1 parent
2cecdbaa
Exists in
master
and in
1 other branch
Add endpoint for deploys and deliver notifications on deploy
Showing
14 changed files
with
123 additions
and
12 deletions
Show diff stats
... | ... | @@ -0,0 +1,14 @@ |
1 | +class DeploysController < ApplicationController | |
2 | + | |
3 | + def create | |
4 | + @project = Project.find_by_api_key!(params[:api_key]) | |
5 | + @deploy = @project.deploys.create!({ | |
6 | + :username => params[:deploy][:local_username], | |
7 | + :environment => params[:deploy][:rails_env], | |
8 | + :repository => params[:deploy][:scm_repository], | |
9 | + :revision => params[:deploy][:scm_revision] | |
10 | + }) | |
11 | + render :xml => @deploy | |
12 | + end | |
13 | + | |
14 | +end | |
0 | 15 | \ No newline at end of file | ... | ... |
app/mailers/mailer.rb
... | ... | @@ -7,8 +7,18 @@ class Mailer < ActionMailer::Base |
7 | 7 | @project = notice.err.project |
8 | 8 | |
9 | 9 | mail({ |
10 | - :to => @project.watchers.map(&:email), | |
11 | - :subject => "[#{@project.name}] #{@notice.err.message}" | |
10 | + :to => @project.watchers.map(&:email), | |
11 | + :subject => "[#{@project.name}] #{@notice.err.message}" | |
12 | + }) | |
13 | + end | |
14 | + | |
15 | + def deploy_notification(deploy) | |
16 | + @deploy = deploy | |
17 | + @project = deploy.project | |
18 | + | |
19 | + mail({ | |
20 | + :to => @project.watchers.map(&:email), | |
21 | + :subject => "[#{@project.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" | |
12 | 22 | }) |
13 | 23 | end |
14 | 24 | ... | ... |
app/models/deploy.rb
... | ... | @@ -9,6 +9,18 @@ class Deploy |
9 | 9 | |
10 | 10 | embedded_in :project, :inverse_of => :deploys |
11 | 11 | |
12 | + after_create :deliver_notification, :if => :should_notify? | |
13 | + | |
12 | 14 | validates_presence_of :username, :environment |
13 | 15 | |
16 | + def deliver_notification | |
17 | + Mailer.deploy_notification(self).deliver | |
18 | + end | |
19 | + | |
20 | + protected | |
21 | + | |
22 | + def should_notify? | |
23 | + project.watchers.any? | |
24 | + end | |
25 | + | |
14 | 26 | end | ... | ... |
app/models/err.rb
... | ... | @@ -19,7 +19,7 @@ class Err |
19 | 19 | |
20 | 20 | def self.for(attrs) |
21 | 21 | project = attrs.delete(:project) |
22 | - project.errs.unresolved.where(attrs).first || project.errs.create(attrs) | |
22 | + project.errs.unresolved.where(attrs).first || project.errs.create!(attrs) | |
23 | 23 | end |
24 | 24 | |
25 | 25 | def resolve! | ... | ... |
app/models/notice.rb
... | ... | @@ -28,7 +28,7 @@ class Notice |
28 | 28 | :environment => hoptoad_notice['server-environment']['environment-name'] |
29 | 29 | }) |
30 | 30 | |
31 | - error.notices.create({ | |
31 | + error.notices.create!({ | |
32 | 32 | :backtrace => hoptoad_notice['error']['backtrace']['line'], |
33 | 33 | :server_environment => hoptoad_notice['server-environment'], |
34 | 34 | :request => hoptoad_notice['request'], | ... | ... |
... | ... | @@ -0,0 +1,9 @@ |
1 | +<%= @project.name %> was just deployed to <%= @deploy.environment %> by <%= @deploy.username %>. | |
2 | + | |
3 | +Details: | |
4 | + | |
5 | + What: <%= @project.name %><%= "@#{@deploy.revision}" unless @deploy.revision.blank? %> | |
6 | + When: <%= @deploy.created_at.to_s %> | |
7 | + From: <%= @deploy.repository.blank? ? 'n/a' : @deploy.repository %> | |
8 | + | |
9 | +<%= render :partial => 'signature' %> | |
0 | 10 | \ No newline at end of file | ... | ... |
app/views/mailer/error_notification.text.erb
... | ... | @@ -4,5 +4,4 @@ This error has occurred <%= pluralize @notice.err.notices.count, 'time' %>. You |
4 | 4 | |
5 | 5 | <%= error_notice_url(@notice.err, @notice) %> |
6 | 6 | |
7 | -Your loyal servant, | |
8 | -Hypnotoad | |
9 | 7 | \ No newline at end of file |
8 | +<%= render :partial => 'signature' %> | |
10 | 9 | \ No newline at end of file | ... | ... |
config/routes.rb
... | ... | @@ -2,9 +2,10 @@ Hypnotoad::Application.routes.draw do |
2 | 2 | |
3 | 3 | # Hoptoad Notifier Routes |
4 | 4 | match '/notifier_api/v2/notices' => 'notices#create' |
5 | - # match '/deploys.txt' => 'deploys#create' | |
5 | + match '/deploys.txt' => 'deploys#create' | |
6 | 6 | |
7 | - resources :notices | |
7 | + resources :notices, :only => [:show] | |
8 | + resources :deploys, :only => [:show] | |
8 | 9 | resources :errors do |
9 | 10 | resources :notices |
10 | 11 | end | ... | ... |
... | ... | @@ -0,0 +1,42 @@ |
1 | +require 'spec_helper' | |
2 | + | |
3 | +describe DeploysController do | |
4 | + | |
5 | + context 'POST #create' do | |
6 | + before do | |
7 | + @params = { | |
8 | + 'local_username' => 'john.doe', | |
9 | + 'scm_repository' => 'git@github.com/jdpace/hypnotoad.git', | |
10 | + 'rails_env' => 'production', | |
11 | + 'scm_revision' => '19d77837eef37902cf5df7e4445c85f392a8d0d5' | |
12 | + } | |
13 | + @project = Factory(:project_with_watcher, :api_key => 'ALLGLORYTOTHEHYPNOTOAD') | |
14 | + end | |
15 | + | |
16 | + it 'finds the project via the api key' do | |
17 | + Project.should_receive(:find_by_api_key!).with('ALLGLORYTOTHEHYPNOTOAD').and_return(@project) | |
18 | + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' | |
19 | + end | |
20 | + | |
21 | + it 'creates a deploy' do | |
22 | + Project.stub(:find_by_api_key!).and_return(@project) | |
23 | + @project.deploys.should_receive(:create!). | |
24 | + with({ | |
25 | + :username => 'john.doe', | |
26 | + :environment => 'production', | |
27 | + :repository => 'git@github.com/jdpace/hypnotoad.git', | |
28 | + :revision => '19d77837eef37902cf5df7e4445c85f392a8d0d5' | |
29 | + }).and_return(Factory(:deploy)) | |
30 | + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' | |
31 | + end | |
32 | + | |
33 | + it 'sends an email notification', :focused => true do | |
34 | + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' | |
35 | + email = ActionMailer::Base.deliveries.last | |
36 | + email.to.should include(@project.watchers.first.email) | |
37 | + email.subject.should == "[#{@project.name}] Deployed to production by john.doe" | |
38 | + end | |
39 | + | |
40 | + end | |
41 | + | |
42 | +end | |
0 | 43 | \ No newline at end of file | ... | ... |
spec/controllers/notices_controller_spec.rb
... | ... | @@ -5,7 +5,8 @@ describe NoticesController do |
5 | 5 | context 'POST[XML] notices#create' do |
6 | 6 | before do |
7 | 7 | @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read |
8 | - Project.stub(:find_by_api_key!).and_return(Factory.build(:project)) | |
8 | + @project = Factory(:project_with_watcher) | |
9 | + Project.stub(:find_by_api_key!).and_return(@project) | |
9 | 10 | @notice = Notice.from_xml(@xml) |
10 | 11 | |
11 | 12 | request.env['Content-type'] = 'text/xml' |
... | ... | @@ -17,6 +18,13 @@ describe NoticesController do |
17 | 18 | Notice.should_receive(:from_xml).with(@xml).and_return(@notice) |
18 | 19 | post :create |
19 | 20 | end |
21 | + | |
22 | + it "sends a notification email" do | |
23 | + post :create | |
24 | + email = ActionMailer::Base.deliveries.last | |
25 | + email.to.should include(@project.watchers.first.email) | |
26 | + email.subject.should include(@notice.err.message) | |
27 | + end | |
20 | 28 | end |
21 | 29 | |
22 | 30 | end | ... | ... |
spec/factories/project_factories.rb
... | ... | @@ -5,6 +5,12 @@ Factory.define(:project) do |p| |
5 | 5 | p.name { Factory.next :project_name } |
6 | 6 | end |
7 | 7 | |
8 | +Factory.define(:project_with_watcher, :parent => :project) do |p| | |
9 | + p.after_create {|project| | |
10 | + Factory(:watcher, :project => project) | |
11 | + } | |
12 | +end | |
13 | + | |
8 | 14 | Factory.define(:watcher) do |w| |
9 | 15 | w.project {|p| p.association :project} |
10 | 16 | w.email { Factory.next :email } | ... | ... |
spec/models/deploy_spec.rb
... | ... | @@ -16,4 +16,12 @@ describe Deploy do |
16 | 16 | end |
17 | 17 | end |
18 | 18 | |
19 | + context 'being created' do | |
20 | + it 'should send an email notification' do | |
21 | + Mailer.should_receive(:deploy_notification). | |
22 | + and_return(mock('email', :deliver => true)) | |
23 | + Factory(:deploy, :project => Factory(:project_with_watcher)) | |
24 | + end | |
25 | + end | |
26 | + | |
19 | 27 | end | ... | ... |
spec/models/notice_spec.rb
... | ... | @@ -42,7 +42,7 @@ describe Notice do |
42 | 42 | :action => 'verify', |
43 | 43 | :environment => 'development' |
44 | 44 | }).and_return(err = Err.new) |
45 | - err.notices.stub(:create) | |
45 | + err.notices.stub(:create!) | |
46 | 46 | @notice = Notice.from_xml(@xml) |
47 | 47 | end |
48 | 48 | |
... | ... | @@ -81,8 +81,8 @@ describe Notice do |
81 | 81 | |
82 | 82 | describe "email notifications" do |
83 | 83 | before do |
84 | - @watcher = Factory(:watcher) | |
85 | - @error = Factory(:err, :project => @watcher.project) | |
84 | + @project = Factory(:project_with_watcher) | |
85 | + @error = Factory(:err, :project => @project) | |
86 | 86 | end |
87 | 87 | |
88 | 88 | App.email_at_notices.each do |threshold| | ... | ... |