Commit e77f238e661fdff86f4ee94c1c8262012ba592b5
1 parent
a689d49b
Exists in
master
and in
1 other branch
Rename Project to App
Showing
44 changed files
with
479 additions
and
479 deletions
Show diff stats
| ... | ... | @@ -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 | 1 | class DeploysController < ApplicationController |
| 2 | 2 | |
| 3 | 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 | 6 | :username => params[:deploy][:local_username], |
| 7 | 7 | :environment => params[:deploy][:rails_env], |
| 8 | 8 | :repository => params[:deploy][:scm_repository], | ... | ... |
app/controllers/errs_controller.rb
| ... | ... | @@ -9,15 +9,15 @@ class ErrsController < ApplicationController |
| 9 | 9 | end |
| 10 | 10 | |
| 11 | 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 | 14 | @notices = @err.notices.ordered.paginate(:page => (params[:notice] || @err.notices.count), :per_page => 1) |
| 15 | 15 | @notice = @notices.first |
| 16 | 16 | end |
| 17 | 17 | |
| 18 | 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 | 22 | # Deal with bug in mogoid where find is returning an Enumberable obj |
| 23 | 23 | @err = @err.first if @err.respond_to?(:first) | ... | ... |
app/controllers/projects_controller.rb
| ... | ... | @@ -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 | 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 | 5 | def error_notification(notice) |
| 6 | 6 | @notice = notice |
| 7 | - @project = notice.err.project | |
| 7 | + @app = notice.err.app | |
| 8 | 8 | |
| 9 | 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 | 13 | end |
| 14 | 14 | |
| 15 | 15 | def deploy_notification(deploy) |
| 16 | 16 | @deploy = deploy |
| 17 | - @project = deploy.project | |
| 17 | + @app = deploy.app | |
| 18 | 18 | |
| 19 | 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 | 23 | end |
| 24 | 24 | ... | ... |
| ... | ... | @@ -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 | 7 | field :environment |
| 8 | 8 | field :revision |
| 9 | 9 | |
| 10 | - embedded_in :project, :inverse_of => :deploys | |
| 10 | + embedded_in :app, :inverse_of => :deploys | |
| 11 | 11 | |
| 12 | 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 | 15 | validates_presence_of :username, :environment |
| 16 | 16 | |
| ... | ... | @@ -18,18 +18,18 @@ class Deploy |
| 18 | 18 | Mailer.deploy_notification(self).deliver |
| 19 | 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 | 23 | end |
| 24 | 24 | |
| 25 | 25 | protected |
| 26 | 26 | |
| 27 | 27 | def should_notify? |
| 28 | - project.watchers.any? | |
| 28 | + app.watchers.any? | |
| 29 | 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 | 33 | end |
| 34 | 34 | |
| 35 | 35 | end | ... | ... |
app/models/err.rb
| ... | ... | @@ -10,7 +10,7 @@ class Err |
| 10 | 10 | field :last_notice_at, :type => DateTime |
| 11 | 11 | field :resolved, :type => Boolean, :default => false |
| 12 | 12 | |
| 13 | - referenced_in :project | |
| 13 | + referenced_in :app | |
| 14 | 14 | embeds_many :notices |
| 15 | 15 | |
| 16 | 16 | validates_presence_of :klass, :environment |
| ... | ... | @@ -20,8 +20,8 @@ class Err |
| 20 | 20 | scope :ordered, order_by(:last_notice_at.desc) |
| 21 | 21 | |
| 22 | 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 | 25 | end |
| 26 | 26 | |
| 27 | 27 | def resolve! | ... | ... |
app/models/notice.rb
| ... | ... | @@ -21,13 +21,13 @@ class Notice |
| 21 | 21 | |
| 22 | 22 | def self.from_xml(hoptoad_xml) |
| 23 | 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 | 26 | hoptoad_notice['request']['component'] = 'unknown' if hoptoad_notice['request']['component'].blank? |
| 27 | 27 | hoptoad_notice['request']['action'] = nil if hoptoad_notice['request']['action'].blank? |
| 28 | 28 | |
| 29 | 29 | error = Err.for({ |
| 30 | - :project => project, | |
| 30 | + :app => app, | |
| 31 | 31 | :klass => hoptoad_notice['error']['class'], |
| 32 | 32 | :component => hoptoad_notice['request']['component'], |
| 33 | 33 | :action => hoptoad_notice['request']['action'], |
| ... | ... | @@ -71,7 +71,7 @@ class Notice |
| 71 | 71 | protected |
| 72 | 72 | |
| 73 | 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 | 75 | end |
| 76 | 76 | |
| 77 | 77 | end |
| 78 | 78 | \ No newline at end of file | ... | ... |
app/models/project.rb
| ... | ... | @@ -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
| ... | ... | @@ -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 | 22 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -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 | 15 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -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 | 27 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -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 | 32 | \ No newline at end of file | ... | ... |
app/views/errs/_table.html.haml
| ... | ... | @@ -2,8 +2,8 @@ |
| 2 | 2 | %thead |
| 3 | 3 | %tr |
| 4 | 4 | %th |
| 5 | - - unless @project | |
| 6 | - %th Project | |
| 5 | + - unless @app | |
| 6 | + %th App | |
| 7 | 7 | %th What & Where |
| 8 | 8 | %th Latest |
| 9 | 9 | %th Deploy |
| ... | ... | @@ -13,15 +13,15 @@ |
| 13 | 13 | %tr |
| 14 | 14 | %td.environment |
| 15 | 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 | 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 | 20 | %em= err.where |
| 21 | 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 | 23 | %td.count= err.notices.count |
| 24 | 24 | - if errs.none? |
| 25 | 25 | %tr |
| 26 | - %td{:colspan => (@project ? 5 : 6)} | |
| 26 | + %td{:colspan => (@app ? 5 : 6)} | |
| 27 | 27 | %em No errors have been caught, yet |
| 28 | 28 | \ No newline at end of file | ... | ... |
app/views/errs/show.html.haml
| ... | ... | @@ -11,9 +11,9 @@ |
| 11 | 11 | - content_for :action_bar do |
| 12 | 12 | = will_paginate @notices, :param_name => :notice, :page_links => false |
| 13 | 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 | 18 | %h3#summary Summary |
| 19 | 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 | 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 | 6 | When: <%= @deploy.created_at.to_s %> |
| 7 | 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 <%= @notice.err.environment %>: <%= @notice.err.me |
| 2 | 2 | |
| 3 | 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 | 7 | <%= render :partial => 'signature' %> |
| 8 | 8 | \ No newline at end of file | ... | ... |
app/views/notices/_backtrace.html.haml
| ... | ... | @@ -8,8 +8,8 @@ |
| 8 | 8 | %td |
| 9 | 9 | %ul.lines |
| 10 | 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 | 13 | = line['file'] |
| 14 | 14 | → |
| 15 | 15 | %strong= line['method'] |
| 16 | 16 | \ No newline at end of file | ... | ... |
app/views/projects/_configuration_instructions.html.haml
| ... | ... | @@ -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 | 0 | \ No newline at end of file |
app/views/projects/_fields.html.haml
| ... | ... | @@ -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 | 0 | \ No newline at end of file |
app/views/projects/edit.html.haml
app/views/projects/index.html.haml
| ... | ... | @@ -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 | 0 | \ No newline at end of file |
app/views/projects/new.html.haml
app/views/projects/show.html.haml
| ... | ... | @@ -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 | 0 | \ No newline at end of file |
app/views/shared/_navigation.html.haml
| 1 | 1 | #nav-bar |
| 2 | 2 | %ul |
| 3 | 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 | 5 | %li.errors{:class => active_if_here(:errs)}= link_to 'Errs', errs_path |
| 6 | 6 | %div.clear |
| 7 | 7 | \ No newline at end of file | ... | ... |
config/initializers/load_config.rb
config/routes.rb
| ... | ... | @@ -12,7 +12,7 @@ Errbit::Application.routes.draw do |
| 12 | 12 | resources :notices, :only => [:show] |
| 13 | 13 | resources :deploys, :only => [:show] |
| 14 | 14 | |
| 15 | - resources :projects do | |
| 15 | + resources :apps do | |
| 16 | 16 | resources :errs do |
| 17 | 17 | resources :notices |
| 18 | 18 | member do |
| ... | ... | @@ -21,6 +21,6 @@ Errbit::Application.routes.draw do |
| 21 | 21 | end |
| 22 | 22 | end |
| 23 | 23 | |
| 24 | - root :to => 'projects#index' | |
| 24 | + root :to => 'apps#index' | |
| 25 | 25 | |
| 26 | 26 | end | ... | ... |
public/stylesheets/application.css
| ... | ... | @@ -86,7 +86,7 @@ header #site-name { |
| 86 | 86 | background: transparent 10px 8px no-repeat; |
| 87 | 87 | } |
| 88 | 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 | 90 | #nav-bar li.errors a { background-image: url(images/icons/error.png); } |
| 91 | 91 | #nav-bar li:hover { |
| 92 | 92 | box-shadow: 0 0 3px #69c; |
| ... | ... | @@ -283,10 +283,10 @@ pre { |
| 283 | 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 | 290 | width: 100%; |
| 291 | 291 | } |
| 292 | 292 | td.deploy { |
| ... | ... | @@ -349,7 +349,7 @@ table.backtrace ul.lines { |
| 349 | 349 | table.backtrace li { |
| 350 | 350 | white-space: nowrap; |
| 351 | 351 | } |
| 352 | -table.backtrace li.in-project { | |
| 352 | +table.backtrace li.in-app { | |
| 353 | 353 | color: #2adb2e; |
| 354 | 354 | background-color: #2f2f2f; |
| 355 | 355 | } |
| 356 | 356 | \ No newline at end of file | ... | ... |
| ... | ... | @@ -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 | 10 | 'rails_env' => 'production', |
| 11 | 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 | 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 | 18 | post :create, :deploy => @params, :api_key => 'APIKEY' |
| 19 | 19 | end |
| 20 | 20 | |
| 21 | 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 | 24 | with({ |
| 25 | 25 | :username => 'john.doe', |
| 26 | 26 | :environment => 'production', |
| ... | ... | @@ -33,8 +33,8 @@ describe DeploysController do |
| 33 | 33 | it 'sends an email notification', :focused => true do |
| 34 | 34 | post :create, :deploy => @params, :api_key => 'APIKEY' |
| 35 | 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 | 38 | end |
| 39 | 39 | |
| 40 | 40 | end | ... | ... |
spec/controllers/errs_controller_spec.rb
| ... | ... | @@ -2,8 +2,8 @@ require 'spec_helper' |
| 2 | 2 | |
| 3 | 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 | 8 | describe "GET /errs" do |
| 9 | 9 | it "gets a paginated list of unresolved errors" do |
| ... | ... | @@ -30,61 +30,61 @@ describe ErrsController do |
| 30 | 30 | end |
| 31 | 31 | end |
| 32 | 32 | |
| 33 | - describe "GET /projects/:project_id/errs/:id" do | |
| 33 | + describe "GET /apps/:app_id/errs/:id" do | |
| 34 | 34 | before do |
| 35 | 35 | 3.times { Factory(:notice, :err => err)} |
| 36 | 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 | 41 | end |
| 42 | 42 | |
| 43 | 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 | 45 | assigns(:err).should == err |
| 46 | 46 | end |
| 47 | 47 | |
| 48 | 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 | 51 | err.notices.should_receive(:ordered).and_return(proxy = stub('proxy')) |
| 52 | 52 | proxy.should_receive(:paginate).with(:page => 3, :per_page => 1). |
| 53 | 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 | 55 | end |
| 56 | 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 | 59 | before do |
| 60 | 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 | 63 | and_return(stub('proxy', :find => @err)) |
| 64 | 64 | @err.stub(:resolve!) |
| 65 | 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 | 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 | 73 | assigns(:err).should == @err |
| 74 | 74 | end |
| 75 | 75 | |
| 76 | 76 | it "should resolve the issue" do |
| 77 | 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 | 79 | end |
| 80 | 80 | |
| 81 | 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 | 83 | request.flash[:success].should match(/Great news/) |
| 84 | 84 | end |
| 85 | 85 | |
| 86 | 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 | 88 | response.should redirect_to(errs_path) |
| 89 | 89 | end |
| 90 | 90 | end | ... | ... |
spec/controllers/notices_controller_spec.rb
| ... | ... | @@ -5,8 +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 = 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 | 10 | @notice = Notice.from_xml(@xml) |
| 11 | 11 | |
| 12 | 12 | request.env['Content-type'] = 'text/xml' |
| ... | ... | @@ -22,7 +22,7 @@ describe NoticesController do |
| 22 | 22 | it "sends a notification email" do |
| 23 | 23 | post :create |
| 24 | 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 | 26 | email.subject.should include(@notice.err.message) |
| 27 | 27 | end |
| 28 | 28 | end | ... | ... |
spec/controllers/projects_controller_spec.rb
| ... | ... | @@ -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
spec/factories/project_factories.rb
| 1 | -Factory.sequence(:project_name) {|n| "Project ##{n}"} | |
| 1 | +Factory.sequence(:app_name) {|n| "App ##{n}"} | |
| 2 | 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 | 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 | 12 | end |
| 13 | 13 | |
| 14 | 14 | Factory.define(:watcher) do |w| |
| 15 | - w.project {|p| p.association :project} | |
| 15 | + w.app {|p| p.association :app} | |
| 16 | 16 | w.email { Factory.next :email } |
| 17 | 17 | end |
| 18 | 18 | |
| 19 | 19 | Factory.define(:deploy) do |d| |
| 20 | - d.project {|p| p.association :project} | |
| 20 | + d.app {|p| p.association :app} | |
| 21 | 21 | d.username 'clyde.frog' |
| 22 | 22 | d.repository 'git@github.com/jdpace/errbit.git' |
| 23 | 23 | d.environment 'production' | ... | ... |
| ... | ... | @@ -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 | 20 | it 'should send an email notification' do |
| 21 | 21 | Mailer.should_receive(:deploy_notification). |
| 22 | 22 | and_return(mock('email', :deliver => true)) |
| 23 | - Factory(:deploy, :project => Factory(:project_with_watcher)) | |
| 23 | + Factory(:deploy, :app => Factory(:app_with_watcher)) | |
| 24 | 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 | 32 | end |
| 33 | 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 | 41 | end |
| 42 | 42 | end |
| 43 | 43 | end | ... | ... |
spec/models/err_spec.rb
| ... | ... | @@ -18,9 +18,9 @@ describe Err do |
| 18 | 18 | |
| 19 | 19 | context '#for' do |
| 20 | 20 | before do |
| 21 | - @project = Factory(:project) | |
| 21 | + @app = Factory(:app) | |
| 22 | 22 | @conditions = { |
| 23 | - :project => @project, | |
| 23 | + :app => @app, | |
| 24 | 24 | :klass => 'Whoops', |
| 25 | 25 | :component => 'Foo', |
| 26 | 26 | :action => 'bar', |
| ... | ... | @@ -33,12 +33,12 @@ describe Err do |
| 33 | 33 | Err.for(@conditions).should == existing |
| 34 | 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 | 38 | end |
| 39 | 39 | |
| 40 | 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 | 42 | lambda { |
| 43 | 43 | Err.for(@conditions) |
| 44 | 44 | }.should change(Err,:count).by(1) | ... | ... |
spec/models/notice_spec.rb
| ... | ... | @@ -25,18 +25,18 @@ describe Notice do |
| 25 | 25 | context '#from_xml' do |
| 26 | 26 | before do |
| 27 | 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 | 29 | Digest::MD5.stub(:hexdigest).and_return('fingerprintdigest') |
| 30 | 30 | end |
| 31 | 31 | |
| 32 | - it 'finds the correct project' do | |
| 32 | + it 'finds the correct app' do | |
| 33 | 33 | @notice = Notice.from_xml(@xml) |
| 34 | - @notice.err.project.should == @project | |
| 34 | + @notice.err.app.should == @app | |
| 35 | 35 | end |
| 36 | 36 | |
| 37 | 37 | it 'finds the correct error for the notice' do |
| 38 | 38 | Err.should_receive(:for).with({ |
| 39 | - :project => @project, | |
| 39 | + :app => @app, | |
| 40 | 40 | :klass => 'HoptoadTestingException', |
| 41 | 41 | :component => 'application', |
| 42 | 42 | :action => 'verify', |
| ... | ... | @@ -87,11 +87,11 @@ describe Notice do |
| 87 | 87 | |
| 88 | 88 | describe "email notifications" do |
| 89 | 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 | 92 | end |
| 93 | 93 | |
| 94 | - App.email_at_notices.each do |threshold| | |
| 94 | + Errbit::Config.email_at_notices.each do |threshold| | |
| 95 | 95 | it "sends an email notification after #{threshold} notice(s)" do |
| 96 | 96 | @error.notices.stub(:count).and_return(threshold) |
| 97 | 97 | Mailer.should_receive(:error_notification). | ... | ... |
spec/models/project_spec.rb
| ... | ... | @@ -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 |