Commit ced5a311fe743b262a8ed936b7cbf52ad8834dba
1 parent
3a3e21a5
Exists in
master
and in
1 other branch
Added ability to tie an app to a GitHub repository. Notices then include links t…
…o the file in the GitHub repo. Conflicts: app/helpers/errs_helper.rb app/models/app.rb app/models/notice.rb app/views/apps/_fields.html.haml app/views/notices/_summary.html.haml spec/models/notice_spec.rb
Showing
8 changed files
with
130 additions
and
4 deletions
Show diff stats
app/helpers/errs_helper.rb
| ... | ... | @@ -7,4 +7,12 @@ module ErrsHelper |
| 7 | 7 | def err_confirm |
| 8 | 8 | Errbit::Config.confirm_resolve_err === false ? nil : 'Seriously?' |
| 9 | 9 | end |
| 10 | + | |
| 11 | + def link_to_github app, notice | |
| 12 | + file_name = notice.top_in_app_backtrace_line['file'].split('/').last | |
| 13 | + file_path = notice.top_in_app_backtrace_line['file'].gsub('[PROJECT_ROOT]', '') | |
| 14 | + line_number = notice.top_in_app_backtrace_line['number'] | |
| 15 | + link_to(file_name, "#{app.github_url_to_file(file_path)}#L#{line_number}", :target => '_blank') | |
| 16 | + end | |
| 17 | + | |
| 10 | 18 | end |
| 11 | 19 | \ No newline at end of file | ... | ... |
app/models/app.rb
| ... | ... | @@ -4,6 +4,7 @@ class App |
| 4 | 4 | |
| 5 | 5 | field :name, :type => String |
| 6 | 6 | field :api_key |
| 7 | + field :github_url | |
| 7 | 8 | field :resolve_errs_on_deploy, :type => Boolean, :default => false |
| 8 | 9 | field :notify_on_errs, :type => Boolean, :default => true |
| 9 | 10 | field :notify_on_deploys, :type => Boolean, :default => true |
| ... | ... | @@ -23,7 +24,8 @@ class App |
| 23 | 24 | references_many :errs, :dependent => :destroy |
| 24 | 25 | |
| 25 | 26 | before_validation :generate_api_key, :on => :create |
| 26 | - | |
| 27 | + before_save :normalize_github_url | |
| 28 | + | |
| 27 | 29 | validates_presence_of :name, :api_key |
| 28 | 30 | validates_uniqueness_of :name, :allow_blank => true |
| 29 | 31 | validates_uniqueness_of :api_key, :allow_blank => true |
| ... | ... | @@ -58,7 +60,15 @@ class App |
| 58 | 60 | !(self[:notify_on_deploys] == false) |
| 59 | 61 | end |
| 60 | 62 | alias :notify_on_deploys? :notify_on_deploys |
| 61 | - | |
| 63 | + | |
| 64 | + def github_url? | |
| 65 | + self.github_url.present? | |
| 66 | + end | |
| 67 | + | |
| 68 | + def github_url_to_file(file) | |
| 69 | + "#{self.github_url}/blob/master#{file}" | |
| 70 | + end | |
| 71 | + | |
| 62 | 72 | protected |
| 63 | 73 | |
| 64 | 74 | def generate_api_key |
| ... | ... | @@ -73,4 +83,12 @@ class App |
| 73 | 83 | end if issue_tracker.errors |
| 74 | 84 | end |
| 75 | 85 | end |
| 86 | + | |
| 87 | + def normalize_github_url | |
| 88 | + return if self.github_url.blank? | |
| 89 | + self.github_url.gsub!(%r{^http://|git@}, 'https://') | |
| 90 | + self.github_url.gsub!(/github\.com:/, 'github.com/') | |
| 91 | + self.github_url.gsub!(/\.git$/, '') | |
| 92 | + end | |
| 93 | + | |
| 76 | 94 | end | ... | ... |
app/models/notice.rb
| ... | ... | @@ -79,7 +79,11 @@ class Notice |
| 79 | 79 | def cache_last_notice_at |
| 80 | 80 | err.update_attributes(:last_notice_at => created_at) |
| 81 | 81 | end |
| 82 | - | |
| 82 | + | |
| 83 | + def top_in_app_backtrace_line | |
| 84 | + @top_in_app_backtrace_line ||= self.backtrace.find {|line| line['file'] =~ %r{^\[PROJECT_ROOT\]/(?!(vendor))} } | |
| 85 | + end | |
| 86 | + | |
| 83 | 87 | protected |
| 84 | 88 | |
| 85 | 89 | def should_notify? | ... | ... |
app/views/apps/_fields.html.haml
| ... | ... | @@ -8,6 +8,10 @@ |
| 8 | 8 | = f.check_box :notify_on_errs |
| 9 | 9 | = f.label :notify_on_errs, 'Notify on errors' |
| 10 | 10 | |
| 11 | +%div | |
| 12 | + = f.label :github_url | |
| 13 | + = f.text_field :github_url | |
| 14 | + | |
| 11 | 15 | %div.checkbox |
| 12 | 16 | = f.check_box :resolve_errs_on_deploy |
| 13 | 17 | = f.label :resolve_errs_on_deploy, 'Resolve errs on deploy' | ... | ... |
app/views/apps/show.html.haml
| ... | ... | @@ -27,6 +27,16 @@ |
| 27 | 27 | %td |
| 28 | 28 | %em Sadly, no one is watching this app |
| 29 | 29 | |
| 30 | +- if @app.github_url? | |
| 31 | + %h3 Repository | |
| 32 | + %table.repository | |
| 33 | + %thead | |
| 34 | + %tr | |
| 35 | + %th GitHub | |
| 36 | + %tbody | |
| 37 | + %tr | |
| 38 | + %td= link_to(@app.github_url, @app.github_url, :target => '_blank') | |
| 39 | + | |
| 30 | 40 | %h3 Latest Deploys |
| 31 | 41 | - if @deploys.any? |
| 32 | 42 | %table.deploys | ... | ... |
app/views/notices/_summary.html.haml
spec/models/app_spec.rb
| ... | ... | @@ -36,6 +36,55 @@ describe App do |
| 36 | 36 | app = Factory(:app) |
| 37 | 37 | app.api_key.should match(/^[a-f0-9]{32}$/) |
| 38 | 38 | end |
| 39 | + | |
| 40 | + it 'is fine with blank github urls' do | |
| 41 | + app = Factory.build(:app, :github_url => "") | |
| 42 | + app.save | |
| 43 | + app.github_url.should == "" | |
| 44 | + end | |
| 45 | + | |
| 46 | + it 'does not touch https github urls' do | |
| 47 | + app = Factory.build(:app, :github_url => "https://github.com/jdpace/errbit") | |
| 48 | + app.save | |
| 49 | + app.github_url.should == "https://github.com/jdpace/errbit" | |
| 50 | + end | |
| 51 | + | |
| 52 | + it 'normalizes http github urls' do | |
| 53 | + app = Factory.build(:app, :github_url => "http://github.com/jdpace/errbit") | |
| 54 | + app.save | |
| 55 | + app.github_url.should == "https://github.com/jdpace/errbit" | |
| 56 | + end | |
| 57 | + | |
| 58 | + it 'normalizes public git repo as a github url' do | |
| 59 | + app = Factory.build(:app, :github_url => "https://github.com/jdpace/errbit.git") | |
| 60 | + app.save | |
| 61 | + app.github_url.should == "https://github.com/jdpace/errbit" | |
| 62 | + end | |
| 63 | + | |
| 64 | + it 'normalizes private git repo as a github url' do | |
| 65 | + app = Factory.build(:app, :github_url => "git@github.com:jdpace/errbit.git") | |
| 66 | + app.save | |
| 67 | + app.github_url.should == "https://github.com/jdpace/errbit" | |
| 68 | + end | |
| 69 | + end | |
| 70 | + | |
| 71 | + context '#github_url_to_file' do | |
| 72 | + it 'resolves to full path to file' do | |
| 73 | + app = Factory(:app, :github_url => "https://github.com/jdpace/errbit") | |
| 74 | + app.github_url_to_file('/path/to/file').should == "https://github.com/jdpace/errbit/blob/master/path/to/file" | |
| 75 | + end | |
| 76 | + end | |
| 77 | + | |
| 78 | + context '#github_url?' do | |
| 79 | + it 'is true when there is a github_url' do | |
| 80 | + app = Factory(:app, :github_url => "https://github.com/jdpace/errbit") | |
| 81 | + app.github_url?.should be_true | |
| 82 | + end | |
| 83 | + | |
| 84 | + it 'is false when no github_url' do | |
| 85 | + app = Factory(:app) | |
| 86 | + app.github_url?.should be_false | |
| 87 | + end | |
| 39 | 88 | end |
| 40 | 89 | |
| 41 | 90 | end | ... | ... |
spec/models/notice_spec.rb
| ... | ... | @@ -21,7 +21,36 @@ describe Notice do |
| 21 | 21 | notice.errors[:notifier].should include("can't be blank") |
| 22 | 22 | end |
| 23 | 23 | end |
| 24 | - | |
| 24 | + | |
| 25 | + context '#top_in_app_backtrace_line' do | |
| 26 | + before do | |
| 27 | + backtrace = [{ | |
| 28 | + 'number' => rand(999), | |
| 29 | + 'file' => '[GEM_ROOT]/gems/actionpack-3.0.4/lib/action_controller/metal/rescue.rb', | |
| 30 | + 'method' => ActiveSupport.methods.shuffle.first | |
| 31 | + }, { | |
| 32 | + 'number' => rand(999), | |
| 33 | + 'file' => '[PROJECT_ROOT]/vendor/plugins/seamless_database_pool/lib/seamless_database_pool/controller_filter.rb', | |
| 34 | + 'method' => ActiveSupport.methods.shuffle.first | |
| 35 | + }, { | |
| 36 | + 'number' => rand(999), | |
| 37 | + 'file' => '[PROJECT_ROOT]/lib/set_headers.rb', | |
| 38 | + 'method' => ActiveSupport.methods.shuffle.first | |
| 39 | + }, { | |
| 40 | + 'number' => rand(999), | |
| 41 | + 'file' => '[PROJECT_ROOT]/lib/detect_api.rb', | |
| 42 | + 'method' => ActiveSupport.methods.shuffle.first | |
| 43 | + }] | |
| 44 | + | |
| 45 | + @notice = Factory(:notice, :backtrace => backtrace) | |
| 46 | + end | |
| 47 | + | |
| 48 | + it 'finds the correct line' do | |
| 49 | + line = @notice.top_in_app_backtrace_line | |
| 50 | + line['file'].should == '[PROJECT_ROOT]/lib/set_headers.rb' | |
| 51 | + end | |
| 52 | + end | |
| 53 | + | |
| 25 | 54 | context '#from_xml' do |
| 26 | 55 | before do |
| 27 | 56 | @xml = Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read | ... | ... |