From 5d56e80523035f6895d568ff4a737d588fbf14ce Mon Sep 17 00:00:00 2001 From: Jared Pace Date: Wed, 4 Aug 2010 15:19:15 -0500 Subject: [PATCH] Add endpoint for deploys and deliver notifications on deploy --- app/controllers/deploys_controller.rb | 14 ++++++++++++++ app/mailers/mailer.rb | 14 ++++++++++++-- app/models/deploy.rb | 12 ++++++++++++ app/models/err.rb | 2 +- app/models/notice.rb | 2 +- app/views/mailer/_signature.text.erb | 2 ++ app/views/mailer/deploy_notification.text.erb | 9 +++++++++ app/views/mailer/error_notification.text.erb | 3 +-- config/routes.rb | 5 +++-- spec/controllers/deploys_controller_spec.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ spec/controllers/notices_controller_spec.rb | 10 +++++++++- spec/factories/project_factories.rb | 6 ++++++ spec/models/deploy_spec.rb | 8 ++++++++ spec/models/notice_spec.rb | 6 +++--- 14 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 app/controllers/deploys_controller.rb create mode 100644 app/views/mailer/_signature.text.erb create mode 100644 app/views/mailer/deploy_notification.text.erb create mode 100644 spec/controllers/deploys_controller_spec.rb diff --git a/app/controllers/deploys_controller.rb b/app/controllers/deploys_controller.rb new file mode 100644 index 0000000..f3969b7 --- /dev/null +++ b/app/controllers/deploys_controller.rb @@ -0,0 +1,14 @@ +class DeploysController < ApplicationController + + def create + @project = Project.find_by_api_key!(params[:api_key]) + @deploy = @project.deploys.create!({ + :username => params[:deploy][:local_username], + :environment => params[:deploy][:rails_env], + :repository => params[:deploy][:scm_repository], + :revision => params[:deploy][:scm_revision] + }) + render :xml => @deploy + end + +end \ No newline at end of file diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb index 6f0c691..562c5e3 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/mailer.rb @@ -7,8 +7,18 @@ class Mailer < ActionMailer::Base @project = notice.err.project mail({ - :to => @project.watchers.map(&:email), - :subject => "[#{@project.name}] #{@notice.err.message}" + :to => @project.watchers.map(&:email), + :subject => "[#{@project.name}] #{@notice.err.message}" + }) + end + + def deploy_notification(deploy) + @deploy = deploy + @project = deploy.project + + mail({ + :to => @project.watchers.map(&:email), + :subject => "[#{@project.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" }) end diff --git a/app/models/deploy.rb b/app/models/deploy.rb index 37e5a1b..d3c44aa 100644 --- a/app/models/deploy.rb +++ b/app/models/deploy.rb @@ -9,6 +9,18 @@ class Deploy embedded_in :project, :inverse_of => :deploys + after_create :deliver_notification, :if => :should_notify? + validates_presence_of :username, :environment + def deliver_notification + Mailer.deploy_notification(self).deliver + end + + protected + + def should_notify? + project.watchers.any? + end + end diff --git a/app/models/err.rb b/app/models/err.rb index 865112a..45879ac 100644 --- a/app/models/err.rb +++ b/app/models/err.rb @@ -19,7 +19,7 @@ class Err def self.for(attrs) project = attrs.delete(:project) - project.errs.unresolved.where(attrs).first || project.errs.create(attrs) + project.errs.unresolved.where(attrs).first || project.errs.create!(attrs) end def resolve! diff --git a/app/models/notice.rb b/app/models/notice.rb index 94b80f8..1d1b09a 100644 --- a/app/models/notice.rb +++ b/app/models/notice.rb @@ -28,7 +28,7 @@ class Notice :environment => hoptoad_notice['server-environment']['environment-name'] }) - error.notices.create({ + error.notices.create!({ :backtrace => hoptoad_notice['error']['backtrace']['line'], :server_environment => hoptoad_notice['server-environment'], :request => hoptoad_notice['request'], diff --git a/app/views/mailer/_signature.text.erb b/app/views/mailer/_signature.text.erb new file mode 100644 index 0000000..89997d9 --- /dev/null +++ b/app/views/mailer/_signature.text.erb @@ -0,0 +1,2 @@ +All Glory, +Hypnotoad \ No newline at end of file diff --git a/app/views/mailer/deploy_notification.text.erb b/app/views/mailer/deploy_notification.text.erb new file mode 100644 index 0000000..52df73d --- /dev/null +++ b/app/views/mailer/deploy_notification.text.erb @@ -0,0 +1,9 @@ +<%= @project.name %> was just deployed to <%= @deploy.environment %> by <%= @deploy.username %>. + +Details: + + What: <%= @project.name %><%= "@#{@deploy.revision}" unless @deploy.revision.blank? %> + When: <%= @deploy.created_at.to_s %> + From: <%= @deploy.repository.blank? ? 'n/a' : @deploy.repository %> + +<%= render :partial => 'signature' %> \ No newline at end of file diff --git a/app/views/mailer/error_notification.text.erb b/app/views/mailer/error_notification.text.erb index 4e7f608..4a6d67c 100644 --- a/app/views/mailer/error_notification.text.erb +++ b/app/views/mailer/error_notification.text.erb @@ -4,5 +4,4 @@ This error has occurred <%= pluralize @notice.err.notices.count, 'time' %>. You <%= error_notice_url(@notice.err, @notice) %> -Your loyal servant, -Hypnotoad \ No newline at end of file +<%= render :partial => 'signature' %> \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 0b789df..da1054f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,9 +2,10 @@ Hypnotoad::Application.routes.draw do # Hoptoad Notifier Routes match '/notifier_api/v2/notices' => 'notices#create' - # match '/deploys.txt' => 'deploys#create' + match '/deploys.txt' => 'deploys#create' - resources :notices + resources :notices, :only => [:show] + resources :deploys, :only => [:show] resources :errors do resources :notices end diff --git a/spec/controllers/deploys_controller_spec.rb b/spec/controllers/deploys_controller_spec.rb new file mode 100644 index 0000000..f60f1fe --- /dev/null +++ b/spec/controllers/deploys_controller_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe DeploysController do + + context 'POST #create' do + before do + @params = { + 'local_username' => 'john.doe', + 'scm_repository' => 'git@github.com/jdpace/hypnotoad.git', + 'rails_env' => 'production', + 'scm_revision' => '19d77837eef37902cf5df7e4445c85f392a8d0d5' + } + @project = Factory(:project_with_watcher, :api_key => 'ALLGLORYTOTHEHYPNOTOAD') + end + + it 'finds the project via the api key' do + Project.should_receive(:find_by_api_key!).with('ALLGLORYTOTHEHYPNOTOAD').and_return(@project) + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' + end + + it 'creates a deploy' do + Project.stub(:find_by_api_key!).and_return(@project) + @project.deploys.should_receive(:create!). + with({ + :username => 'john.doe', + :environment => 'production', + :repository => 'git@github.com/jdpace/hypnotoad.git', + :revision => '19d77837eef37902cf5df7e4445c85f392a8d0d5' + }).and_return(Factory(:deploy)) + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' + end + + it 'sends an email notification', :focused => true do + post :create, :deploy => @params, :api_key => 'ALLGLORYTOTHEHYPNOTOAD' + email = ActionMailer::Base.deliveries.last + email.to.should include(@project.watchers.first.email) + email.subject.should == "[#{@project.name}] Deployed to production by john.doe" + end + + end + +end \ No newline at end of file diff --git a/spec/controllers/notices_controller_spec.rb b/spec/controllers/notices_controller_spec.rb index 9edb9bb..8c5abdf 100644 --- a/spec/controllers/notices_controller_spec.rb +++ b/spec/controllers/notices_controller_spec.rb @@ -5,7 +5,8 @@ describe NoticesController do context 'POST[XML] notices#create' do before do @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read - Project.stub(:find_by_api_key!).and_return(Factory.build(:project)) + @project = Factory(:project_with_watcher) + Project.stub(:find_by_api_key!).and_return(@project) @notice = Notice.from_xml(@xml) request.env['Content-type'] = 'text/xml' @@ -17,6 +18,13 @@ describe NoticesController do Notice.should_receive(:from_xml).with(@xml).and_return(@notice) post :create end + + it "sends a notification email" do + post :create + email = ActionMailer::Base.deliveries.last + email.to.should include(@project.watchers.first.email) + email.subject.should include(@notice.err.message) + end end end diff --git a/spec/factories/project_factories.rb b/spec/factories/project_factories.rb index 739439e..aed2f84 100644 --- a/spec/factories/project_factories.rb +++ b/spec/factories/project_factories.rb @@ -5,6 +5,12 @@ Factory.define(:project) do |p| p.name { Factory.next :project_name } end +Factory.define(:project_with_watcher, :parent => :project) do |p| + p.after_create {|project| + Factory(:watcher, :project => project) + } +end + Factory.define(:watcher) do |w| w.project {|p| p.association :project} w.email { Factory.next :email } diff --git a/spec/models/deploy_spec.rb b/spec/models/deploy_spec.rb index 5c46ac8..e33cf8b 100644 --- a/spec/models/deploy_spec.rb +++ b/spec/models/deploy_spec.rb @@ -16,4 +16,12 @@ describe Deploy do end end + context 'being created' do + it 'should send an email notification' do + Mailer.should_receive(:deploy_notification). + and_return(mock('email', :deliver => true)) + Factory(:deploy, :project => Factory(:project_with_watcher)) + end + end + end diff --git a/spec/models/notice_spec.rb b/spec/models/notice_spec.rb index b5eaed6..aa2dfb3 100644 --- a/spec/models/notice_spec.rb +++ b/spec/models/notice_spec.rb @@ -42,7 +42,7 @@ describe Notice do :action => 'verify', :environment => 'development' }).and_return(err = Err.new) - err.notices.stub(:create) + err.notices.stub(:create!) @notice = Notice.from_xml(@xml) end @@ -81,8 +81,8 @@ describe Notice do describe "email notifications" do before do - @watcher = Factory(:watcher) - @error = Factory(:err, :project => @watcher.project) + @project = Factory(:project_with_watcher) + @error = Factory(:err, :project => @project) end App.email_at_notices.each do |threshold| -- libgit2 0.21.2