Commit e77f238e661fdff86f4ee94c1c8262012ba592b5

Authored by Jared Pace
1 parent a689d49b
Exists in master and in 1 other branch production

Rename Project to App

Showing 44 changed files with 479 additions and 479 deletions   Show diff stats
app/controllers/apps_controller.rb 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +class AppsController < ApplicationController
  2 +
  3 + def index
  4 + @apps = App.all
  5 + end
  6 +
  7 + def show
  8 + @app = App.find(params[:id])
  9 + @errs = @app.errs.paginate
  10 + end
  11 +
  12 + def new
  13 + @app = App.new
  14 + @app.watchers.build
  15 + end
  16 +
  17 + def edit
  18 + @app = App.find(params[:id])
  19 + @app.watchers.build if @app.watchers.none?
  20 + end
  21 +
  22 + def create
  23 + @app = App.new(params[:app])
  24 +
  25 + if @app.save
  26 + flash[:success] = 'Great success! Configure your app with the API key below'
  27 + redirect_to app_path(@app)
  28 + else
  29 + render :new
  30 + end
  31 + end
  32 +
  33 + def update
  34 + @app = App.find(params[:id])
  35 +
  36 + if @app.update_attributes!(params[:app])
  37 + flash[:success] = "Good news everyone! '#{@app.name}' was successfully updated."
  38 + redirect_to app_path(@app)
  39 + else
  40 + render :edit
  41 + end
  42 + end
  43 +
  44 + def destroy
  45 + @app = App.find(params[:id])
  46 + @app.destroy
  47 + flash[:success] = "'#{@app.name}' was successfully destroyed."
  48 + redirect_to apps_path
  49 + end
  50 +end
