From f0ad1d4afde18f12c2445afd843c75a44eacc31a Mon Sep 17 00:00:00 2001 From: Ben Abrams Date: Sat, 17 Nov 2018 17:39:51 -0800 Subject: [PATCH] much needed cleanup Breaking Changes: - removed ruby `< 2.3` support as they are EOL - appeased the cops Signed-off-by: Ben Abrams --- .rubocop.yml | 13 ++++++- .travis.yml | 6 ---- CHANGELOG.md | 9 +++++ Rakefile | 6 ++-- bin/check-mysql-disk.rb | 9 ++--- bin/check-mysql-innodb-lock.rb | 1 - bin/check-mysql-msr-replication-status.rb | 20 ++++++----- bin/check-mysql-query-result-count.rb | 5 +-- bin/check-mysql-replication-status.rb | 32 ++++++++++++------ bin/check-mysql-select-count.rb | 3 -- bin/check-mysql-status.rb | 8 ++--- bin/metrics-mysql-graphite.rb | 37 +++++++++++--------- bin/metrics-mysql-processes.rb | 41 +++++++++++++---------- bin/metrics-mysql-query-result-count.rb | 5 +-- bin/metrics-mysql-raw.rb | 25 +++++++------- sensu-plugins-mysql.gemspec | 10 +++--- 16 files changed, 129 insertions(+), 101 deletions(-) mode change 100644 => 100755 bin/check-mysql-select-count.rb diff --git a/.rubocop.yml b/.rubocop.yml index 016c78c..b7e108f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -30,4 +30,15 @@ Style/Documentation: Enabled: false Style/Next: - Enabled: false \ No newline at end of file + Enabled: false + +Style/NumericPredicate: + Enabled: false + +# TODO: when we bump RC this should be: +# Style/TrailingCommaInHashLiteral: +# Enabled: true +# Style/TrailingCommaInArrayLiteral: +# Enabled: true +Style/TrailingCommaInLiteral: + Enabled: false diff --git a/.travis.yml b/.travis.yml index a4a5fc1..f11ba32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,6 @@ cache: install: - bundle install rvm: -- 2.0 -- 2.1 -- 2.2 - 2.3.0 - 2.4.1 notifications: @@ -27,9 +24,6 @@ deploy: on: tags: true all_branches: true - rvm: 2.0 - rvm: 2.1 - rvm: 2.2 rvm: 2.3.0 rvm: 2.4.1 repo: sensu-plugins/sensu-plugins-mysql diff --git a/CHANGELOG.md b/CHANGELOG.md index a970a5e..7162df4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ This CHANGELOG follows the format listed [here](https://github.com/sensu-plugins ## [Unreleased] +### Security +- updated rubocop dependency to `~> 0.51.0` per: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-8418. (@majormoses) + +### Breaking Changes +- removed < ruby 2.3 support as they are EOL (@majormoses) + +### Changed +- appeased the cops (@majormoses) + ## [2.5.1] - 2018-06-21 ### Fixed - check-mysql-alive.rb: allow specifying a value for `-i` (@scones) diff --git a/Rakefile b/Rakefile index da5efb3..4aa305e 100644 --- a/Rakefile +++ b/Rakefile @@ -7,9 +7,9 @@ require 'yard' require 'yard/rake/yardoc_task' YARD::Rake::YardocTask.new do |t| - OTHER_PATHS = %w().freeze + OTHER_PATHS = %w[].freeze t.files = ['lib/**/*.rb', 'bin/**/*.rb', OTHER_PATHS] - t.options = %w(--markup-provider=redcarpet --markup=markdown --main=README.md --files CHANGELOG.md) + t.options = %w[--markup-provider=redcarpet --markup=markdown --main=README.md --files CHANGELOG.md] end RuboCop::RakeTask.new @@ -35,4 +35,4 @@ task :check_binstubs do end end -task default: [:spec, :make_bin_executable, :yard, :rubocop, :check_binstubs] +task default: %i[spec make_bin_executable yard rubocop check_binstubs] diff --git a/bin/check-mysql-disk.rb b/bin/check-mysql-disk.rb index 81c676d..4050e10 100755 --- a/bin/check-mysql-disk.rb +++ b/bin/check-mysql-disk.rb @@ -97,7 +97,7 @@ def run total_size = 0.0 db = Mysql.real_connect(config[:host], db_user, db_pass, nil, config[:port], config[:socket]) - results = db.query <<-EOSQL + results = db.query <<-SQL SELECT table_schema, count(*) TABLES, concat(round(sum(table_rows)/1000000,2),'M') rows, @@ -106,7 +106,7 @@ def run round(sum(data_length+index_length)/(1024*1024*1024),2) total_size, round(sum(index_length)/sum(data_length),2) idxfrac FROM information_schema.TABLES group by table_schema - EOSQL + SQL unless results.nil? results.each_hash do |row| @@ -125,14 +125,11 @@ def run else ok diskstr end - rescue Mysql::Error => e errstr = "Error code: #{e.errno} Error message: #{e.error}" critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate') - - rescue => e + rescue StandardError => e critical e - ensure db.close if db end diff --git a/bin/check-mysql-innodb-lock.rb b/bin/check-mysql-innodb-lock.rb index 0ddd2d5..a96c11c 100755 --- a/bin/check-mysql-innodb-lock.rb +++ b/bin/check-mysql-innodb-lock.rb @@ -140,7 +140,6 @@ def run else critical "Detected Locks #{lock_info}" end - rescue Mysql::Error => e critical "MySQL check failed: #{e.error}" ensure diff --git a/bin/check-mysql-msr-replication-status.rb b/bin/check-mysql-msr-replication-status.rb index 5b07351..f958a4e 100755 --- a/bin/check-mysql-msr-replication-status.rb +++ b/bin/check-mysql-msr-replication-status.rb @@ -74,6 +74,16 @@ class CheckMysqlMSRReplicationStatus < Sensu::Plugin::Check::CLI default: 1800, proc: proc(&:to_i) + def set_status(io_thread_status, sql_thread_status, seconds_behind_master) + if io_thread_status == 'No' || sql_thread_status == 'No' || seconds_behind_master > config[:crit] + 2 + elsif seconds_behind_master > config[:warn] && seconds_behind_master <= config[:crit] + 1 + else + 0 + end + end + def run if config[:ini] ini = IniFile.load(config[:ini]) @@ -106,19 +116,13 @@ def run io_thread_status = row['Slave_IO_Running'] sql_thread_status = row['Slave_SQL_Running'] seconds_behind_master = row['Seconds_Behind_Master'].to_i - status = 0 - if io_thread_status == 'No' || sql_thread_status == 'No' || seconds_behind_master > config[:crit] - status = 2 - end - if seconds_behind_master > config[:warn] && seconds_behind_master <= config[:crit] - status = 1 - end + status = set_status message = "#{channel['channel_name']} STATES:" message += " Slave_IO_Running=#{io_thread_status}" message += ", Slave_SQL_Running=#{sql_thread_status}" message += ", Seconds_Behind_Master=#{seconds_behind_master}" - if status.zero? + if status == 0 ok_statuses << message elsif status == 1 warn_statuses << message diff --git a/bin/check-mysql-query-result-count.rb b/bin/check-mysql-query-result-count.rb index b5fe6d8..fbf8d94 100755 --- a/bin/check-mysql-query-result-count.rb +++ b/bin/check-mysql-query-result-count.rb @@ -99,14 +99,11 @@ def run else ok 'Result count length is below thresholds' end - rescue Mysql::Error => e errstr = "Error code: #{e.errno} Error message: #{e.error}" critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate') - - rescue => e + rescue StandardError => e critical e - ensure db.close if db end diff --git a/bin/check-mysql-replication-status.rb b/bin/check-mysql-replication-status.rb index 6242e3c..6e0a2d6 100755 --- a/bin/check-mysql-replication-status.rb +++ b/bin/check-mysql-replication-status.rb @@ -93,6 +93,24 @@ class CheckMysqlReplicationStatus < Sensu::Plugin::Check::CLI # #YELLOW proc: lambda { |s| s.to_i } # rubocop:disable Lambda + def detect_replication_status?(row) + %w[ + Slave_IO_State + Slave_IO_Running + Slave_SQL_Running + Last_IO_Error + Last_SQL_Error + Seconds_Behind_Master + ].all? { |key| row.key? key } + end + + def slave_running?(row) + %w[ + Slave_IO_Running + Slave_SQL_Running + ].all? { |key| row[key] =~ /Yes/ } + end + def run if config[:ini] ini = IniFile.load(config[:ini]) @@ -121,14 +139,9 @@ def run unless results.nil? results.each_hash do |row| - warn "couldn't detect replication status" unless - %w(Slave_IO_State Slave_IO_Running Slave_SQL_Running Last_IO_Error Last_SQL_Error Seconds_Behind_Master).all? do |key| - row.key? key - end + warn "couldn't detect replication status" unless detect_replication_status?(row) - slave_running = %w(Slave_IO_Running Slave_SQL_Running).all? do |key| - row[key] =~ /Yes/ - end + slave_running = slave_running?(row) output = if db_conn.nil? 'Slave not running!' @@ -160,14 +173,11 @@ def run end ok 'show slave status was nil. This server is not a slave.' end - rescue Mysql::Error => e errstr = "Error code: #{e.errno} Error message: #{e.error}" critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate') - - rescue => e + rescue StandardError => e critical e - ensure db.close if db end diff --git a/bin/check-mysql-select-count.rb b/bin/check-mysql-select-count.rb old mode 100644 new mode 100755 index 18764b9..1b3add3 --- a/bin/check-mysql-select-count.rb +++ b/bin/check-mysql-select-count.rb @@ -101,14 +101,11 @@ def run else ok "Count is below thresholds : #{count} count" end - rescue Mysql::Error => e errstr = "Error code: #{e.errno} Error message: #{e.error}" critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate') - rescue StandardError => e critical "unhandled exception: #{e}" - ensure db.close if db end diff --git a/bin/check-mysql-status.rb b/bin/check-mysql-status.rb index 4569e9f..027dfc9 100755 --- a/bin/check-mysql-status.rb +++ b/bin/check-mysql-status.rb @@ -139,7 +139,7 @@ def status_check(db_user, db_pass, db_socket) else critical "Error message: status: #{status}" end - rescue => e + rescue StandardError => e critical "Error message: status: #{status} | Exception: #{e}" ensure puts '' @@ -162,14 +162,14 @@ def replication_check(db_user, db_pass, db_socket) end dict = [] table.keys.to_a.each do |k| - %w(Slave_IO_State Slave_IO_Running Slave_SQL_Running Last_IO_Error Last_SQL_Error Seconds_Behind_Master).each do |key| + %w[Slave_IO_State Slave_IO_Running Slave_SQL_Running Last_IO_Error Last_SQL_Error Seconds_Behind_Master].each do |key| dict.push(k.strip.to_s) if key.strip == k.strip end end table.each do |attribute, value| puts "#{attribute} : #{value}" if config[:debug] warn "couldn't detect replication status :#{dict.size}" unless dict.size == 6 - slave_running = %w(Slave_IO_Running Slave_SQL_Running).all? do |key| + slave_running = %w[Slave_IO_Running Slave_SQL_Running].all? do |key| table[key].to_s =~ /Yes/ end output = 'Slave not running!' @@ -189,7 +189,7 @@ def replication_check(db_user, db_pass, db_socket) end end ok 'show slave status was nil. This server is not a slave.' - rescue => e + rescue StandardError => e critical "Error message: status: #{status} | Exception: #{e}" end end diff --git a/bin/metrics-mysql-graphite.rb b/bin/metrics-mysql-graphite.rb index 59b7483..6f3cd81 100755 --- a/bin/metrics-mysql-graphite.rb +++ b/bin/metrics-mysql-graphite.rb @@ -90,10 +90,8 @@ class MysqlGraphite < Sensu::Plugin::Metric::CLI::Graphite long: '--verbose', boolean: true - def run - # props to https://github.com/coredump/hoardd/blob/master/scripts-available/mysql.coffee - - metrics = { + def metrics_hash + { 'general' => { 'Bytes_received' => 'rxBytes', 'Bytes_sent' => 'txBytes', @@ -117,14 +115,14 @@ def run 'Select_range' => 'selectRange', 'Select_range_check' => 'selectRange_check', 'Select_scan' => 'selectScan', - 'Slow_queries' => 'slowQueries' + 'Slow_queries' => 'slowQueries', }, 'querycache' => { 'Qcache_queries_in_cache' => 'queriesInCache', 'Qcache_hits' => 'cacheHits', 'Qcache_inserts' => 'inserts', 'Qcache_not_cached' => 'notCached', - 'Qcache_lowmem_prunes' => 'lowMemPrunes' + 'Qcache_lowmem_prunes' => 'lowMemPrunes', }, 'commands' => { 'Com_admin_commands' => 'admin_commands', @@ -159,7 +157,7 @@ def run 'Com_lock_tables' => 'lock_tables', 'Com_show_create_table' => 'show_create_table', 'Com_unlock_tables' => 'unlock_tables', - 'Com_alter_table' => 'alter_table' + 'Com_alter_table' => 'alter_table', }, 'counters' => { 'Handler_write' => 'handlerWrite', @@ -174,7 +172,7 @@ def run 'Handler_commit' => 'handlerCommit', 'Handler_rollback' => 'handlerRollback', 'Handler_savepoint' => 'handlerSavepoint', - 'Handler_savepoint_rollback' => 'handlerSavepointRollback' + 'Handler_savepoint_rollback' => 'handlerSavepointRollback', }, 'innodb' => { 'Innodb_buffer_pool_pages_total' => 'bufferTotal_pages', @@ -195,15 +193,22 @@ def run 'Innodb_rows_updated' => 'rowsUpdated', 'Innodb_rows_read' => 'rowsRead', 'Innodb_rows_deleted' => 'rowsDeleted', - 'Innodb_rows_inserted' => 'rowsInserted' + 'Innodb_rows_inserted' => 'rowsInserted', }, 'configuration' => { 'max_connections' => 'MaxConnections', - 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount' - } + 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount', + }, } + end + + def run + # props to https://github.com/coredump/hoardd/blob/master/scripts-available/mysql.coffee + + metrics = metrics_hash - config[:host].split(' ').each do |mysql_host| + # FIXME: break this up + config[:host].split(' ').each do |mysql_host| # rubocop:disable Metrics/BlockLength mysql_shorthostname = mysql_host.split('.')[0] if config[:ini] ini = IniFile.load(config[:ini]) @@ -218,7 +223,7 @@ def run mysql = Mysql.new(mysql_host, db_user, db_pass, nil, config[:port], config[:socket]) results = mysql.query('SHOW GLOBAL STATUS') - rescue => e + rescue StandardError => e puts e.message end @@ -241,7 +246,7 @@ def run output "#{config[:scheme]}.#{mysql_shorthostname}.general.#{metrics['general'][key]}", value end end - rescue => e + rescue StandardError => e puts "Error querying slave status: #{e}" if config[:verbose] end @@ -251,12 +256,12 @@ def run category = 'configuration' variables_results.each_hash do |row| metrics[category].each do |metric, desc| - if metric.casecmp(row['Variable_name']) == 0 + if metric.casecmp(row['Variable_name']).zero? output "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{desc}", row['Value'] end end end - rescue => e + rescue StandardError => e puts e.message end diff --git a/bin/metrics-mysql-processes.rb b/bin/metrics-mysql-processes.rb index 071da3c..12ff7d1 100755 --- a/bin/metrics-mysql-processes.rb +++ b/bin/metrics-mysql-processes.rb @@ -94,33 +94,40 @@ class MetricsMySQLProcesses < Sensu::Plugin::Metric::CLI::Graphite long: '--socket SOCKET', description: 'MySQL Unix socket to connect to' + def set_default_metrics + { + 'user' => {}, + 'database' => {}, + 'command' => {}, + }.each_value { |value| value.default = 0 } + end + + def db_connection_creds + if config[:ini] + ini = IniFile.load(config[:ini]) + section = ini[config[:ini_section]] + db_user = section['user'] + db_pass = section['password'] + else + db_user = config[:username] + db_pass = config[:password] + end + [db_user, db_pass] + end + def run config[:host].split(' ').each do |mysql_host| mysql_shorthostname = mysql_host.split('.')[0] - if config[:ini] - ini = IniFile.load(config[:ini]) - section = ini[config[:ini_section]] - db_user = section['user'] - db_pass = section['password'] - else - db_user = config[:username] - db_pass = config[:password] - end + db_user, db_pass = db_connection_creds begin mysql = Mysql.new(mysql_host, db_user, db_pass, nil, config[:port], config[:socket]) results = mysql.query('SHOW PROCESSLIST') - rescue => e + rescue StandardError => e unknown "Unable to query MySQL: #{e.message}" end - metrics = { - 'user' => {}, - 'database' => {}, - 'command' => {} - } - - metrics.each_value { |value| value.default = 0 } + metrics = set_default_metrics results.each_hash do |row| metrics['user'][row['User']] += 1 diff --git a/bin/metrics-mysql-query-result-count.rb b/bin/metrics-mysql-query-result-count.rb index d09af99..0cfc489 100755 --- a/bin/metrics-mysql-query-result-count.rb +++ b/bin/metrics-mysql-query-result-count.rb @@ -86,14 +86,11 @@ def run output config[:name], length ok - rescue Mysql::Error => e errstr = "Error code: #{e.errno} Error message: #{e.error}" critical "#{errstr} SQLSTATE: #{e.sqlstate}" if e.respond_to?('sqlstate') - - rescue => e + rescue StandardError => e critical e - ensure db.close if db end diff --git a/bin/metrics-mysql-raw.rb b/bin/metrics-mysql-raw.rb index 120112a..b4daa37 100755 --- a/bin/metrics-mysql-raw.rb +++ b/bin/metrics-mysql-raw.rb @@ -182,7 +182,7 @@ def metrics_hash 'Select_range' => 'selectRange', 'Select_range_check' => 'selectRange_check', 'Select_scan' => 'selectScan', - 'Slow_queries' => 'slowQueries' + 'Slow_queries' => 'slowQueries', }, 'querycache' => { 'Qcache_queries_in_cache' => 'queriesInCache', @@ -190,7 +190,7 @@ def metrics_hash 'Qcache_inserts' => 'inserts', 'Qcache_not_cached' => 'notCached', 'Qcache_lowmem_prunes' => 'lowMemPrunes', - 'Qcache_free_memory' => 'freeMemory' + 'Qcache_free_memory' => 'freeMemory', }, 'commands' => { 'Com_admin_commands' => 'admin_commands', @@ -225,7 +225,7 @@ def metrics_hash 'Com_lock_tables' => 'lock_tables', 'Com_show_create_table' => 'show_create_table', 'Com_unlock_tables' => 'unlock_tables', - 'Com_alter_table' => 'alter_table' + 'Com_alter_table' => 'alter_table', }, 'counters' => { 'Handler_write' => 'handlerWrite', @@ -240,7 +240,7 @@ def metrics_hash 'Handler_commit' => 'handlerCommit', 'Handler_rollback' => 'handlerRollback', 'Handler_savepoint' => 'handlerSavepoint', - 'Handler_savepoint_rollback' => 'handlerSavepointRollback' + 'Handler_savepoint_rollback' => 'handlerSavepointRollback', }, 'innodb' => { 'Innodb_buffer_pool_pages_total' => 'bufferTotal_pages', @@ -261,11 +261,11 @@ def metrics_hash 'Innodb_rows_updated' => 'rowsUpdated', 'Innodb_rows_read' => 'rowsRead', 'Innodb_rows_deleted' => 'rowsDeleted', - 'Innodb_rows_inserted' => 'rowsInserted' + 'Innodb_rows_inserted' => 'rowsInserted', }, 'configuration' => { - 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount' - } + 'Max_prepared_stmt_count' => 'MaxPreparedStmtCount', + }, } metrics end @@ -299,7 +299,7 @@ def slave_metrics(metrics) output "#{config[:scheme]}.#{mysql_shorthostname}.general.#{metrics['general'][key]}", value end end - rescue => e + rescue StandardError => e puts "Error querying slave status: #{e}" if config[:verbose] end @@ -332,14 +332,15 @@ def configuration_metrics(metrics, db_user, db_pass, db_socket) end end end - rescue => e + rescue StandardError => e puts e.message end # Fetch MySQL metrics def fetcher(db_user, db_pass, db_socket) metrics = metrics_hash - if config[:check] == 'metric' + # FIXME: this needs refactoring + if config[:check] == 'metric' # rubocop:disable Style/GuardClause mysql_shorthostname = config[:hostname].tr('.', '_') begin table = [] @@ -362,7 +363,7 @@ def fetcher(db_user, db_pass, db_socket) table.each do |row| metrics.each do |category, var_mapping| row_var_name = row['Variable_name'].to_s - var_mapping.keys.each do |vmkey| + var_mapping.each_key do |vmkey| if row_var_name.to_s == vmkey.to_s prefix = "#{config[:scheme]}.#{mysql_shorthostname}.#{category}.#{vmkey[row_var_name]}" output prefix, row['Value'] unless mysql_shorthostname.to_s.chomp.empty? @@ -373,7 +374,7 @@ def fetcher(db_user, db_pass, db_socket) # Slave and configuration metrics here slave_metrics(metrics) configuration_metrics(metrics, db_user, db_pass, db_socket) - rescue => e + rescue StandardError => e critical "Error message: status: #{status} | Exception: #{e.backtrace}" ensure ok '' diff --git a/sensu-plugins-mysql.gemspec b/sensu-plugins-mysql.gemspec index 7b1b5a1..d6d8eab 100644 --- a/sensu-plugins-mysql.gemspec +++ b/sensu-plugins-mysql.gemspec @@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'date' require_relative 'lib/sensu-plugins-mysql' -Gem::Specification.new do |s| +Gem::Specification.new do |s| # rubocop:disable Metrics/BlockLength s.authors = ['Sensu-Plugins and contributors'] # s.cert_chain = ['certs/sensu-plugins.pem'] s.date = Date.today.to_s @@ -15,7 +15,7 @@ Gem::Specification.new do |s| sending metrics to a MySQL database.' s.email = '' s.executables = Dir.glob('bin/**/*.rb').map { |file| File.basename(file) } - s.files = Dir.glob('{bin,lib}/**/*') + %w(LICENSE README.md CHANGELOG.md) + s.files = Dir.glob('{bin,lib}/**/*') + %w[LICENSE README.md CHANGELOG.md] s.homepage = 'https://github.com/sensu-plugins/sensu-plugins-mysql' s.license = 'MIT' s.metadata = { 'maintainer' => 'sensu-plugin', @@ -27,7 +27,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.post_install_message = 'You can use the embedded Ruby by setting EMBEDDED_RUBY=true in /etc/default/sensu' s.require_paths = ['lib'] - s.required_ruby_version = '>= 2.0.0' + s.required_ruby_version = '>= 2.3.0' # s.signing_key = File.expand_path(pvt_key) if $PROGRAM_NAME =~ /gem\z/ s.summary = 'Sensu plugins for MySql' s.test_files = s.files.grep(%r{^(test|spec|features)/}) @@ -37,13 +37,13 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'ruby-mysql', '~> 2.9' s.add_runtime_dependency 'sensu-plugin', '~> 1.2' - s.add_development_dependency 'codeclimate-test-reporter', '~> 0.4' s.add_development_dependency 'bundler', '~> 1.7' + s.add_development_dependency 'codeclimate-test-reporter', '~> 0.4' s.add_development_dependency 'github-markup', '~> 1.3' s.add_development_dependency 'pry', '~> 0.10' s.add_development_dependency 'rake', '~> 10.0' s.add_development_dependency 'redcarpet', '~> 3.2' s.add_development_dependency 'rspec', '~> 3.1' - s.add_development_dependency 'rubocop', '~> 0.50.0' + s.add_development_dependency 'rubocop', '~> 0.51.0' s.add_development_dependency 'yard', '~> 0.8' end