diff options
author | Douwe Maan <douwe@selenight.nl> | 2016-01-20 22:04:15 +0300 |
---|---|---|
committer | Douwe Maan <douwe@selenight.nl> | 2016-01-20 22:04:15 +0300 |
commit | 7d347ae564c137bd8b133dd4d589b089bde931a5 (patch) | |
tree | 2004517d9c80fbd95359d2bd53842fa031415a72 | |
parent | 6000f8545f43b449035cb50382901ce40fb807b0 (diff) | |
parent | a8a65afe1e953ce3a9fc151f9e033b99fc568fad (diff) |
Merge branch 'master' into issue_3945
31 files changed, 159 insertions, 32 deletions
diff --git a/CHANGELOG b/CHANGELOG index 2e0eee52a59..cd147dc7662 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,7 @@ Please view this file on the master branch, on stable branches it's out of date. v 8.5.0 (unreleased) - Add "visibility" flag to GET /projects api endpoint + - Upgrade gitlab_git to 7.2.23 to fix commit message mentions in first branch push v 8.4.0 (unreleased) - Allow LDAP users to change their email if it was not set by the LDAP server @@ -13,6 +14,7 @@ v 8.4.0 (unreleased) - Autocomplete data is now always loaded, instead of when focusing a comment text area - Improved performance of finding issues for an entire group - Added custom application performance measuring system powered by InfluxDB + - Gracefully handle invalid UTF-8 sequences in Markdown links (Stan Hu) - Bump fog to 1.36.0 (Stan Hu) - Add user's last used IP addresses to admin page (Stan Hu) - Add housekeeping function to project settings page @@ -49,7 +49,7 @@ gem "browser", '~> 1.0.0' # Extracting information from a git repository # Provide access to Gitlab::Git library -gem "gitlab_git", '~> 7.2.22' +gem "gitlab_git", '~> 7.2.23' # LDAP Auth # GitLab fork with several improvements to original library. For full list of changes @@ -293,6 +293,9 @@ end group :production do gem "gitlab_meta", '7.0' + + # Sentry integration + gem 'sentry-raven' end gem "newrelic_rpm", '~> 3.9.4.245' diff --git a/Gemfile.lock b/Gemfile.lock index a14fdbeed23..5e0718af70f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -356,7 +356,7 @@ GEM posix-spawn (~> 0.3) gitlab_emoji (0.2.0) gemojione (~> 2.1) - gitlab_git (7.2.22) + gitlab_git (7.2.23) activesupport (~> 4.0) charlock_holmes (~> 0.7.3) github-linguist (~> 4.7.0) @@ -725,6 +725,8 @@ GEM activesupport (>= 3.1, < 4.3) select2-rails (3.5.9.3) thor (~> 0.14) + sentry-raven (0.15.3) + faraday (>= 0.7.6) settingslogic (2.0.9) sexp_processor (4.6.0) sham_rack (1.3.6) @@ -932,7 +934,7 @@ DEPENDENCIES github-markup (~> 1.3.1) gitlab-flowdock-git-hook (~> 1.0.1) gitlab_emoji (~> 0.2.0) - gitlab_git (~> 7.2.22) + gitlab_git (~> 7.2.23) gitlab_meta (= 7.0) gitlab_omniauth-ldap (~> 1.2.1) gollum-lib (~> 4.1.0) @@ -1008,6 +1010,7 @@ DEPENDENCIES sdoc (~> 0.3.20) seed-fu (~> 2.3.5) select2-rails (~> 3.5.9) + sentry-raven settingslogic (~> 2.0.9) sham_rack shoulda-matchers (~> 2.8.0) diff --git a/app/assets/javascripts/awards_handler.coffee b/app/assets/javascripts/awards_handler.coffee index 9d5ae6c04e9..1ef31c7700e 100644 --- a/app/assets/javascripts/awards_handler.coffee +++ b/app/assets/javascripts/awards_handler.coffee @@ -44,7 +44,6 @@ class @AwardsHandler decrementCounter: (emoji) -> counter = @findEmojiIcon(emoji).siblings(".counter") emojiIcon = counter.parent() - if parseInt(counter.text()) > 1 counter.text(parseInt(counter.text()) - 1) emojiIcon.removeClass("active") @@ -60,20 +59,18 @@ class @AwardsHandler removeMeFromAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() authors = award_block.attr("data-original-title").split(", ") - authors = _.without(authors, "me").join(", ") - award_block.attr("title", authors) + authors.splice(authors.indexOf("me"),1) + award_block.closest(".award").attr("data-original-title", authors.join(", ")) @resetTooltip(award_block) addMeToAuthorList: (emoji) -> award_block = @findEmojiIcon(emoji).parent() - authors = _.compact(award_block.attr("data-original-title").split(", ")) + origTitle = award_block.attr("data-original-title").trim() + authors = [] + if origTitle + authors = origTitle.split(', ') authors.push("me") - - if authors.length == 1 - award_block.attr("title", "me") - else - award_block.attr("title", authors.join(", ")) - + award_block.attr("title", authors.join(", ")) @resetTooltip(award_block) resetTooltip: (award) -> diff --git a/app/assets/javascripts/dispatcher.js.coffee b/app/assets/javascripts/dispatcher.js.coffee index 58d6b9d4060..0d88e8d254a 100644 --- a/app/assets/javascripts/dispatcher.js.coffee +++ b/app/assets/javascripts/dispatcher.js.coffee @@ -87,7 +87,6 @@ class Dispatcher new GroupAvatar() when 'projects:tree:show' new TreeView() - shortcut_handler = new ShortcutsTree() when 'projects:find_file:show' shortcut_handler = true when 'projects:blob:show' diff --git a/app/assets/javascripts/shortcuts.js.coffee b/app/assets/javascripts/shortcuts.js.coffee index 4d915bfc8c5..f141fb69c3e 100644 --- a/app/assets/javascripts/shortcuts.js.coffee +++ b/app/assets/javascripts/shortcuts.js.coffee @@ -4,6 +4,7 @@ class @Shortcuts Mousetrap.reset() Mousetrap.bind('?', @selectiveHelp) Mousetrap.bind('s', Shortcuts.focusSearch) + Mousetrap.bind('t', -> Turbolinks.visit(findFileURL)) if findFileURL? selectiveHelp: (e) => Shortcuts.showHelp(e, @enabledHelp) diff --git a/app/assets/javascripts/shortcuts_tree.coffee b/app/assets/javascripts/shortcuts_tree.coffee deleted file mode 100644 index ba0839c9fc0..00000000000 --- a/app/assets/javascripts/shortcuts_tree.coffee +++ /dev/null @@ -1,4 +0,0 @@ -class @ShortcutsTree extends ShortcutsNavigation - constructor: -> - super() - Mousetrap.bind('t', -> ShortcutsTree.findAndFollowLink('.shortcuts-find-file')) diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 91f7d78bd73..9943745208e 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -77,6 +77,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :recaptcha_enabled, :recaptcha_site_key, :recaptcha_private_key, + :sentry_enabled, + :sentry_dsn, restricted_visibility_levels: [], import_sources: [] ) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 8b62c11f7cc..2d735b90597 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base before_action :check_password_expiration before_action :check_2fa_requirement before_action :ldap_security_check + before_action :sentry_user_context before_action :default_headers before_action :add_gon_variables before_action :configure_permitted_parameters, if: :devise_controller? @@ -42,6 +43,16 @@ class ApplicationController < ActionController::Base protected + def sentry_user_context + if Rails.env.production? && current_application_settings.sentry_enabled && current_user + Raven.user_context( + id: current_user.id, + email: current_user.email, + username: current_user.username, + ) + end + end + # From https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example # https://gist.github.com/josevalim/fb706b1e933ef01e4fb6 def authenticate_user_from_token! diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 6c6c2468374..59563b8823c 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -41,6 +41,8 @@ # recaptcha_site_key :string # recaptcha_private_key :string # metrics_port :integer default(8089) +# sentry_enabled :boolean default(FALSE) +# sentry_dsn :string # class ApplicationSetting < ActiveRecord::Base @@ -82,6 +84,10 @@ class ApplicationSetting < ActiveRecord::Base presence: true, if: :recaptcha_enabled + validates :sentry_dsn, + presence: true, + if: :sentry_enabled + validates_each :restricted_visibility_levels do |record, attr, value| unless value.nil? value.each do |level| diff --git a/app/models/note.rb b/app/models/note.rb index 3e1375e5ad6..15f48110ad2 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -33,7 +33,7 @@ class Note < ActiveRecord::Base participant :author belongs_to :project - belongs_to :noteable, polymorphic: true + belongs_to :noteable, polymorphic: true, touch: true belongs_to :author, class_name: "User" belongs_to :updated_by, class_name: "User" diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml index 83f6814d822..35e4dd761ab 100644 --- a/app/views/admin/application_settings/_form.html.haml +++ b/app/views/admin/application_settings/_form.html.haml @@ -226,11 +226,30 @@ = f.text_field :recaptcha_site_key, class: 'form-control' .help-block Generate site and private keys here: - %a{ href: 'http://www.google.com/recaptcha', target: 'blank'} http://www.google.com/recaptcha + %a{ href: 'http://www.google.com/recaptcha', target: '_blank'} http://www.google.com/recaptcha .form-group = f.label :recaptcha_private_key, 'reCAPTCHA Private Key', class: 'control-label col-sm-2' .col-sm-10 = f.text_field :recaptcha_private_key, class: 'form-control' + %fieldset + %legend Error Reporting and Logging + %p + These settings require a restart to take effect. + .form-group + .col-sm-offset-2.col-sm-10 + .checkbox + = f.label :sentry_enabled do + = f.check_box :sentry_enabled + Enable Sentry + .help-block + Sentry is an error reporting and logging tool which is currently not shipped with GitLab, get it here: + %a{ href: 'https://getsentry.com', target: '_blank' } https://getsentry.com + + .form-group + = f.label :sentry_dsn, 'Sentry DSN', class: 'control-label col-sm-2' + .col-sm-10 + = f.text_field :sentry_dsn, class: 'form-control' + .form-actions = f.submit 'Save', class: 'btn btn-primary' diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml index 3892ef8eefa..fcb6b835a7e 100644 --- a/app/views/layouts/header/_default.html.haml +++ b/app/views/layouts/header/_default.html.haml @@ -37,3 +37,6 @@ %h1.title= title = render 'shared/outdated_browser' +- if @project && !@project.empty_repo? + :javascript + var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}";
\ No newline at end of file diff --git a/app/views/projects/artifacts/_tree_directory.html.haml b/app/views/projects/artifacts/_tree_directory.html.haml index e4b7979949c..def493c56f5 100644 --- a/app/views/projects/artifacts/_tree_directory.html.haml +++ b/app/views/projects/artifacts/_tree_directory.html.haml @@ -6,4 +6,3 @@ %span.str-truncated = link_to directory.name, path_to_directory %td - %td diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml index 3dfc09cc495..36fb4c998c9 100644 --- a/app/views/projects/artifacts/_tree_file.html.haml +++ b/app/views/projects/artifacts/_tree_file.html.haml @@ -7,5 +7,3 @@ = link_to file.name, path_to_file %td = number_to_human_size(file.metadata[:size], precision: 2) - %td - = number_to_human_size(file.metadata[:zipped], precision: 2) diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index b70c776a2b2..d3c969cc035 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -15,7 +15,6 @@ %tr %th Name %th Size - %th Compressed to = render partial: 'tree_directory', collection: @entry.directories(parent: true), as: :directory = render partial: 'tree_file', collection: @entry.files, as: :file diff --git a/app/views/projects/find_file/show.html.haml b/app/views/projects/find_file/show.html.haml index 40a2a61d8a1..905f6bbbd48 100644 --- a/app/views/projects/find_file/show.html.haml +++ b/app/views/projects/find_file/show.html.haml @@ -10,7 +10,7 @@ = link_to namespace_project_tree_path(@project.namespace, @project, @ref) do = @project.path %li.file-finder - %input#file_find.form-control.file-finder-input{type: "text", placeholder: 'Find by path'} + %input#file_find.form-control.file-finder-input{type: "text", placeholder: 'Find by path', autocomplete: 'off'} %div.tree-content-holder .table-holder diff --git a/config.ru b/config.ru index a2525c81361..065ce59932f 100644 --- a/config.ru +++ b/config.ru @@ -7,8 +7,11 @@ if defined?(Unicorn) # Unicorn self-process killer require 'unicorn/worker_killer' + min = (ENV['GITLAB_UNICORN_MEMORY_MIN'] || 300 * 1 << 20).to_i + max = (ENV['GITLAB_UNICORN_MEMORY_MAX'] || 350 * 1 << 20).to_i + # Max memory size (RSS) per worker - use Unicorn::WorkerKiller::Oom, (200 * (1 << 20)), (250 * (1 << 20)) + use Unicorn::WorkerKiller::Oom, min, max end end diff --git a/config/initializers/sentry.rb b/config/initializers/sentry.rb new file mode 100644 index 00000000000..d0630b9fa07 --- /dev/null +++ b/config/initializers/sentry.rb @@ -0,0 +1,19 @@ +# Be sure to restart your server when you modify this file. + +require 'gitlab/current_settings' +include Gitlab::CurrentSettings + +if Rails.env.production? + # allow it to fail: it may do so when create_from_defaults is executed before migrations are actually done + begin + sentry_enabled = current_application_settings.sentry_enabled + rescue + sentry_enabled = false + end + + if sentry_enabled + Raven.configure do |config| + config.dsn = current_application_settings.sentry_dsn + end + end +end diff --git a/db/migrate/20160118155830_add_sentry_to_application_settings.rb b/db/migrate/20160118155830_add_sentry_to_application_settings.rb new file mode 100644 index 00000000000..fa7ff9d9228 --- /dev/null +++ b/db/migrate/20160118155830_add_sentry_to_application_settings.rb @@ -0,0 +1,8 @@ +class AddSentryToApplicationSettings < ActiveRecord::Migration + def change + change_table :application_settings do |t| + t.boolean :sentry_enabled, default: false + t.string :sentry_dsn + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 7eb99a47c71..a7cadacc0ce 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -62,6 +62,8 @@ ActiveRecord::Schema.define(version: 20160120172143) do t.string "recaptcha_private_key" t.integer "metrics_port", default: 8089 t.integer "metrics_sample_interval", default: 15 + t.boolean "sentry_enabled", default: false + t.string "sentry_dsn" end create_table "audit_events", force: :cascade do |t| diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md index 1eb3a74d304..42a27dcf6d6 100644 --- a/doc/administration/environment_variables.md +++ b/doc/administration/environment_variables.md @@ -17,6 +17,8 @@ DATABASE_URL | url | For example: postgresql://localhost/blog_development?pool=5 GITLAB_EMAIL_FROM | email | Email address used in the "From" field in mails sent by GitLab GITLAB_EMAIL_DISPLAY_NAME | string | Name used in the "From" field in mails sent by GitLab GITLAB_EMAIL_REPLY_TO | email | Email address used in the "Reply-To" field in mails sent by GitLab +GITLAB_UNICORN_MEMORY_MIN | integer | The minimum memory threshold (in bytes) for the Unicorn worker killer +GITLAB_UNICORN_MEMORY_MAX | integer | The maximum memory threshold (in bytes) for the Unicorn worker killer ## Complete database variables diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md index 6420d65cf1b..c29037e89c2 100644 --- a/doc/web_hooks/web_hooks.md +++ b/doc/web_hooks/web_hooks.md @@ -56,7 +56,7 @@ X-Gitlab-Event: Push Hook "author": { "name": "Jordi Mallach", "email": "jordi@softcatala.org" - } + }, "added": ["CHANGELOG"], "modified": ["app/controller/application.rb"], "removed": [] diff --git a/features/project/issues/issues.feature b/features/project/issues/issues.feature index ab234bc7507..1502b0952cd 100644 --- a/features/project/issues/issues.feature +++ b/features/project/issues/issues.feature @@ -52,6 +52,14 @@ Feature: Project Issues And I should see an error alert section within the comment form @javascript + Scenario: Visiting Issues after leaving a comment + Given I visit issue page "Release 0.4" + And I leave a comment like "XML attached" + And I visit project "Shop" issues page + And I sort the list by "Last updated" + Then I should see "Release 0.4" at the top + + @javascript Scenario: I search issue Given I fill in issue search with "Re" Then I should see "Release 0.4" in issues diff --git a/features/project/merge_requests.feature b/features/project/merge_requests.feature index aa9078b878f..f1629a26f10 100644 --- a/features/project/merge_requests.feature +++ b/features/project/merge_requests.feature @@ -76,6 +76,25 @@ Feature: Project Merge Requests Then I should see comment "XML attached" @javascript + Scenario: Visiting Merge Requests after leaving a comment + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-04" + And I leave a comment like "XML attached" + And I visit project "Shop" merge requests page + And I sort the list by "Last updated" + Then I should see "Bug NS-04" at the top + + @javascript + Scenario: Visiting Merge Requests after commenting on diffs + Given project "Shop" have "Bug NS-05" open merge request with diffs inside + And I visit merge request page "Bug NS-05" + And I click on the Changes tab + And I leave a comment like "Line is wrong" on diff + And I visit project "Shop" merge requests page + And I sort the list by "Last updated" + Then I should see "Bug NS-05" at the top + + @javascript Scenario: I comment on a merge request diff Given project "Shop" have "Bug NS-05" open merge request with diffs inside And I visit merge request page "Bug NS-05" diff --git a/features/steps/project/issues/issues.rb b/features/steps/project/issues/issues.rb index 8e8c9c57452..d556b73f9fd 100644 --- a/features/steps/project/issues/issues.rb +++ b/features/steps/project/issues/issues.rb @@ -293,6 +293,11 @@ class Spinach::Features::ProjectIssues < Spinach::FeatureSteps expect(page).to have_content('Yay!') end end + + step 'I should see "Release 0.4" at the top' do + expect(page.find('ul.content-list.issues-list li.issue:first-child')).to have_content("Release 0.4") + end + def filter_issue(text) fill_in 'issue_search', with: text end diff --git a/features/steps/project/merge_requests.rb b/features/steps/project/merge_requests.rb index be993d11093..8af635689e0 100644 --- a/features/steps/project/merge_requests.rb +++ b/features/steps/project/merge_requests.rb @@ -41,7 +41,7 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end step 'I should not see "master" branch' do - expect(page).not_to have_content "master" + expect(find('.merge-request-info')).not_to have_content "master" end step 'I should see "other_branch" branch' do @@ -415,6 +415,14 @@ class Spinach::Features::ProjectMergeRequests < Spinach::FeatureSteps end end + step 'I should see "Bug NS-05" at the top' do + expect(page.find('ul.content-list.mr-list li.merge-request:first-child')).to have_content("Bug NS-05") + end + + step 'I should see "Bug NS-04" at the top' do + expect(page.find('ul.content-list.mr-list li.merge-request:first-child')).to have_content("Bug NS-04") + end + def merge_request @merge_request ||= MergeRequest.find_by!(title: "Bug NS-05") end diff --git a/features/steps/shared/note.rb b/features/steps/shared/note.rb index 444d6726f99..eb6df61b8e6 100644 --- a/features/steps/shared/note.rb +++ b/features/steps/shared/note.rb @@ -144,4 +144,11 @@ module SharedNote expect(page).to have_content("+1 Awesome!") end end + + step 'I sort the list by "Last updated"' do + find('button.dropdown-toggle.btn').click + page.within('ul.dropdown-menu.dropdown-menu-align-right li') do + click_link "Last updated" + end + end end diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index 20bd4f7ee6e..3637b1bac94 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -133,6 +133,7 @@ module Banzai next unless link && text link = CGI.unescape(link) + next unless link.force_encoding('UTF-8').valid_encoding? # Ignore ending punctionation like periods or commas next unless link == text && text =~ /\A#{pattern}/ @@ -170,6 +171,7 @@ module Banzai next unless link && text link = CGI.unescape(link) + next unless link.force_encoding('UTF-8').valid_encoding? next unless link && link =~ /\A#{pattern}\z/ html = yield link, text diff --git a/spec/lib/gitlab/note_data_builder_spec.rb b/spec/lib/gitlab/note_data_builder_spec.rb index 6cbdae737f4..691f36e6cb7 100644 --- a/spec/lib/gitlab/note_data_builder_spec.rb +++ b/spec/lib/gitlab/note_data_builder_spec.rb @@ -37,7 +37,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and issue-specific data' do expect(data).to have_key(:issue) - expect(data[:issue]).to eq(issue.hook_attrs) + expect(data[:issue].except('updated_at')).to eq(issue.hook_attrs.except('updated_at')) + expect(data[:issue]['updated_at']).to be > issue.hook_attrs['updated_at'] end end @@ -47,7 +48,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and merge request data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request]).to eq(merge_request.hook_attrs) + expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] end end @@ -57,7 +59,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and merge request diff data' do expect(data).to have_key(:merge_request) - expect(data[:merge_request]).to eq(merge_request.hook_attrs) + expect(data[:merge_request].except('updated_at')).to eq(merge_request.hook_attrs.except('updated_at')) + expect(data[:merge_request]['updated_at']).to be > merge_request.hook_attrs['updated_at'] end end @@ -67,7 +70,8 @@ describe 'Gitlab::NoteDataBuilder', lib: true do it 'returns the note and project snippet data' do expect(data).to have_key(:snippet) - expect(data[:snippet]).to eq(snippet.hook_attrs) + expect(data[:snippet].except('updated_at')).to eq(snippet.hook_attrs.except('updated_at')) + expect(data[:snippet]['updated_at']).to be > snippet.hook_attrs['updated_at'] end end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 91b250265e6..f4c58882757 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -41,6 +41,8 @@ # recaptcha_site_key :string # recaptcha_private_key :string # metrics_port :integer default(8089) +# sentry_enabled :boolean default(FALSE) +# sentry_dsn :string # require 'spec_helper' |