roo_on_rails 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,205 @@
1
+ PATH
2
+ remote: ../
3
+ specs:
4
+ roo_on_rails (1.1.0)
5
+ dotenv-rails (~> 2.1)
6
+ hashie (~> 3.4)
7
+ newrelic_rpm (~> 3.17)
8
+ platform-api (~> 0.8)
9
+ rack-ssl-enforcer
10
+ rack-timeout
11
+ rails (>= 3.2.22, < 5.1)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ actioncable (5.0.1)
17
+ actionpack (= 5.0.1)
18
+ nio4r (~> 1.2)
19
+ websocket-driver (~> 0.6.1)
20
+ actionmailer (5.0.1)
21
+ actionpack (= 5.0.1)
22
+ actionview (= 5.0.1)
23
+ activejob (= 5.0.1)
24
+ mail (~> 2.5, >= 2.5.4)
25
+ rails-dom-testing (~> 2.0)
26
+ actionpack (5.0.1)
27
+ actionview (= 5.0.1)
28
+ activesupport (= 5.0.1)
29
+ rack (~> 2.0)
30
+ rack-test (~> 0.6.3)
31
+ rails-dom-testing (~> 2.0)
32
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
33
+ actionview (5.0.1)
34
+ activesupport (= 5.0.1)
35
+ builder (~> 3.1)
36
+ erubis (~> 2.7.0)
37
+ rails-dom-testing (~> 2.0)
38
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
39
+ activejob (5.0.1)
40
+ activesupport (= 5.0.1)
41
+ globalid (>= 0.3.6)
42
+ activemodel (5.0.1)
43
+ activesupport (= 5.0.1)
44
+ activerecord (5.0.1)
45
+ activemodel (= 5.0.1)
46
+ activesupport (= 5.0.1)
47
+ arel (~> 7.0)
48
+ activesupport (5.0.1)
49
+ concurrent-ruby (~> 1.0, >= 1.0.2)
50
+ i18n (~> 0.7)
51
+ minitest (~> 5.1)
52
+ tzinfo (~> 1.1)
53
+ appraisal (2.1.0)
54
+ bundler
55
+ rake
56
+ thor (>= 0.14.0)
57
+ arel (7.1.4)
58
+ builder (3.2.3)
59
+ byebug (9.0.6)
60
+ coderay (1.1.1)
61
+ concurrent-ruby (1.0.5)
62
+ diff-lcs (1.3)
63
+ dotenv (2.2.0)
64
+ dotenv-rails (2.2.0)
65
+ dotenv (= 2.2.0)
66
+ railties (>= 3.2, < 5.1)
67
+ erubis (2.7.0)
68
+ excon (0.55.0)
69
+ ffi (1.9.17)
70
+ formatador (0.2.5)
71
+ globalid (0.3.7)
72
+ activesupport (>= 4.1.0)
73
+ guard (2.14.1)
74
+ formatador (>= 0.2.4)
75
+ listen (>= 2.7, < 4.0)
76
+ lumberjack (~> 1.0)
77
+ nenv (~> 0.1)
78
+ notiffany (~> 0.0)
79
+ pry (>= 0.9.12)
80
+ shellany (~> 0.0)
81
+ thor (>= 0.18.1)
82
+ guard-compat (1.2.1)
83
+ guard-rspec (4.7.3)
84
+ guard (~> 2.1)
85
+ guard-compat (~> 1.1)
86
+ rspec (>= 2.99.0, < 4.0)
87
+ hashie (3.5.5)
88
+ heroics (0.0.21)
89
+ erubis (~> 2.0)
90
+ excon
91
+ multi_json (>= 1.9.2)
92
+ i18n (0.8.1)
93
+ listen (3.1.5)
94
+ rb-fsevent (~> 0.9, >= 0.9.4)
95
+ rb-inotify (~> 0.9, >= 0.9.7)
96
+ ruby_dep (~> 1.2)
97
+ loofah (2.0.3)
98
+ nokogiri (>= 1.5.9)
99
+ lumberjack (1.0.11)
100
+ mail (2.6.4)
101
+ mime-types (>= 1.16, < 4)
102
+ method_source (0.8.2)
103
+ mime-types (3.1)
104
+ mime-types-data (~> 3.2015)
105
+ mime-types-data (3.2016.0521)
106
+ mini_portile2 (2.1.0)
107
+ minitest (5.10.1)
108
+ multi_json (1.12.1)
109
+ nenv (0.3.0)
110
+ newrelic_rpm (3.18.1.330)
111
+ nio4r (1.2.1)
112
+ nokogiri (1.7.0.1)
113
+ mini_portile2 (~> 2.1.0)
114
+ notiffany (0.1.1)
115
+ nenv (~> 0.1)
116
+ shellany (~> 0.0)
117
+ platform-api (0.8.0)
118
+ heroics (~> 0.0.17)
119
+ pry (0.10.4)
120
+ coderay (~> 1.1.0)
121
+ method_source (~> 0.8.1)
122
+ slop (~> 3.4)
123
+ pry-byebug (3.4.2)
124
+ byebug (~> 9.0)
125
+ pry (~> 0.10)
126
+ rack (2.0.1)
127
+ rack-ssl-enforcer (0.2.9)
128
+ rack-test (0.6.3)
129
+ rack (>= 1.0)
130
+ rack-timeout (0.4.2)
131
+ rails (5.0.1)
132
+ actioncable (= 5.0.1)
133
+ actionmailer (= 5.0.1)
134
+ actionpack (= 5.0.1)
135
+ actionview (= 5.0.1)
136
+ activejob (= 5.0.1)
137
+ activemodel (= 5.0.1)
138
+ activerecord (= 5.0.1)
139
+ activesupport (= 5.0.1)
140
+ bundler (>= 1.3.0, < 2.0)
141
+ railties (= 5.0.1)
142
+ sprockets-rails (>= 2.0.0)
143
+ rails-dom-testing (2.0.2)
144
+ activesupport (>= 4.2.0, < 6.0)
145
+ nokogiri (~> 1.6)
146
+ rails-html-sanitizer (1.0.3)
147
+ loofah (~> 2.0)
148
+ railties (5.0.1)
149
+ actionpack (= 5.0.1)
150
+ activesupport (= 5.0.1)
151
+ method_source
152
+ rake (>= 0.8.7)
153
+ thor (>= 0.18.1, < 2.0)
154
+ rake (10.5.0)
155
+ rb-fsevent (0.9.8)
156
+ rb-inotify (0.9.8)
157
+ ffi (>= 0.5.0)
158
+ rspec (3.5.0)
159
+ rspec-core (~> 3.5.0)
160
+ rspec-expectations (~> 3.5.0)
161
+ rspec-mocks (~> 3.5.0)
162
+ rspec-core (3.5.4)
163
+ rspec-support (~> 3.5.0)
164
+ rspec-expectations (3.5.0)
165
+ diff-lcs (>= 1.2.0, < 2.0)
166
+ rspec-support (~> 3.5.0)
167
+ rspec-mocks (3.5.0)
168
+ diff-lcs (>= 1.2.0, < 2.0)
169
+ rspec-support (~> 3.5.0)
170
+ rspec-support (3.5.0)
171
+ ruby_dep (1.5.0)
172
+ shellany (0.0.1)
173
+ slop (3.6.0)
174
+ sprockets (3.7.1)
175
+ concurrent-ruby (~> 1.0)
176
+ rack (> 1, < 3)
177
+ sprockets-rails (3.2.0)
178
+ actionpack (>= 4.0)
179
+ activesupport (>= 4.0)
180
+ sprockets (>= 3.0.0)
181
+ thor (0.19.4)
182
+ thread_safe (0.3.6)
183
+ tzinfo (1.2.2)
184
+ thread_safe (~> 0.1)
185
+ websocket-driver (0.6.5)
186
+ websocket-extensions (>= 0.1.0)
187
+ websocket-extensions (0.1.2)
188
+
189
+ PLATFORMS
190
+ ruby
191
+
192
+ DEPENDENCIES
193
+ appraisal
194
+ bundler (~> 1.13)
195
+ guard
196
+ guard-rspec
197
+ pry-byebug
198
+ rails (~> 5.0)
199
+ rake (~> 10.0)
200
+ roo_on_rails!
201
+ rspec (~> 3.0)
202
+ thor (~> 0.19)
203
+
204
+ BUNDLED WITH
205
+ 1.14.6
@@ -1,10 +1,12 @@
1
1
  require 'roo_on_rails/checks/env_specific'