app/controllers/deploys_controller.rb
1 class DeploysController < ApplicationController 1 class DeploysController < ApplicationController
2 2
3 def create 3 def create
4 - @project = Project.find_by_api_key!(params[:api_key])  
5 - @deploy = @project.deploys.create!({ 4 + @app = App.find_by_api_key!(params[:api_key])
  5 + @deploy = @app.deploys.create!({
6 :username => params[:deploy][:local_username], 6 :username => params[:deploy][:local_username],
7 :environment => params[:deploy][:rails_env], 7 :environment => params[:deploy][:rails_env],
8 :repository => params[:deploy][:scm_repository], 8 :repository => params[:deploy][:scm_repository],
app/controllers/errs_controller.rb
@@ -9,15 +9,15 @@ class ErrsController &lt; ApplicationController @@ -9,15 +9,15 @@ class ErrsController &lt; ApplicationController
9 end 9 end
10 10
11 def show 11 def show
12 - @project = Project.find(params[:project_id])  
13 - @err = @project.errs.find(params[:id]) 12 + @app = App.find(params[:app_id])
  13 + @err = @app.errs.find(params[:id])
14 @notices = @err.notices.ordered.paginate(:page => (params[:notice] || @err.notices.count), :per_page => 1) 14 @notices = @err.notices.ordered.paginate(:page => (params[:notice] || @err.notices.count), :per_page => 1)
15 @notice = @notices.first 15 @notice = @notices.first
16 end 16 end
17 17
18 def resolve 18 def resolve
19 - @project = Project.find(params[:project_id])  
20 - @err = @project.errs.unresolved.find(params[:id]) 19 + @app = App.find(params[:app_id])
  20 + @err = @app.errs.unresolved.find(params[:id])
21 21
22 # Deal with bug in mogoid where find is returning an Enumberable obj 22 # Deal with bug in mogoid where find is returning an Enumberable obj
23 @err = @err.first if @err.respond_to?(:first) 23 @err = @err.first if @err.respond_to?(:first)
app/controllers/projects_controller.rb
@@ -1,50 +0,0 @@ @@ -1,50 +0,0 @@
1 -class ProjectsController < ApplicationController  
2 -  
3 - def index  
4 - @projects = Project.all  
5 - end  
6 -  
7 - def show  
8 - @project = Project.find(params[:id])  
9 - @errs = @project.errs.paginate  
10 - end  
11 -  
12 - def new  
13 - @project = Project.new  
14 - @project.watchers.build  
15 - end  
16 -  
17 - def edit  
18 - @project = Project.find(params[:id])  
19 - @project.watchers.build if @project.watchers.none?  
20 - end  
21 -  
22 - def create  
23 - @project = Project.new(params[:project])  
24 -  
25 - if @project.save  
26 - flash[:success] = 'Great success! Configure your project with the API key below'  
27 - redirect_to project_path(@project)  
28 - else  
29 - render :new  
30 - end  
31 - end  
32 -  
33 - def update  
34 - @project = Project.find(params[:id])  
35 -  
36 - if @project.update_attributes(params[:project])  
37 - flash[:success] = "Good news everyone! '#{@project.name}' was successfully updated."  
38 - redirect_to project_path(@project)  
39 - else  
40 - render :edit  
41 - end  
42 - end  
43 -  
44 - def destroy  
45 - @project = Project.find(params[:id])  
46 - @project.destroy  
47 - flash[:success] = "'#{@project.name}' was successfully destroyed."  
48 - redirect_to projects_path  
49 - end  
50 -end  
app/mailers/mailer.rb
1 class Mailer < ActionMailer::Base 1 class Mailer < ActionMailer::Base
2 - default :from => App.email_from  
3 - default_url_options[:host] = App.host 2 + default :from => Errbit::Config.email_from
  3 + default_url_options[:host] = Errbit::Config.host
4 4
5 def error_notification(notice) 5 def error_notification(notice)
6 @notice = notice 6 @notice = notice
7 - @project = notice.err.project 7 + @app = notice.err.app
8 8
9 mail({ 9 mail({
10 - :to => @project.watchers.map(&:email),  
11 - :subject => "[#{@project.name}] #{@notice.err.message}" 10 + :to => @app.watchers.map(&:email),
  11 + :subject => "[#{@app.name}] #{@notice.err.message}"
12 }) 12 })
13 end 13 end
14 14
15 def deploy_notification(deploy) 15 def deploy_notification(deploy)
16 @deploy = deploy 16 @deploy = deploy
17 - @project = deploy.project 17 + @app = deploy.app
18 18
19 mail({ 19 mail({
20 - :to => @project.watchers.map(&:email),  
21 - :subject => "[#{@project.name}] Deployed to #{@deploy.environment} by #{@deploy.username}" 20 + :to => @app.watchers.map(&:email),
  21 + :subject => "[#{@app.name}] Deployed to #{@deploy.environment} by #{@deploy.username}"
22 }) 22 })
23 end 23 end
24 24
app/models/app.rb 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +class App
  2 + include Mongoid::Document
  3 + include Mongoid::Timestamps
  4 +
  5 + field :name, :type => String
  6 + field :api_key
  7 + field :resolve_errs_on_deploy, :type => Boolean, :default => false
  8 + key :name
  9 +
  10 + embeds_many :watchers
  11 + embeds_many :deploys
  12 + references_many :errs, :dependent => :destroy
  13 +
  14 + before_validation :generate_api_key, :on => :create
  15 +
  16 + validates_presence_of :name, :api_key
  17 + validates_uniqueness_of :name, :api_key, :allow_blank => true, :on => :create
  18 +
  19 + accepts_nested_attributes_for :watchers, :allow_destroy => true,
  20 + :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
  21 +
  22 + def self.find_by_api_key!(key)
  23 + where(:api_key => key).first || raise(Mongoid::Errors::DocumentNotFound.new(self,key))
  24 + end
  25 +
  26 + def last_deploy_at
  27 + deploys.last && deploys.last.created_at
  28 + end
  29 +
  30 + protected
  31 +
  32 + def generate_api_key
  33 + self.api_key ||= ActiveSupport::SecureRandom.hex
  34 + end
  35 +
  36 +end
app/models/deploy.rb
@@ -7,10 +7,10 @@ class Deploy @@ -7,10 +7,10 @@ class Deploy
7 field :environment 7 field :environment
8 field :revision 8 field :revision
9 9
10 - embedded_in :project, :inverse_of => :deploys 10 + embedded_in :app, :inverse_of => :deploys
11 11
12 after_create :deliver_notification, :if => :should_notify? 12 after_create :deliver_notification, :if => :should_notify?
13 - after_create :resolve_project_errs, :if => :should_resolve_project_errs? 13 + after_create :resolve_app_errs, :if => :should_resolve_app_errs?
14 14
15 validates_presence_of :username, :environment 15 validates_presence_of :username, :environment
16 16
@@ -18,18 +18,18 @@ class Deploy @@ -18,18 +18,18 @@ class Deploy
18 Mailer.deploy_notification(self).deliver 18 Mailer.deploy_notification(self).deliver
19 end 19 end
20 20
21 - def resolve_project_errs  
22 - project.errs.unresolved.each {|err| err.resolve!} 21 + def resolve_app_errs
  22 + app.errs.unresolved.each {|err| err.resolve!}
23 end 23 end
24 24
25 protected 25 protected
26 26
27 def should_notify? 27 def should_notify?
28 - project.watchers.any? 28 + app.watchers.any?
29 end 29 end
30 30
31 - def should_resolve_project_errs?  
32 - project.resolve_errs_on_deploy? 31 + def should_resolve_app_errs?
  32 + app.resolve_errs_on_deploy?
33 end 33 end
34 34
35 end 35 end
app/models/err.rb
@@ -10,7 +10,7 @@ class Err @@ -10,7 +10,7 @@ class Err
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 12
13 - referenced_in :project 13 + referenced_in :app
14 embeds_many :notices 14 embeds_many :notices
15 15
16 validates_presence_of :klass, :environment 16 validates_presence_of :klass, :environment
@@ -20,8 +20,8 @@ class Err @@ -20,8 +20,8 @@ class Err
20 scope :ordered, order_by(:last_notice_at.desc) 20 scope :ordered, order_by(:last_notice_at.desc)
21 21
22 def self.for(attrs) 22 def self.for(attrs)
23 - project = attrs.delete(:project)  
24 - project.errs.unresolved.where(attrs).first || project.errs.create!(attrs) 23 + app = attrs.delete(:app)
  24 + app.errs.unresolved.where(attrs).first || app.errs.create!(attrs)
25 end 25 end
26 26
27 def resolve! 27 def resolve!
app/models/notice.rb
@@ -21,13 +21,13 @@ class Notice @@ -21,13 +21,13 @@ class Notice
21 21
22 def self.from_xml(hoptoad_xml) 22 def self.from_xml(hoptoad_xml)
23 hoptoad_notice = Hoptoad::V2.parse_xml(hoptoad_xml) 23 hoptoad_notice = Hoptoad::V2.parse_xml(hoptoad_xml)
24 - project = Project.find_by_api_key!(hoptoad_notice['api-key']) 24 + app = App.find_by_api_key!(hoptoad_notice['api-key'])
25 25
26 hoptoad_notice['request']['component'] = 'unknown' if hoptoad_notice['request']['component'].blank? 26 hoptoad_notice['request']['component'] = 'unknown' if hoptoad_notice['request']['component'].blank?
27 hoptoad_notice['request']['action'] = nil if hoptoad_notice['request']['action'].blank? 27 hoptoad_notice['request']['action'] = nil if hoptoad_notice['request']['action'].blank?
28 28
29 error = Err.for({ 29 error = Err.for({
30 - :project => project, 30 + :app => app,
31 :klass => hoptoad_notice['error']['class'], 31 :klass => hoptoad_notice['error']['class'],
32 :component => hoptoad_notice['request']['component'], 32 :component => hoptoad_notice['request']['component'],
33 :action => hoptoad_notice['request']['action'], 33 :action => hoptoad_notice['request']['action'],
@@ -71,7 +71,7 @@ class Notice @@ -71,7 +71,7 @@ class Notice
71 protected 71 protected
72 72
73 def should_notify? 73 def should_notify?
74 - App.email_at_notices.include?(err.notices.count) && err.project.watchers.any? 74 + Errbit::Config.email_at_notices.include?(err.notices.count) && err.app.watchers.any?
75 end 75 end
76 76
77 end 77 end
78 \ No newline at end of file 78 \ No newline at end of file
app/models/project.rb
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -class Project  
2 - include Mongoid::Document  
3 - include Mongoid::Timestamps  
4 -  
5 - field :name, :type => String  
6 - field :api_key  
7 - field :resolve_errs_on_deploy, :type => Boolean, :default => false  
8 - key :name  
9 -  
10 - embeds_many :watchers  
11 - embeds_many :deploys  
12 - references_many :errs, :dependent => :destroy  
13 -  
14 - before_validation :generate_api_key, :on => :create  
15 -  
16 - validates_presence_of :name, :api_key  
17 - validates_uniqueness_of :name, :api_key, :allow_blank => true  
18 -  
19 - accepts_nested_attributes_for :watchers, :allow_destroy => true,  
20 - :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }  
21 -  
22 - def self.find_by_api_key!(key)  
23 - where(:api_key => key).first || raise(Mongoid::Errors::DocumentNotFound.new(self,key))  
24 - end  
25 -  
26 - def last_deploy_at  
27 - deploys.last && deploys.last.created_at  
28 - end  
29 -  
30 - protected  
31 -  
32 - def generate_api_key  
33 - self.api_key ||= ActiveSupport::SecureRandom.hex  
34 - end  
35 -  
36 -end  
app/models/watcher.rb
@@ -4,7 +4,7 @@ class Watcher @@ -4,7 +4,7 @@ class Watcher
4 4
5 field :email 5 field :email
6 6
7 - embedded_in :project, :inverse_of => :watchers 7 + embedded_in :app, :inverse_of => :watchers
8 8
9 validates_presence_of :email 9 validates_presence_of :email
10 10
app/views/apps/_configuration_instructions.html.haml 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +%pre
  2 + %code
  3 + :preserve
  4 +
  5 + # Require the hoptoad_notifier gem in you App.
  6 + #
  7 + # Rails 3 - In your Gemfile
  8 + # gem 'hoptoad_notifier'
  9 + #
  10 + # Rails 2 - In environment.rb
  11 + # config.gem 'hoptoad_notifier'
  12 + #
  13 + # Then add the following to config/initializers/hoptoad.rb
  14 + HoptoadNotifier.configure do |config|
  15 + config.api_key = '#{app.api_key}'
  16 + config.host = '#{request.host}'
  17 + config.port = #{request.port}
  18 + # Note: Deployment notifications only work on port 80
  19 + end
  20 +
  21 +
0 \ No newline at end of file 22 \ No newline at end of file
app/views/apps/_fields.html.haml 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +%div.required
  2 + = f.label :name
  3 + = f.text_field :name
  4 +
  5 +%div.checkbox
  6 + = f.check_box :resolve_errs_on_deploy
  7 + = f.label :resolve_errs_on_deploy, 'Resolve errors on deploy'
  8 +
  9 +%fieldset.nested-wrapper
  10 + %legend Watchers
  11 + - f.fields_for :watchers do |w|
  12 + %div.nested
  13 + = w.label :email
  14 + = w.text_field :email
0 \ No newline at end of file 15 \ No newline at end of file
app/views/apps/edit.html.haml 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +- content_for :title, 'Edit App'
  2 +- content_for :action_bar, link_to('cancel', app_path(@app))
  3 +
  4 += form_for @app do |f|
  5 +
  6 + = render 'fields', :f => f
  7 +
  8 + %div= f.submit 'Update'
0 \ No newline at end of file 9 \ No newline at end of file
app/views/apps/index.html.haml 0 → 100644
@@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
  1 +- content_for :title, 'Apps'
  2 +- content_for :action_bar do
  3 + %span= link_to('Add a New App', new_app_path, :class => 'add')
  4 +
  5 +%table.apps
  6 + %thead
  7 + %tr
  8 + %th Name
  9 + %th Last Deploy
  10 + %th Errors
  11 + %tbody
  12 + - @apps.each do |app|
  13 + %tr
  14 + %td.name= link_to app.name, app_path(app)
  15 + %td.deploy= app.last_deploy_at ? app.last_deploy_at.to_s(:micro) : 'n/a'
  16 + %td.count
  17 + - if app.errs.any?
  18 + = link_to app.errs.unresolved.count, app_errs_path(app)
  19 + - else
  20 + \-
  21 + - if @apps.none?
  22 + %tr
  23 + %td{:colspan => 3}
  24 + %em
  25 + No apps here.
  26 + = link_to 'Click here to create your first one', new_app_path
0 \ No newline at end of file 27 \ No newline at end of file
app/views/apps/new.html.haml 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +- content_for :title, 'Add App'
  2 +- content_for :action_bar, link_to('cancel', apps_path)
  3 +
  4 += form_for @app do |f|
  5 +
  6 + = render 'fields', :f => f
  7 +
  8 + %div= f.submit 'Add'
0 \ No newline at end of file 9 \ No newline at end of file
app/views/apps/show.html.haml 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +- content_for :title, @app.name
  2 +- content_for :meta do
  3 + %strong Errors Caught:
  4 + = @app.errs.count
  5 + %strong API Key:
  6 + = @app.api_key
  7 +- content_for :action_bar do
  8 + = link_to 'edit', edit_app_path(@app)
  9 + |
  10 + = link_to 'destroy', app_path(@app), :method => :delete, :confirm => 'Seriously?'
  11 +
  12 +- if @app.errs.none?
  13 + %h3 Setup your app
  14 + = render 'configuration_instructions', :app => @app
  15 +
  16 +%h3 Watchers
  17 +%table.watchers
  18 + %thead
  19 + %tr
  20 + %th Email
  21 + %tbody
  22 + - @app.watchers.each do |watcher|
  23 + %tr
  24 + %td= watcher.email
  25 + - if @app.watchers.none?
  26 + %tr
  27 + %td
  28 + %em Sadly, no one is watching this app
  29 +
  30 +%h3 Errors
  31 += render 'errs/table', :errs => @errs
0 \ No newline at end of file 32 \ No newline at end of file
app/views/errs/_table.html.haml
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 %thead 2 %thead
3 %tr 3 %tr
4 %th 4 %th
5 - - unless @project  
6 - %th Project 5 + - unless @app
  6 + %th App
7 %th What &amp; Where 7 %th What &amp; Where
8 %th Latest 8 %th Latest
9 %th Deploy 9 %th Deploy
@@ -13,15 +13,15 @@ @@ -13,15 +13,15 @@
13 %tr 13 %tr
14 %td.environment 14 %td.environment
15 %abbr{:title => err.environment}= err.environment.chars.first.upcase 15 %abbr{:title => err.environment}= err.environment.chars.first.upcase
16 - - unless @project  
17 - %td.project= err.project.name 16 + - unless @app
  17 + %td.app= err.app.name
18 %td.message 18 %td.message
19 - = link_to err.message, project_err_path(err.project, err) 19 + = link_to err.message, app_err_path(err.app, err)
20 %em= err.where 20 %em= err.where
21 %td.latest #{time_ago_in_words(err.last_notice_at)} ago 21 %td.latest #{time_ago_in_words(err.last_notice_at)} ago
22 - %td.deploy= err.project.last_deploy_at ? err.project.last_deploy_at.to_s(:micro) : 'n/a' 22 + %td.deploy= err.app.last_deploy_at ? err.app.last_deploy_at.to_s(:micro) : 'n/a'
23 %td.count= err.notices.count 23 %td.count= err.notices.count
24 - if errs.none? 24 - if errs.none?
25 %tr 25 %tr
26 - %td{:colspan => (@project ? 5 : 6)} 26 + %td{:colspan => (@app ? 5 : 6)}
27 %em No errors have been caught, yet 27 %em No errors have been caught, yet
28 \ No newline at end of file 28 \ No newline at end of file
app/views/errs/show.html.haml
@@ -11,9 +11,9 @@ @@ -11,9 +11,9 @@
11 - content_for :action_bar do 11 - content_for :action_bar do
12 = will_paginate @notices, :param_name => :notice, :page_links => false 12 = will_paginate @notices, :param_name => :notice, :page_links => false
13 .float-left viewing occurrence #{@notices.current_page} of #{@notices.total_pages} 13 .float-left viewing occurrence #{@notices.current_page} of #{@notices.total_pages}
14 - = link_to "back to '#{@project.name}'", project_path(@project) 14 + = link_to "back to '#{@app.name}'", app_path(@app)
15 | 15 |
16 - = link_to 'resolve', resolve_project_err_path(@project, @err), :method => :put, :confirm => 'Seriously?' if @err.unresolved? 16 + = link_to 'resolve', resolve_app_err_path(@app, @err), :method => :put, :confirm => 'Seriously?' if @err.unresolved?
17 17
18 %h3#summary Summary 18 %h3#summary Summary
19 = render 'notices/summary', :notice => @notice 19 = render 'notices/summary', :notice => @notice
app/views/mailer/deploy_notification.text.erb
1 -<%= @project.name %> was just deployed to <%= @deploy.environment %> by <%= @deploy.username %>. 1 +<%= @app.name %> was just deployed to <%= @deploy.environment %> by <%= @deploy.username %>.
2 2
3 Details: 3 Details:
4 4
5 - What: <%= @project.name %><%= "@#{@deploy.revision}" unless @deploy.revision.blank? %> 5 + What: <%= @app.name %><%= "@#{@deploy.revision}" unless @deploy.revision.blank? %>
6 When: <%= @deploy.created_at.to_s %> 6 When: <%= @deploy.created_at.to_s %>
7 From: <%= @deploy.repository.blank? ? 'n/a' : @deploy.repository %> 7 From: <%= @deploy.repository.blank? ? 'n/a' : @deploy.repository %>
8 8
app/views/mailer/error_notification.text.erb
@@ -2,6 +2,6 @@ An error has just occurred in &lt;%= @notice.err.environment %&gt;: &lt;%= @notice.err.me @@ -2,6 +2,6 @@ An error has just occurred in &lt;%= @notice.err.environment %&gt;: &lt;%= @notice.err.me
2 2
3 This error has occurred <%= pluralize @notice.err.notices.count, 'time' %>. You should really look into it here: 3 This error has occurred <%= pluralize @notice.err.notices.count, 'time' %>. You should really look into it here:
4 4
5 - <%= project_err_notice_url(@project, @notice.err, @notice) %> 5 + <%= app_err_notice_url(@app, @notice.err, @notice) %>
6 6
7 <%= render :partial => 'signature' %> 7 <%= render :partial => 'signature' %>
8 \ No newline at end of file 8 \ No newline at end of file
app/views/notices/_backtrace.html.haml
@@ -8,8 +8,8 @@ @@ -8,8 +8,8 @@
8 %td 8 %td
9 %ul.lines 9 %ul.lines
10 - lines.each do |line| 10 - lines.each do |line|
11 - - in_project = line['file'].gsub!('[PROJECT_ROOT]','') && !line['file'].match(/^\/vendor\//)  
12 - %li{:class => (in_project ? 'in-project' : nil)} 11 + - in_app = line['file'].gsub!('[PROJECT_ROOT]','') && !line['file'].match(/^\/vendor\//)
  12 + %li{:class => (in_app ? 'in-app' : nil)}
13 = line['file'] 13 = line['file']
14 &rarr; 14 &rarr;
15 %strong= line['method'] 15 %strong= line['method']
16 \ No newline at end of file 16 \ No newline at end of file
app/views/projects/_configuration_instructions.html.haml
@@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
1 -%pre  
2 - %code  
3 - :preserve  
4 -  
5 - # Require the hoptoad_notifier gem in you App.  
6 - #  
7 - # Rails 3 - In your Gemfile  
8 - # gem 'hoptoad_notifier'  
9 - #  
10 - # Rails 2 - In environment.rb  
11 - # config.gem 'hoptoad_notifier'  
12 - #  
13 - # Then add the following to config/initializers/hoptoad.rb  
14 - HoptoadNotifier.configure do |config|  
15 - config.api_key = '#{project.api_key}'  
16 - config.host = '#{request.host}'  
17 - config.port = #{request.port}  
18 - # Note: Deployment notifications only work on port 80  
19 - end  
20 -  
21 -  
22 \ No newline at end of file 0 \ No newline at end of file
app/views/projects/_fields.html.haml
@@ -1,14 +0,0 @@ @@ -1,14 +0,0 @@
1 -%div.required  
2 - = f.label :name  
3 - = f.text_field :name  
4 -  
5 -%div.checkbox  
6 - = f.check_box :resolve_errs_on_deploy  
7 - = f.label :resolve_errs_on_deploy, 'Resolve errors on deploy'  
8 -  
9 -%fieldset.nested-wrapper  
10 - %legend Watchers  
11 - - f.fields_for :watchers do |w|  
12 - %div.nested  
13 - = w.label :email  
14 - = w.text_field :email  
15 \ No newline at end of file 0 \ No newline at end of file
app/views/projects/edit.html.haml
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -- content_for :title, 'Edit Project'  
2 -- content_for :action_bar, link_to('cancel', project_path(@project))  
3 -  
4 -= form_for @project do |f|  
5 -  
6 - = render 'fields', :f => f  
7 -  
8 - %div= f.submit 'Update'  
9 \ No newline at end of file 0 \ No newline at end of file
app/views/projects/index.html.haml
@@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
1 -- content_for :title, 'Apps'  
2 -- content_for :action_bar do  
3 - %span= link_to('Add a New App', new_project_path, :class => 'add')  
4 -  
5 -%table.projects  
6 - %thead  
7 - %tr  
8 - %th Name  
9 - %th Last Deploy  
10 - %th Errors  
11 - %tbody  
12 - - @projects.each do |project|  
13 - %tr  
14 - %td.name= link_to project.name, project_path(project)  
15 - %td.deploy= project.last_deploy_at ? project.last_deploy_at.to_s(:micro) : 'n/a'  
16 - %td.count  
17 - - if project.errs.any?  
18 - = link_to project.errs.unresolved.count, project_errs_path(project)  
19 - - else  
20 - \-  
21 - - if @projects.none?  
22 - %tr  
23 - %td{:colspan => 3}  
24 - %em  
25 - No projects here.  
26 - = link_to 'Click here to create your first one', new_project_path  
27 \ No newline at end of file 0 \ No newline at end of file
app/views/projects/new.html.haml
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -- content_for :title, 'Add Project'  
2 -- content_for :action_bar, link_to('cancel', projects_path)  
3 -  
4 -= form_for @project do |f|  
5 -  
6 - = render 'fields', :f => f  
7 -  
8 - %div= f.submit 'Add'  
9 \ No newline at end of file 0 \ No newline at end of file
app/views/projects/show.html.haml
@@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
1 -- content_for :title, @project.name  
2 -- content_for :meta do  
3 - %strong Errors Caught:  
4 - = @project.errs.count  
5 - %strong API Key:  
6 - = @project.api_key  
7 -- content_for :action_bar do  
8 - = link_to 'edit', edit_project_path(@project)  
9 - |  
10 - = link_to 'destroy', project_path(@project), :method => :delete, :confirm => 'Seriously?'  
11 -  
12 -- if @project.errs.none?  
13 - %h3 Setup your app  
14 - = render 'configuration_instructions', :project => @project  
15 -  
16 -%h3 Watchers  
17 -%table.watchers  
18 - %thead  
19 - %tr  
20 - %th Email  
21 - %tbody  
22 - - @project.watchers.each do |watcher|  
23 - %tr  
24 - %td= watcher.email  
25 - - if @project.watchers.none?  
26 - %tr  
27 - %td  
28 - %em Sadly, no one is watching this project  
29 -  
30 -%h3 Errors  
31 -= render 'errs/table', :errs => @errs  
32 \ No newline at end of file 0 \ No newline at end of file
app/views/shared/_navigation.html.haml
1 #nav-bar 1 #nav-bar
2 %ul 2 %ul
3 //%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards) 3 //%li= link_to 'Dashboard', admin_dashboard_path, :class => active_if_here(:dashboards)
4 - %li.projects{:class => active_if_here(:projects)}= link_to 'Apps', projects_path 4 + %li.apps{:class => active_if_here(:apps)}= link_to 'Apps', apps_path
5 %li.errors{:class => active_if_here(:errs)}= link_to 'Errs', errs_path 5 %li.errors{:class => active_if_here(:errs)}= link_to 'Errs', errs_path
6 %div.clear 6 %div.clear
7 \ No newline at end of file 7 \ No newline at end of file
config/initializers/load_config.rb
@@ -5,4 +5,4 @@ config = YAML.load(yaml) @@ -5,4 +5,4 @@ config = YAML.load(yaml)
5 5
6 config.merge!(config.delete(Rails.env)) if config.has_key?(Rails.env) 6 config.merge!(config.delete(Rails.env)) if config.has_key?(Rails.env)
7 7
8 -::App = OpenStruct.new(config)  
9 \ No newline at end of file 8 \ No newline at end of file
  9 +Errbit::Config = OpenStruct.new(config)
10 \ No newline at end of file 10 \ No newline at end of file
config/routes.rb
@@ -12,7 +12,7 @@ Errbit::Application.routes.draw do @@ -12,7 +12,7 @@ Errbit::Application.routes.draw do
12 resources :notices, :only => [:show] 12 resources :notices, :only => [:show]
13 resources :deploys, :only => [:show] 13 resources :deploys, :only => [:show]
14 14
15 - resources :projects do 15 + resources :apps do
16 resources :errs do 16 resources :errs do
17 resources :notices 17 resources :notices
18 member do 18 member do
@@ -21,6 +21,6 @@ Errbit::Application.routes.draw do @@ -21,6 +21,6 @@ Errbit::Application.routes.draw do
21 end 21 end
22 end 22 end
23 23
24 - root :to => 'projects#index' 24 + root :to => 'apps#index'
25 25
26 end 26 end
public/stylesheets/application.css
@@ -86,7 +86,7 @@ header #site-name { @@ -86,7 +86,7 @@ header #site-name {
86 background: transparent 10px 8px no-repeat; 86 background: transparent 10px 8px no-repeat;
87 } 87 }
88 #nav-bar li a:hover { color: #666;} 88 #nav-bar li a:hover { color: #666;}
89 -#nav-bar li.projects a { background-image: url(images/icons/briefcase.png); } 89 +#nav-bar li.apps a { background-image: url(images/icons/briefcase.png); }
90 #nav-bar li.errors a { background-image: url(images/icons/error.png); } 90 #nav-bar li.errors a { background-image: url(images/icons/error.png); }
91 #nav-bar li:hover { 91 #nav-bar li:hover {
92 box-shadow: 0 0 3px #69c; 92 box-shadow: 0 0 3px #69c;
@@ -283,10 +283,10 @@ pre { @@ -283,10 +283,10 @@ pre {
283 color: #AAA; 283 color: #AAA;
284 } 284 }
285 285
286 -/* Projects Table */  
287 -table.projects tbody tr:hover td ,table.errs tbody tr:hover td { background-color: #F2F2F2;} 286 +/* Apps Table */
  287 +table.apps tbody tr:hover td ,table.errs tbody tr:hover td { background-color: #F2F2F2;}
288 288
289 -table.projects td.name, table.errs td.message { 289 +table.apps td.name, table.errs td.message {
290 width: 100%; 290 width: 100%;
291 } 291 }
292 td.deploy { 292 td.deploy {
@@ -349,7 +349,7 @@ table.backtrace ul.lines { @@ -349,7 +349,7 @@ table.backtrace ul.lines {
349 table.backtrace li { 349 table.backtrace li {
350 white-space: nowrap; 350 white-space: nowrap;
351 } 351 }
352 -table.backtrace li.in-project { 352 +table.backtrace li.in-app {
353 color: #2adb2e; 353 color: #2adb2e;
354 background-color: #2f2f2f; 354 background-color: #2f2f2f;
355 } 355 }
356 \ No newline at end of file 356 \ No newline at end of file
spec/controllers/apps_controller_spec.rb 0 → 100644
@@ -0,0 +1,128 @@ @@ -0,0 +1,128 @@
  1 +require 'spec_helper'
  2 +
  3 +describe AppsController do
  4 +
  5 + describe "GET /apps" do
  6 + it 'finds all apps' do
  7 + 3.times { Factory(:app) }
  8 + apps = App.all
  9 + get :index
  10 + assigns(:apps).should == apps
  11 + end
  12 + end
  13 +
  14 + describe "GET /apps/:id" do
  15 + it 'finds the app' do
  16 + app = Factory(:app)
  17 + get :show, :id => app.id
  18 + assigns(:app).should == app
  19 + end
  20 + end
  21 +
  22 + describe "GET /apps/new" do
  23 + it 'instantiates a new app with a prebuilt watcher' do
  24 + get :new
  25 + assigns(:app).should be_a(App)
  26 + assigns(:app).should be_new_record
  27 + assigns(:app).watchers.should_not be_empty
  28 + end
  29 + end
  30 +
  31 + describe "GET /apps/:id/edit" do
  32 + it 'finds the correct app' do
  33 + app = Factory(:app)
  34 + get :edit, :id => app.id
  35 + assigns(:app).should == app
  36 + end
  37 + end
  38 +
  39 + describe "POST /apps" do
  40 + before do
  41 + @app = Factory(:app)
  42 + App.stub(:new).and_return(@app)
  43 + end
  44 +
  45 + context "when the create is successful" do
  46 + before do
  47 + @app.should_receive(:save).and_return(true)
  48 + end
  49 +
  50 + it "should redirect to the app page" do
  51 + post :create, :app => {}
  52 + response.should redirect_to(app_path(@app))
  53 + end
  54 +
  55 + it "should display a message" do
  56 + post :create, :app => {}
  57 + request.flash[:success].should match(/success/)
  58 + end
  59 + end
  60 +
  61 + context "when the create is unsuccessful" do
  62 + it "should render the new page" do
  63 + @app.should_receive(:save).and_return(false)
  64 + post :create, :app => {}
  65 + response.should render_template(:new)
  66 + end
  67 + end
  68 + end
  69 +
  70 + describe "PUT /apps/:id" do
  71 + before do
  72 + @app = Factory(:app)
  73 + App.stub(:find).with(@app.id).and_return(@app)
  74 + end
  75 +
  76 + context "when the update is successful" do
  77 + before do
  78 + @app.should_receive(:update_attributes).and_return(true)
  79 + end
  80 +
  81 + it "should redirect to the app page" do
  82 + put :update, :id => @app.id, :app => {}
  83 + response.should redirect_to(app_path(@app))
  84 + end
  85 +
  86 + it "should display a message" do
  87 + put :update, :id => @app.id, :app => {}
  88 + request.flash[:success].should match(/success/)
  89 + end
  90 + end
  91 +
  92 + context "when the update is unsuccessful" do
  93 + it "should render the edit page" do
  94 + @app.should_receive(:update_attributes).and_return(false)
  95 + put :update, :id => @app.id, :app => {}
  96 + response.should render_template(:edit)
  97 + end
  98 + end
  99 + end
  100 +
  101 + describe "DELETE /apps/:id" do
  102 + before do
  103 + @app = Factory(:app)
  104 + App.stub(:find).with(@app.id).and_return(@app)
  105 + end
  106 +
  107 + it "should find the app" do
  108 + delete :destroy, :id => @app.id
  109 + assigns(:app).should == @app
  110 + end
  111 +
  112 + it "should destroy the app" do
  113 + @app.should_receive(:destroy)
  114 + delete :destroy, :id => @app.id
  115 + end
  116 +
  117 + it "should display a message" do
  118 + delete :destroy, :id => @app.id
  119 + request.flash[:success].should match(/success/)
  120 + end
  121 +
  122 + it "should redirect to the apps page" do
  123 + delete :destroy, :id => @app.id
  124 + response.should redirect_to(apps_path)
  125 + end
  126 + end
  127 +
  128 +end
spec/controllers/deploys_controller_spec.rb
@@ -10,17 +10,17 @@ describe DeploysController do @@ -10,17 +10,17 @@ describe DeploysController do
10 'rails_env' => 'production', 10 'rails_env' => 'production',
11 'scm_revision' => '19d77837eef37902cf5df7e4445c85f392a8d0d5' 11 'scm_revision' => '19d77837eef37902cf5df7e4445c85f392a8d0d5'
12 } 12 }
13 - @project = Factory(:project_with_watcher, :api_key => 'APIKEY') 13 + @app = Factory(:app_with_watcher, :api_key => 'APIKEY')
14 end 14 end
15 15
16 - it 'finds the project via the api key' do  
17 - Project.should_receive(:find_by_api_key!).with('APIKEY').and_return(@project) 16 + it 'finds the app via the api key' do
  17 + App.should_receive(:find_by_api_key!).with('APIKEY').and_return(@app)
18 post :create, :deploy => @params, :api_key => 'APIKEY' 18 post :create, :deploy => @params, :api_key => 'APIKEY'
19 end 19 end
20 20
21 it 'creates a deploy' do 21 it 'creates a deploy' do
22 - Project.stub(:find_by_api_key!).and_return(@project)  
23 - @project.deploys.should_receive(:create!). 22 + App.stub(:find_by_api_key!).and_return(@app)
  23 + @app.deploys.should_receive(:create!).
24 with({ 24 with({
25 :username => 'john.doe', 25 :username => 'john.doe',
26 :environment => 'production', 26 :environment => 'production',
@@ -33,8 +33,8 @@ describe DeploysController do @@ -33,8 +33,8 @@ describe DeploysController do
33 it 'sends an email notification', :focused => true do 33 it 'sends an email notification', :focused => true do
34 post :create, :deploy => @params, :api_key => 'APIKEY' 34 post :create, :deploy => @params, :api_key => 'APIKEY'
35 email = ActionMailer::Base.deliveries.last 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" 36 + email.to.should include(@app.watchers.first.email)
  37 + email.subject.should == "[#{@app.name}] Deployed to production by john.doe"
38 end 38 end
39 39
40 end 40 end
spec/controllers/errs_controller_spec.rb
@@ -2,8 +2,8 @@ require &#39;spec_helper&#39; @@ -2,8 +2,8 @@ require &#39;spec_helper&#39;
2 2
3 describe ErrsController do 3 describe ErrsController do
4 4
5 - let(:project) { Factory(:project) }  
6 - let(:err) { Factory(:err, :project => project) } 5 + let(:app) { Factory(:app) }
  6 + let(:err) { Factory(:err, :app => app) }
7 7
8 describe "GET /errs" do 8 describe "GET /errs" do
9 it "gets a paginated list of unresolved errors" do 9 it "gets a paginated list of unresolved errors" do
@@ -30,61 +30,61 @@ describe ErrsController do @@ -30,61 +30,61 @@ describe ErrsController do
30 end 30 end
31 end 31 end
32 32
33 - describe "GET /projects/:project_id/errs/:id" do 33 + describe "GET /apps/:app_id/errs/:id" do
34 before do 34 before do
35 3.times { Factory(:notice, :err => err)} 35 3.times { Factory(:notice, :err => err)}
36 end 36 end
37 37
38 - it "finds the project" do  
39 - get :show, :project_id => project.id, :id => err.id  
40 - assigns(:project).should == project 38 + it "finds the app" do
  39 + get :show, :app_id => app.id, :id => err.id
  40 + assigns(:app).should == app
41 end 41 end
42 42
43 it "finds the err" do 43 it "finds the err" do
44 - get :show, :project_id => project.id, :id => err.id 44 + get :show, :app_id => app.id, :id => err.id
45 assigns(:err).should == err 45 assigns(:err).should == err
46 end 46 end
47 47
48 it "paginates the notices, 1 at a time" do 48 it "paginates the notices, 1 at a time" do
49 - Project.stub(:find).with(project.id).and_return(project)  
50 - project.errs.stub(:find).with(err.id).and_return(err) 49 + App.stub(:find).with(app.id).and_return(app)
  50 + app.errs.stub(:find).with(err.id).and_return(err)
51 err.notices.should_receive(:ordered).and_return(proxy = stub('proxy')) 51 err.notices.should_receive(:ordered).and_return(proxy = stub('proxy'))
52 proxy.should_receive(:paginate).with(:page => 3, :per_page => 1). 52 proxy.should_receive(:paginate).with(:page => 3, :per_page => 1).
53 and_return(WillPaginate::Collection.new(1,1) << err.notices.first) 53 and_return(WillPaginate::Collection.new(1,1) << err.notices.first)
54 - get :show, :project_id => project.id, :id => err.id 54 + get :show, :app_id => app.id, :id => err.id
55 end 55 end
56 end 56 end
57 57
58 - describe "PUT /projects/:project_id/errs/:id/resolve" do 58 + describe "PUT /apps/:app_id/errs/:id/resolve" do
59 before do 59 before do
60 @err = Factory(:err) 60 @err = Factory(:err)
61 - Project.stub(:find).with(@err.project.id).and_return(@err.project)  
62 - @err.project.errs.stub(:unresolved). 61 + App.stub(:find).with(@err.app.id).and_return(@err.app)
  62 + @err.app.errs.stub(:unresolved).
63 and_return(stub('proxy', :find => @err)) 63 and_return(stub('proxy', :find => @err))
64 @err.stub(:resolve!) 64 @err.stub(:resolve!)
65 end 65 end
66 66
67 - it 'finds the project and the err' do  
68 - Project.should_receive(:find).with(@err.project.id).and_return(@err.project)  
69 - @err.project.errs.should_receive(:unresolved). 67 + it 'finds the app and the err' do
  68 + App.should_receive(:find).with(@err.app.id).and_return(@err.app)
  69 + @err.app.errs.should_receive(:unresolved).
70 and_return(mock('proxy', :find => @err)) 70 and_return(mock('proxy', :find => @err))
71 - put :resolve, :project_id => @err.project.id, :id => @err.id  
72 - assigns(:project).should == @err.project 71 + put :resolve, :app_id => @err.app.id, :id => @err.id
  72 + assigns(:app).should == @err.app
73 assigns(:err).should == @err 73 assigns(:err).should == @err
74 end 74 end
75 75
76 it "should resolve the issue" do 76 it "should resolve the issue" do
77 @err.should_receive(:resolve!).and_return(true) 77 @err.should_receive(:resolve!).and_return(true)
78 - put :resolve, :project_id => @err.project.id, :id => @err.id 78 + put :resolve, :app_id => @err.app.id, :id => @err.id
79 end 79 end
80 80
81 it "should display a message" do 81 it "should display a message" do
82 - put :resolve, :project_id => @err.project.id, :id => @err.id 82 + put :resolve, :app_id => @err.app.id, :id => @err.id
83 request.flash[:success].should match(/Great news/) 83 request.flash[:success].should match(/Great news/)
84 end 84 end
85 85
86 it "should redirect do the errs page" do 86 it "should redirect do the errs page" do
87 - put :resolve, :project_id => @err.project.id, :id => @err.id 87 + put :resolve, :app_id => @err.app.id, :id => @err.id
88 response.should redirect_to(errs_path) 88 response.should redirect_to(errs_path)
89 end 89 end
90 end 90 end
spec/controllers/notices_controller_spec.rb
@@ -5,8 +5,8 @@ describe NoticesController do @@ -5,8 +5,8 @@ describe NoticesController do
5 context 'POST[XML] notices#create' do 5 context 'POST[XML] notices#create' do
6 before do 6 before do
7 @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read 7 @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read
8 - @project = Factory(:project_with_watcher)  
9 - Project.stub(:find_by_api_key!).and_return(@project) 8 + @app = Factory(:app_with_watcher)
  9 + App.stub(:find_by_api_key!).and_return(@app)
10 @notice = Notice.from_xml(@xml) 10 @notice = Notice.from_xml(@xml)
11 11
12 request.env['Content-type'] = 'text/xml' 12 request.env['Content-type'] = 'text/xml'
@@ -22,7 +22,7 @@ describe NoticesController do @@ -22,7 +22,7 @@ describe NoticesController do
22 it "sends a notification email" do 22 it "sends a notification email" do
23 post :create 23 post :create
24 email = ActionMailer::Base.deliveries.last 24 email = ActionMailer::Base.deliveries.last
25 - email.to.should include(@project.watchers.first.email) 25 + email.to.should include(@app.watchers.first.email)
26 email.subject.should include(@notice.err.message) 26 email.subject.should include(@notice.err.message)
27 end 27 end
28 end 28 end
spec/controllers/projects_controller_spec.rb
@@ -1,128 +0,0 @@ @@ -1,128 +0,0 @@
1 -require 'spec_helper'  
2 -  
3 -describe ProjectsController do  
4 -  
5 - describe "GET /projects" do  
6 - it 'finds all projects' do  
7 - 3.times { Factory(:project) }  
8 - projects = Project.all  
9 - get :index  
10 - assigns(:projects).should == projects  
11 - end  
12 - end  
13 -  
14 - describe "GET /projects/:id" do  
15 - it 'finds the project' do  
16 - project = Factory(:project)  
17 - get :show, :id => project.id  
18 - assigns(:project).should == project  
19 - end  
20 - end  
21 -  
22 - describe "GET /projects/new" do  
23 - it 'instantiates a new project with a prebuilt watcher' do  
24 - get :new  
25 - assigns(:project).should be_a(Project)  
26 - assigns(:project).should be_new_record  
27 - assigns(:project).watchers.should_not be_empty  
28 - end  
29 - end  
30 -  
31 - describe "GET /projects/:id/edit" do  
32 - it 'finds the correct project' do  
33 - project = Factory(:project)  
34 - get :edit, :id => project.id  
35 - assigns(:project).should == project  
36 - end  
37 - end  
38 -  
39 - describe "POST /projects" do  
40 - before do  
41 - @project = Factory(:project)  
42 - Project.stub(:new).and_return(@project)  
43 - end  
44 -  
45 - context "when the create is successful" do  
46 - before do  
47 - @project.should_receive(:save).and_return(true)  
48 - end  
49 -  
50 - it "should redirect to the project page" do  
51 - post :create, :project => {}  
52 - response.should redirect_to(project_path(@project))  
53 - end  
54 -  
55 - it "should display a message" do  
56 - post :create, :project => {}  
57 - request.flash[:success].should match(/success/)  
58 - end  
59 - end  
60 -  
61 - context "when the create is unsuccessful" do  
62 - it "should render the new page" do  
63 - @project.should_receive(:save).and_return(false)  
64 - post :create, :project => {}  
65 - response.should render_template(:new)  
66 - end  
67 - end  
68 - end  
69 -  
70 - describe "PUT /projects/:id" do  
71 - before do  
72 - @project = Factory(:project)  
73 - Project.stub(:find).with(@project.id).and_return(@project)  
74 - end  
75 -  
76 - context "when the update is successful" do  
77 - before do  
78 - @project.should_receive(:update_attributes).and_return(true)  
79 - end  
80 -  
81 - it "should redirect to the project page" do  
82 - put :update, :id => @project.id, :project => {}  
83 - response.should redirect_to(project_path(@project))  
84 - end  
85 -  
86 - it "should display a message" do  
87 - put :update, :id => @project.id, :project => {}  
88 - request.flash[:success].should match(/success/)  
89 - end  
90 - end  
91 -  
92 - context "when the update is unsuccessful" do  
93 - it "should render the edit page" do  
94 - @project.should_receive(:update_attributes).and_return(false)  
95 - put :update, :id => @project.id, :project => {}  
96 - response.should render_template(:edit)  
97 - end  
98 - end  
99 - end  
100 -  
101 - describe "DELETE /projects/:id" do  
102 - before do  
103 - @project = Factory(:project)  
104 - Project.stub(:find).with(@project.id).and_return(@project)  
105 - end  
106 -  
107 - it "should find the project" do  
108 - delete :destroy, :id => @project.id  
109 - assigns(:project).should == @project  
110 - end  
111 -  
112 - it "should destroy the project" do  
113 - @project.should_receive(:destroy)  
114 - delete :destroy, :id => @project.id  
115 - end  
116 -  
117 - it "should display a message" do  
118 - delete :destroy, :id => @project.id  
119 - request.flash[:success].should match(/success/)  
120 - end  
121 -  
122 - it "should redirect to the projects page" do  
123 - delete :destroy, :id => @project.id  
124 - response.should redirect_to(projects_path)  
125 - end  
126 - end  
127 -  
128 -end  
spec/factories/err_factories.rb
1 Factory.define :err do |e| 1 Factory.define :err do |e|
2 - e.project {|p| p.association :project} 2 + e.app {|p| p.association :app}
3 e.klass 'FooError' 3 e.klass 'FooError'
4 e.component 'foo' 4 e.component 'foo'
5 e.action 'bar' 5 e.action 'bar'
spec/factories/project_factories.rb
1 -Factory.sequence(:project_name) {|n| "Project ##{n}"} 1 +Factory.sequence(:app_name) {|n| "App ##{n}"}
2 Factory.sequence(:email) {|n| "email#{n}@example.com"} 2 Factory.sequence(:email) {|n| "email#{n}@example.com"}
3 3
4 -Factory.define(:project) do |p|  
5 - p.name { Factory.next :project_name } 4 +Factory.define(:app) do |p|
  5 + p.name { Factory.next :app_name }
6 end 6 end
7 7
8 -Factory.define(:project_with_watcher, :parent => :project) do |p|  
9 - p.after_create {|project|  
10 - Factory(:watcher, :project => project) 8 +Factory.define(:app_with_watcher, :parent => :app) do |p|
  9 + p.after_create {|app|
  10 + Factory(:watcher, :app => app)
11 } 11 }
12 end 12 end
13 13
14 Factory.define(:watcher) do |w| 14 Factory.define(:watcher) do |w|
15 - w.project {|p| p.association :project} 15 + w.app {|p| p.association :app}
16 w.email { Factory.next :email } 16 w.email { Factory.next :email }
17 end 17 end
18 18
19 Factory.define(:deploy) do |d| 19 Factory.define(:deploy) do |d|
20 - d.project {|p| p.association :project} 20 + d.app {|p| p.association :app}
21 d.username 'clyde.frog' 21 d.username 'clyde.frog'
22 d.repository 'git@github.com/jdpace/errbit.git' 22 d.repository 'git@github.com/jdpace/errbit.git'
23 d.environment 'production' 23 d.environment 'production'
spec/models/app_spec.rb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +require 'spec_helper'
  2 +
  3 +describe App do
  4 +
  5 + context 'validations' do
  6 + it 'requires a name' do
  7 + app = Factory.build(:app, :name => nil)
  8 + app.should_not be_valid
  9 + app.errors[:name].should include("can't be blank")
  10 + end
  11 +
  12 + it 'requires unique names' do
  13 + Factory(:app, :name => 'Errbit')
  14 + app = Factory.build(:app, :name => 'Errbit')
  15 + app.should_not be_valid
  16 + app.errors[:name].should include('is already taken')
  17 + end
  18 +
  19 + it 'requires unique api_keys' do
  20 + Factory(:app, :api_key => 'APIKEY')
  21 + app = Factory.build(:app, :api_key => 'APIKEY')
  22 + app.should_not be_valid
  23 + app.errors[:api_key].should include('is already taken')
  24 + end
  25 + end
  26 +
  27 + context 'being created' do
  28 + it 'generates a new api-key' do
  29 + app = Factory.build(:app)
  30 + app.api_key.should be_nil
  31 + app.save
  32 + app.api_key.should_not be_nil
  33 + end
  34 +
  35 + it 'generates a correct api-key' do
  36 + app = Factory(:app)
  37 + app.api_key.should match(/^[a-f0-9]{32}$/)
  38 + end
  39 + end
  40 +
  41 +end
spec/models/deploy_spec.rb
@@ -20,24 +20,24 @@ describe Deploy do @@ -20,24 +20,24 @@ describe Deploy do
20 it 'should send an email notification' do 20 it 'should send an email notification' do
21 Mailer.should_receive(:deploy_notification). 21 Mailer.should_receive(:deploy_notification).
22 and_return(mock('email', :deliver => true)) 22 and_return(mock('email', :deliver => true))
23 - Factory(:deploy, :project => Factory(:project_with_watcher)) 23 + Factory(:deploy, :app => Factory(:app_with_watcher))
24 end 24 end
25 25
26 - context 'when the project has resolve_errs_on_deploy set to false' do  
27 - it 'should not resolve the projects errs' do  
28 - project = Factory(:project, :resolve_errs_on_deploy => false)  
29 - @errs = 3.times.inject([]) {|errs,_| errs << Factory(:err, :resolved => false, :project => project)}  
30 - Factory(:deploy, :project => project)  
31 - project.reload.errs.none?{|err| err.resolved?}.should == true 26 + context 'when the app has resolve_errs_on_deploy set to false' do
  27 + it 'should not resolve the apps errs' do
  28 + app = Factory(:app, :resolve_errs_on_deploy => false)
  29 + @errs = 3.times.inject([]) {|errs,_| errs << Factory(:err, :resolved => false, :app => app)}
  30 + Factory(:deploy, :app => app)
  31 + app.reload.errs.none?{|err| err.resolved?}.should == true
32 end 32 end
33 end 33 end
34 34
35 - context 'when the project has resolve_errs_on_deploy set to true' do  
36 - it 'should not resolve the projects errs' do  
37 - project = Factory(:project, :resolve_errs_on_deploy => true)  
38 - @errs = 3.times.inject([]) {|errs,_| errs << Factory(:err, :resolved => false, :project => project)}  
39 - Factory(:deploy, :project => project)  
40 - project.reload.errs.all?{|err| err.resolved?}.should == true 35 + context 'when the app has resolve_errs_on_deploy set to true' do
  36 + it 'should not resolve the apps errs' do
  37 + app = Factory(:app, :resolve_errs_on_deploy => true)
  38 + @errs = 3.times.inject([]) {|errs,_| errs << Factory(:err, :resolved => false, :app => app)}
  39 + Factory(:deploy, :app => app)
  40 + app.reload.errs.all?{|err| err.resolved?}.should == true
41 end 41 end
42 end 42 end
43 end 43 end
spec/models/err_spec.rb
@@ -18,9 +18,9 @@ describe Err do @@ -18,9 +18,9 @@ describe Err do
18 18
19 context '#for' do 19 context '#for' do
20 before do 20 before do
21 - @project = Factory(:project) 21 + @app = Factory(:app)
22 @conditions = { 22 @conditions = {
23 - :project => @project, 23 + :app => @app,
24 :klass => 'Whoops', 24 :klass => 'Whoops',
25 :component => 'Foo', 25 :component => 'Foo',
26 :action => 'bar', 26 :action => 'bar',
@@ -33,12 +33,12 @@ describe Err do @@ -33,12 +33,12 @@ describe Err do
33 Err.for(@conditions).should == existing 33 Err.for(@conditions).should == existing
34 end 34 end
35 35
36 - it 'assigns the returned error to the given project' do  
37 - Err.for(@conditions).project.should == @project 36 + it 'assigns the returned error to the given app' do
  37 + Err.for(@conditions).app.should == @app
38 end 38 end
39 39
40 it 'creates a new error if a matching one does not already exist' do 40 it 'creates a new error if a matching one does not already exist' do
41 - Err.where(@conditions.except(:project)).exists?.should == false 41 + Err.where(@conditions.except(:app)).exists?.should == false
42 lambda { 42 lambda {
43 Err.for(@conditions) 43 Err.for(@conditions)
44 }.should change(Err,:count).by(1) 44 }.should change(Err,:count).by(1)
spec/models/notice_spec.rb
@@ -25,18 +25,18 @@ describe Notice do @@ -25,18 +25,18 @@ describe Notice do
25 context '#from_xml' do 25 context '#from_xml' do
26 before do 26 before do
27 @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read 27 @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read
28 - @project = Factory(:project, :api_key => 'APIKEY') 28 + @app = Factory(:app, :api_key => 'APIKEY')
29 Digest::MD5.stub(:hexdigest).and_return('fingerprintdigest') 29 Digest::MD5.stub(:hexdigest).and_return('fingerprintdigest')
30 end 30 end
31 31
32 - it 'finds the correct project' do 32 + it 'finds the correct app' do
33 @notice = Notice.from_xml(@xml) 33 @notice = Notice.from_xml(@xml)
34 - @notice.err.project.should == @project 34 + @notice.err.app.should == @app
35 end 35 end
36 36
37 it 'finds the correct error for the notice' do 37 it 'finds the correct error for the notice' do
38 Err.should_receive(:for).with({ 38 Err.should_receive(:for).with({
39 - :project => @project, 39 + :app => @app,
40 :klass => 'HoptoadTestingException', 40 :klass => 'HoptoadTestingException',
41 :component => 'application', 41 :component => 'application',
42 :action => 'verify', 42 :action => 'verify',
@@ -87,11 +87,11 @@ describe Notice do @@ -87,11 +87,11 @@ describe Notice do
87 87
88 describe "email notifications" do 88 describe "email notifications" do
89 before do 89 before do
90 - @project = Factory(:project_with_watcher)  
91 - @error = Factory(:err, :project => @project) 90 + @app = Factory(:app_with_watcher)
  91 + @error = Factory(:err, :app => @app)
92 end 92 end
93 93
94 - App.email_at_notices.each do |threshold| 94 + Errbit::Config.email_at_notices.each do |threshold|
95 it "sends an email notification after #{threshold} notice(s)" do 95 it "sends an email notification after #{threshold} notice(s)" do
96 @error.notices.stub(:count).and_return(threshold) 96 @error.notices.stub(:count).and_return(threshold)
97 Mailer.should_receive(:error_notification). 97 Mailer.should_receive(:error_notification).
spec/models/project_spec.rb
@@ -1,41 +0,0 @@ @@ -1,41 +0,0 @@
1 -require 'spec_helper'  
2 -  
3 -describe Project do  
4 -  
5 - context 'validations' do  
6 - it 'requires a name' do  
7 - project = Factory.build(:project, :name => nil)  
8 - project.should_not be_valid  
9 - project.errors[:name].should include("can't be blank")  
10 - end  
11 -  
12 - it 'requires unique names' do  
13 - Factory(:project, :name => 'Errbit')  
14 - project = Factory.build(:project, :name => 'Errbit')  
15 - project.should_not be_valid  
16 - project.errors[:name].should include('is already taken')  
17 - end  
18 -  
19 - it 'requires unique api_keys' do  
20 - Factory(:project, :api_key => 'APIKEY')  
21 - project = Factory.build(:project, :api_key => 'APIKEY')  
22 - project.should_not be_valid  
23 - project.errors[:api_key].should include('is already taken')  
24 - end  
25 - end  
26 -  
27 - context 'being created' do  
28 - it 'generates a new api-key' do  
29 - project = Factory.build(:project)  
30 - project.api_key.should be_nil  
31 - project.save  
32 - project.api_key.should_not be_nil  
33 - end  
34 -  
35 - it 'generates a correct api-key' do  
36 - project = Factory(:project)  
37 - project.api_key.should match(/^[a-f0-9]{32}$/)  
38 - end  
39 - end  
40 -  
41 -end