2
+ require 'roo_on_rails/checks/github/branch_protection'
2
3
  require 'roo_on_rails/checks/heroku/app_exists'
3
4
  require 'roo_on_rails/checks/heroku/preboot_enabled'
4
5
 
5
6
  module RooOnRails
6
7
  module Checks
7
8
  class Environment < EnvSpecific
9
+ requires GitHub::BranchProtection
8
10
  requires Heroku::PrebootEnabled
9
11
 
10
12
  def call
@@ -19,4 +21,3 @@ module RooOnRails
19
21
  end
20
22
  end
21
23
  end
22
-
@@ -0,0 +1,130 @@
1
+ require 'roo_on_rails/checks/base'
2
+ require 'roo_on_rails/checks/git/origin'
3
+ require 'roo_on_rails/checks/github/token'
4
+
5
+ module RooOnRails
6
+ module Checks
7
+ module GitHub
8
+ class BranchProtection < Base
9
+ requires GitHub::Token, Git::Origin
10
+
11
+ def intro
12
+ 'Checking if GitHub master branch is protected...'
13
+ end
14
+
15
+ def call
16
+ ensure_status_checks!
17
+ ensure_code_reviews!
18
+ ensure_no_push!
19
+ pass 'branch protection is sufficient'
20
+ end
21
+
22
+ def fix
23
+ client.protect_branch(
24
+ repo,
25
+ branch,
26
+ options.merge(
27
+ required_status_checks: fixed_required_status_checks,
28
+ required_pull_request_reviews: fixed_pull_request_reviews,
29
+ restrictions: fixed_restrictions
30
+ )
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def ensure_status_checks!
37
+ status_checks = protection[:required_status_checks] || {}
38
+ fail! 'status checks do not include admins' unless status_checks[:include_admins]
39
+
40
+ contexts = status_checks[:contexts] || []
41
+ ensure_ci_status_check!(contexts)
42
+ ensure_analysis_status_check!(contexts)
43
+ ensure_coverage_status_check!(contexts)
44
+ end
45
+
46
+ def ensure_ci_status_check!(contexts)
47
+ fail! 'no CI status check' unless contexts.include?(ci_context)
48
+ end
49
+
50
+ def ensure_analysis_status_check!(contexts)
51
+ fail! 'no code analysis status check' unless contexts.include?(analysis_context)
52
+ end
53
+
54
+ def ensure_coverage_status_check!(contexts)
55
+ return if (contexts & coverage_contexts) == coverage_contexts
56
+ fail! 'no code coverage status checks'
57
+ end
58
+
59
+ def ensure_code_reviews!
60
+ reviews = protection[:required_pull_request_reviews] || {}
61
+ fail! 'code reviews do not include admins' unless reviews[:include_admins]
62
+ end
63
+
64
+ def ensure_no_push!
65
+ users = protection.dig(:restrictions, :users)
66
+ teams = protection.dig(:restrictions, :teams)
67
+ fail! 'push restrictions should be enabled' if users.nil? || teams.nil?
68
+ fail! 'no users or teams should be allowed to push to master' if users.any? || teams.any?
69
+ end
70
+
71
+ def fixed_required_status_checks
72
+ status_checks = protection[:required_status_checks] || {}
73
+ status_checks.merge(
74
+ include_admins: true,
75
+ contexts: (status_checks[:contexts] || []) | [
76
+ ci_context,
77
+ analysis_context,
78
+ *coverage_contexts
79
+ ]
80
+ )
81
+ end
82
+
83
+ def fixed_pull_request_reviews
84
+ reviews = protection[:required_pull_request_reviews] || {}
85
+ reviews.merge(include_admins: true)
86
+ end
87
+
88
+ def fixed_restrictions
89
+ restrictions = protection[:restrictions] || {}
90
+ restrictions.merge(users: [], teams: [])
91
+ end
92
+
93
+ def ci_context
94
+ if Pathname.new('.travis.yml').exist? then 'continuous-integration/travis-ci'
95
+ else 'ci/circle-ci'
96
+ end
97
+ end
98
+
99
+ def analysis_context
100
+ 'codeclimate'
101
+ end
102
+
103
+ def coverage_contexts
104
+ %w(codecov/patch codecov/project)
105
+ end
106
+
107
+ def protection
108
+ client.branch_protection(repo, branch, options).to_h
109
+ end
110
+
111
+ def repo
112
+ "#{context.git_org}/#{context.git_repo}"
113
+ end
114
+
115
+ def branch
116
+ 'master'
117
+ end
118
+
119
+ def options
120
+ accept = Octokit::Preview::PREVIEW_TYPES[:branch_protection]
121
+ accept ? { accept: accept } : {}
122
+ end
123
+
124
+ def client
125
+ context.github.api_client
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,85 @@
1
+ require 'roo_on_rails/checks/base'
2
+ require 'octokit'
3
+ require 'socket'
4
+
5
+ module RooOnRails
6
+ module Checks
7
+ module GitHub
8
+ # Output context:
9
+ # - github.api_client: a connected Octokit client
10
+ class Token < Base
11
+ TOKEN_FILE = File.expand_path('~/.roo_on_rails/github-token').freeze
12
+ private_constant :TOKEN_FILE
13
+
14
+ def intro
15
+ 'Obtaining GitHub auth token...'
16
+ end
17
+
18
+ def call
19
+ token = File.exist?(TOKEN_FILE) && File.read(TOKEN_FILE)
20
+ fail! 'no token found' unless token && !token.empty?
21
+
22
+ oauth_client = Octokit::Client.new(access_token: token)
23
+ oauth_client.user # idempotent call to check access
24
+
25
+ context.github!.api_client = oauth_client
26
+ pass "connected to GitHub's API"
27
+ rescue Octokit::Error => e
28
+ fail! "#{e.class}: #{e.message}"
29
+ end
30
+
31
+ def fix
32
+ token = create_access_token
33
+ FileUtils.mkpath(File.dirname(TOKEN_FILE))
34
+ File.write(TOKEN_FILE, token)
35
+ rescue Octokit::Error => e
36
+ final_fail! "#{e.class}: #{e.message}"
37
+ end
38
+
39
+ private
40
+
41
+ def create_access_token
42
+ delete_existing_access_token
43
+ result = basic_client.create_authorization(
44
+ scopes: %w(repo),
45
+ note: token_name,
46
+ note_url: 'https://github.com/deliveroo/roo_on_rails',
47
+ headers: two_factor_headers
48
+ )
49
+ result[:token]
50
+ end
51
+
52
+ def delete_existing_access_token
53
+ authorizations = basic_client.authorizations(headers: two_factor_headers)
54
+ authorization = authorizations.find { |a| a[:note] == token_name }
55
+ return unless authorization
56
+
57
+ basic_client.delete_authorization(authorization[:id], headers: two_factor_headers)
58
+ end
59
+
60
+ def basic_client
61
+ @basic_client ||= begin
62
+ username = ask 'Enter your GitHub username:'
63
+ password = ask 'Enter your GitHub password (typing will be hidden):', echo: false
64
+ say # line break after non-echoed password
65
+ Octokit::Client.new(login: username, password: password)
66
+ end
67
+ end
68
+
69
+ def two_factor_headers
70
+ @two_factor_headers ||= begin
71
+ basic_client.user # idempotent call to check access
72
+ {}
73
+ rescue Octokit::OneTimePasswordRequired
74
+ otp = ask 'Enter your GitHub 2FA code:'
75
+ { 'X-GitHub-OTP' => otp }
76
+ end
77
+ end
78
+
79
+ def token_name
80
+ "Roo on Rails @ #{Socket.gethostname}"
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -13,7 +13,7 @@ module RooOnRails
13
13
  def self.included(by)
14
14
  by.class_eval do
15
15
  extend Forwardable
16
- delegate %i[say set_color] => :'RooOnRails::Checks::Helpers::Receiver.instance'
16
+ delegate %i[ask say set_color] => :'RooOnRails::Checks::Helpers::Receiver.instance'
17
17
  end
18
18
  end
19
19
 
@@ -7,3 +7,5 @@ NEW_RELIC_TRANSACTION_TRACER_RECORD_SQL=obfuscated
7
7
  NEW_RELIC_TRANSACTION_TRACER_RECORD_REDIS_ARGUMENTS=true
8
8
  NEW_RELIC_DEVELOPER_MODE=false
9
9
  NEW_RELIC_LICENSE_KEY=override-me
10
+ RACK_SERVICE_TIMEOUT=10
11
+ RACK_WAIT_TIMEOUT=30
@@ -0,0 +1,28 @@
1
+ # inspiration from:
2
+ # https://devcenter.heroku.com/articles/concurrency-and-database-connections#multi-process-servers
3
+ # https://devcenter.heroku.com/articles/postgres-logs-errors#pgerror-prepared-statement-a30-already-exists
4
+ # http://stackoverflow.com/questions/8118074/is-the-prepared-statement-cache-cleared-per-request-in-rails-3-1
5
+ # http://stackoverflow.com/questions/16775795/rails-switch-connection-on-each-request-but-keep-a-connection-pool
6
+
7
+ module RooOnRails
8
+ module Rack
9
+ # Cleans up Rails database connections on timeouts, before they're returned
10
+ # to the pool.
11
+ #
12
+ # In particular, this clears the prepared statement cache, which can become
13
+ # corrupted as ActiveRecord isn't interrupt-safe.
14
+ class SafeTimeouts
15
+ def initialize(app)
16
+ @app = app
17
+ end
18
+
19
+ def call(env)
20
+ @app.call(env)
21
+ rescue Rack::Timeout::Error, Rack::Timeout::RequestTimeoutException
22
+ Rails.logger.warn('Clearing ActiveRecord connection cache due to timeout')
23
+ ActiveRecord::Base.connection.clear_cache!
24
+ raise
25
+ end
26
+ end
27
+ end
28
+ end
@@ -12,30 +12,5 @@ module RooOnRails
12
12
  # puts "#{k}: #{v}"
13
13
  # end
14
14
  # end
15
-
16
- initializer 'roo_on_rails.new_relic' do
17
- $stderr.puts 'initializer roo_on_rails.new_relic'
18
-
19
- license_key = ENV['NEW_RELIC_LICENSE_KEY']
20
-
21
- if %w[ test development ].exclude?(Rails.env.to_s) and license_key == 'override-me'
22
- abort 'Aborting: NEW_RELIC_LICENSE_KEY must be set in production environments'
23
- end
24
-
25
- if license_key.nil?
26
- abort 'Aborting: NEW_RELIC_LICENSE_KEY is required'
27
- end
28
-
29
- path = %w[newrelic.yml config/newrelic.yml].map { |p|
30
- Pathname.new(p)
31
- }.find(&:exist?)
32
- if path
33
- abort "Aborting: newrelic.yml detected in '#{path.parent.realpath}', should not exist"
34
- end
35
-
36
- require 'newrelic_rpm'
37
- ::NewRelic::Agent.manual_start unless Rails.env.test?
38
- end
39
15
  end
40
16
  end
41
-
@@ -0,0 +1,38 @@
1
+ module RooOnRails
2
+ module Railties
3
+ class HTTP < Rails::Railtie
4
+ initializer 'roo_on_rails.http' do |app|
5
+ $stderr.puts 'initializer roo_on_rails.http'
6
+ require 'rack/timeout/base'
7
+ require 'rack/ssl-enforcer'
8
+
9
+ require 'roo_on_rails/rack/safe_timeouts'
10
+
11
+ ::Rack::Timeout.service_timeout = ENV.fetch('RACK_SERVICE_TIMEOUT', 15).to_i
12
+ ::Rack::Timeout.wait_timeout = ENV.fetch('RACK_WAIT_TIMEOUT', 30).to_i
13
+ ::Rack::Timeout::Logger.level = Logger::WARN
14
+
15
+ app.config.middleware.insert_before(
16
+ ::Rack::Runtime,
17
+ ::Rack::Timeout
18
+ )
19
+
20
+ # This needs to be inserted low in the stack, before Rails returns the
21
+ # thread-current connection to the pool.
22
+ app.config.middleware.insert_before(
23
+ ActionDispatch::Cookies,
24
+ RooOnRails::Rack::SafeTimeouts
25
+ )
26
+
27
+ if ENV.fetch('ROO_ON_RAILS_RACK_DEFLATE', 'YES').to_s =~ /\A(YES|TRUE|ON|1)\Z/i
28
+ app.config.middleware.use ::Rack::Deflater
29
+ end
30
+
31
+ app.config.middleware.insert_before(
32
+ ActionDispatch::Cookies,
33
+ ::Rack::SslEnforcer
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ module RooOnRails
2
+ module Railties
3
+ class NewRelic < Rails::Railtie
4
+ initializer 'roo_on_rails.new_relic' do
5
+ $stderr.puts 'initializer roo_on_rails.new_relic'
6
+
7
+ license_key = ENV['NEW_RELIC_LICENSE_KEY']
8
+
9
+ if %w(test development).exclude?(Rails.env.to_s) && (license_key == 'override-me')
10
+ abort 'Aborting: NEW_RELIC_LICENSE_KEY must be set in production environments'
11
+ end
12
+
13
+ abort 'Aborting: NEW_RELIC_LICENSE_KEY is required' if license_key.nil?
14
+
15
+ path = %w(newrelic.yml config/newrelic.yml).map do |p|
16
+ Pathname.new(p)
17
+ end.find(&:exist?)
18
+ if path
19
+ abort "Aborting: newrelic.yml detected in '#{path.parent.realpath}', should not exist"
20
+ end
21
+
22
+ require 'newrelic_rpm'
23
+ ::NewRelic::Agent.manual_start unless Rails.env.test?
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,3 @@
1
1
  module RooOnRails
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
data/lib/roo_on_rails.rb CHANGED
@@ -6,4 +6,6 @@ end
6
6
  if defined?(Rails)
7
7
  require 'dotenv/rails-now'
8
8
  require 'roo_on_rails/railtie'
9
+ require 'roo_on_rails/railties/new_relic'
10
+ require 'roo_on_rails/railties/http'
9
11
  end
data/roo_on_rails.gemspec CHANGED
@@ -4,32 +4,38 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'roo_on_rails/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "roo_on_rails"
7
+ spec.name = 'roo_on_rails'
8
8
  spec.version = RooOnRails::VERSION
9
- spec.authors = ["Julien Letessier"]
10
- spec.email = ["julien.letessier@gmail.com"]
9
+ spec.authors = ['Julien Letessier']
10
+ spec.email = ['julien.letessier@gmail.com']
11
11
 
12
- spec.summary = %q{Scaffolding for building services}
13
- spec.description = %q{Scaffolding for building services}
12
+ spec.summary = 'Scaffolding for building services'
13
+ spec.description = 'Scaffolding for building services'
14
14
  spec.homepage = 'https://github.com/deliveroo/roo_on_rails'
15
- spec.license = "MIT"
15
+ spec.license = 'MIT'
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
20
- spec.bindir = "exe"
20
+ spec.bindir = 'exe'
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
22
+ spec.require_paths = ['lib']
23
23
 
24
24
  spec.add_runtime_dependency 'dotenv-rails', '~> 2.1'
25
25
  spec.add_runtime_dependency 'newrelic_rpm', '~> 3.17'
26
- spec.add_runtime_dependency 'rails', '~> 5.0'
26
+ spec.add_runtime_dependency 'rails', '>= 3.2.22', '< 5.1'
27
27
  spec.add_runtime_dependency 'platform-api', '~> 0.8'
28
28
  spec.add_runtime_dependency 'hashie', '~> 3.4'
29
+ spec.add_runtime_dependency 'rack-timeout'
30
+ spec.add_runtime_dependency 'rack-ssl-enforcer'
31
+ spec.add_runtime_dependency 'octokit'
29
32
 
30
- spec.add_development_dependency "bundler", "~> 1.13"
31
- spec.add_development_dependency "rake", "~> 10.0"
32
- spec.add_development_dependency "rspec", "~> 3.0"
33
+ spec.add_development_dependency 'bundler', '~> 1.13'
34
+ spec.add_development_dependency 'rake', '~> 10.0'
35
+ spec.add_development_dependency 'rspec', '~> 3.0'
33
36
  spec.add_development_dependency 'thor', '~> 0.19'
34
37
  spec.add_development_dependency 'pry-byebug'
38
+ spec.add_development_dependency 'memfs'
39
+ spec.add_development_dependency 'simplecov'
40
+ spec.add_development_dependency 'codecov'
35
41
  end