suspenders 1.44.0 → 1.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +1 -1
- data/LICENSE +1 -1
- data/NEWS.md +27 -0
- data/README.md +7 -4
- data/lib/suspenders.rb +2 -0
- data/lib/suspenders/actions.rb +6 -1
- data/lib/suspenders/adapters/heroku.rb +18 -0
- data/lib/suspenders/app_builder.rb +24 -30
- data/lib/suspenders/generators/app_generator.rb +11 -14
- data/lib/suspenders/generators/enforce_ssl_generator.rb +12 -0
- data/lib/suspenders/generators/initialize_active_job_generator.rb +19 -0
- data/lib/suspenders/generators/stylesheet_base_generator.rb +6 -2
- data/lib/suspenders/version.rb +2 -2
- data/spec/adapters/heroku_spec.rb +15 -0
- data/spec/features/heroku_spec.rb +4 -8
- data/spec/features/new_project_spec.rb +38 -4
- data/spec/support/suspenders.rb +17 -1
- data/suspenders.gemspec +1 -1
- data/templates/Gemfile.erb +11 -7
- data/templates/Procfile +1 -1
- data/templates/_analytics.html.erb +4 -3
- data/templates/active_job.rb +13 -0
- data/templates/application.scss +1 -1
- data/templates/bin_deploy +1 -1
- data/templates/bin_setup +7 -3
- data/templates/bin_setup_review_app.erb +5 -2
- data/templates/bundler_audit.rake +2 -10
- data/templates/postgresql_database.yml.erb +0 -2
- data/templates/secrets.yml +1 -7
- data/templates/spec_helper.rb +4 -0
- data/templates/suspenders_gitignore +6 -1
- metadata +11 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 253fc6f3c173bce9e7858831161cf75924094222
|
|
4
|
+
data.tar.gz: 947de81dd1fc955c04f13ea1260e4391b505b0f2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 003c8627d76eaad3f8a51f404608dc1cd66ee35dbaba8b45cf6f5ef0e9a06fc4fe7f826f9f387a51118d2670df7499a46b83a7441541e21f5a0b691a08a0e063
|
|
7
|
+
data.tar.gz: 3a08ab29152033941e6a1b2baba20743d2992ab9872e590e7815007cadcbba37514700cc6f9deaed72f02408458a21d1ed020f15c1e060e16250bd7da01a5553
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.4.
|
|
1
|
+
2.4.1
|
data/.travis.yml
CHANGED
data/LICENSE
CHANGED
data/NEWS.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
1.45.0 (September 8, 2017)
|
|
2
|
+
|
|
3
|
+
* Bump Rails to 5.1.3 (#857)
|
|
4
|
+
* Configure HONEYBADGER_ENV for staging, production (#861)
|
|
5
|
+
* Remove vestigial `staging` references (#860)
|
|
6
|
+
* Prevent memory bloat in ActiveJob children (#856)
|
|
7
|
+
* .git/safe is opt-in (#837)
|
|
8
|
+
* Enforce SSL in production environment (#855)
|
|
9
|
+
* Configures action mailer asset host (#853)
|
|
10
|
+
* Install normalize.css via yarn (#851)
|
|
11
|
+
* Update Rails to 5.1 (#847)
|
|
12
|
+
* Update bourbon from 5.0.0.beta.7 to 5.0.0.beta.8 (#848)
|
|
13
|
+
* Update Neat to 2.1 (#849)
|
|
14
|
+
* Update Bitters to 1.7 (#850)
|
|
15
|
+
* Fix incorrect Timecop link (#845)
|
|
16
|
+
* Update Ruby to 2.4.1 (#841)
|
|
17
|
+
* Update rspec-rails to 3.6 (#842)
|
|
18
|
+
* Configure TimeCop safe mode (#840)
|
|
19
|
+
* Pull normalize.css through Rails Assets (#839)
|
|
20
|
+
* Fix fatal git failures in tests (#832)
|
|
21
|
+
* Schedule Heroku Backups and Capture backup of existing staging database for
|
|
22
|
+
Review Apps (#826)
|
|
23
|
+
* Use bundle-audit rake task from the gem (#831)
|
|
24
|
+
* Update thoughtbot logo (#829)
|
|
25
|
+
* Change terminal symbol in README's deploying section (#828)
|
|
26
|
+
* Update Segment snippet to 4.0.0 (#822)
|
|
27
|
+
|
|
1
28
|
1.44.0 (January 25, 2017)
|
|
2
29
|
|
|
3
30
|
* Improve readability of `bin/setup-review-app` (#819)
|
data/README.md
CHANGED
|
@@ -87,7 +87,7 @@ And testing gems like:
|
|
|
87
87
|
* [RSpec Mocks](https://github.com/rspec/rspec-mocks) for stubbing and spying
|
|
88
88
|
* [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for common
|
|
89
89
|
RSpec matchers
|
|
90
|
-
* [Timecop](https://github.com/
|
|
90
|
+
* [Timecop](https://github.com/travisjeffery/timecop) for testing time
|
|
91
91
|
|
|
92
92
|
## Other goodies
|
|
93
93
|
|
|
@@ -127,9 +127,10 @@ This:
|
|
|
127
127
|
|
|
128
128
|
* Creates a staging and production Heroku app
|
|
129
129
|
* Sets them as `staging` and `production` Git remotes
|
|
130
|
-
* Configures staging with `
|
|
130
|
+
* Configures staging with `HONEYBADGER_ENV` environment variable set
|
|
131
131
|
to `staging`
|
|
132
132
|
* Creates a [Heroku Pipeline] for review apps
|
|
133
|
+
* Schedules automated backups for 10AM UTC for both `staging` and `production`
|
|
133
134
|
|
|
134
135
|
[Heroku Pipeline]: https://devcenter.heroku.com/articles/pipelines
|
|
135
136
|
|
|
@@ -205,7 +206,7 @@ Thank you, [contributors]!
|
|
|
205
206
|
|
|
206
207
|
## License
|
|
207
208
|
|
|
208
|
-
Suspenders is Copyright © 2008-
|
|
209
|
+
Suspenders is Copyright © 2008-2017 thoughtbot.
|
|
209
210
|
It is free software,
|
|
210
211
|
and may be redistributed under the terms specified in the [LICENSE] file.
|
|
211
212
|
|
|
@@ -213,7 +214,7 @@ and may be redistributed under the terms specified in the [LICENSE] file.
|
|
|
213
214
|
|
|
214
215
|
## About thoughtbot
|
|
215
216
|
|
|
216
|
-
![thoughtbot]
|
|
217
|
+
[![thoughtbot][thoughtbot-logo]][thoughtbot]
|
|
217
218
|
|
|
218
219
|
Suspenders is maintained and funded by thoughtbot, inc.
|
|
219
220
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
|
@@ -222,5 +223,7 @@ We love open source software!
|
|
|
222
223
|
See [our other projects][community].
|
|
223
224
|
We are [available for hire][hire].
|
|
224
225
|
|
|
226
|
+
[thoughtbot]: https://thoughtbot.com?utm_source=github
|
|
227
|
+
[thoughtbot-logo]: http://presskit.thoughtbot.com/images/thoughtbot-logo-for-readmes.svg
|
|
225
228
|
[community]: https://thoughtbot.com/community?utm_source=github
|
|
226
229
|
[hire]: https://thoughtbot.com?utm_source=github
|
data/lib/suspenders.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
require 'suspenders/version'
|
|
2
2
|
require 'suspenders/generators/app_generator'
|
|
3
|
+
require "suspenders/generators/enforce_ssl_generator"
|
|
4
|
+
require "suspenders/generators/initialize_active_job_generator"
|
|
3
5
|
require 'suspenders/generators/static_generator'
|
|
4
6
|
require 'suspenders/generators/stylesheet_base_generator'
|
|
5
7
|
require 'suspenders/actions'
|
data/lib/suspenders/actions.rb
CHANGED
|
@@ -14,6 +14,11 @@ module Suspenders
|
|
|
14
14
|
configure_environment(rails_env, config)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
def action_mailer_asset_host(rails_env, host)
|
|
18
|
+
config = "config.action_mailer.asset_host = { host: #{host} }"
|
|
19
|
+
configure_environment(rails_env, config)
|
|
20
|
+
end
|
|
21
|
+
|
|
17
22
|
def configure_application_file(config)
|
|
18
23
|
inject_into_file(
|
|
19
24
|
"config/application.rb",
|
|
@@ -25,7 +30,7 @@ module Suspenders
|
|
|
25
30
|
def configure_environment(rails_env, config)
|
|
26
31
|
inject_into_file(
|
|
27
32
|
"config/environments/#{rails_env}.rb",
|
|
28
|
-
"\n
|
|
33
|
+
"\n #{config}",
|
|
29
34
|
before: "\nend"
|
|
30
35
|
)
|
|
31
36
|
end
|
|
@@ -37,6 +37,24 @@ module Suspenders
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
+
def set_heroku_honeybadger_env
|
|
41
|
+
%w(staging production).each do |environment|
|
|
42
|
+
run_toolbelt_command(
|
|
43
|
+
"config:add HONEYBADGER_ENV=#{environment}",
|
|
44
|
+
environment,
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def set_heroku_backup_schedule
|
|
50
|
+
%w(staging production).each do |environment|
|
|
51
|
+
run_toolbelt_command(
|
|
52
|
+
"pg:backups:schedule DATABASE_URL --at '10:00 UTC'",
|
|
53
|
+
environment,
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
40
58
|
def create_review_apps_setup_script
|
|
41
59
|
app_builder.template(
|
|
42
60
|
"bin_setup_review_app.erb",
|
|
@@ -5,15 +5,19 @@ module Suspenders
|
|
|
5
5
|
include Suspenders::Actions
|
|
6
6
|
extend Forwardable
|
|
7
7
|
|
|
8
|
-
def_delegators
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
def_delegators(
|
|
9
|
+
:heroku_adapter,
|
|
10
|
+
:create_heroku_application_manifest_file,
|
|
11
|
+
:create_heroku_pipeline,
|
|
12
|
+
:create_production_heroku_app,
|
|
13
|
+
:create_review_apps_setup_script,
|
|
14
|
+
:create_staging_heroku_app,
|
|
15
|
+
:set_heroku_application_host,
|
|
16
|
+
:set_heroku_backup_schedule,
|
|
17
|
+
:set_heroku_honeybadger_env,
|
|
18
|
+
:set_heroku_rails_secrets,
|
|
19
|
+
:set_heroku_remotes,
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
def readme
|
|
19
23
|
template 'README.md.erb', 'README.md'
|
|
@@ -43,14 +47,6 @@ module Suspenders
|
|
|
43
47
|
'raise_delivery_errors = false', 'raise_delivery_errors = true'
|
|
44
48
|
end
|
|
45
49
|
|
|
46
|
-
def remove_turbolinks
|
|
47
|
-
replace_in_file(
|
|
48
|
-
"app/assets/javascripts/application.js",
|
|
49
|
-
"//= require turbolinks",
|
|
50
|
-
""
|
|
51
|
-
)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
50
|
def set_test_delivery_method
|
|
55
51
|
inject_into_file(
|
|
56
52
|
"config/environments/development.rb",
|
|
@@ -157,11 +153,7 @@ module Suspenders
|
|
|
157
153
|
config.middleware.use Rack::CanonicalHost, ENV.fetch("APPLICATION_HOST")
|
|
158
154
|
RUBY
|
|
159
155
|
|
|
160
|
-
|
|
161
|
-
"config/environments/production.rb",
|
|
162
|
-
config,
|
|
163
|
-
after: "Rails.application.configure do",
|
|
164
|
-
)
|
|
156
|
+
configure_environment "production", config
|
|
165
157
|
end
|
|
166
158
|
|
|
167
159
|
def enable_rack_deflater
|
|
@@ -226,7 +218,7 @@ config.public_file_server.headers = {
|
|
|
226
218
|
end
|
|
227
219
|
|
|
228
220
|
def create_database
|
|
229
|
-
bundle_command
|
|
221
|
+
bundle_command "exec rails db:create db:migrate"
|
|
230
222
|
end
|
|
231
223
|
|
|
232
224
|
def replace_gemfile(path)
|
|
@@ -310,8 +302,14 @@ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
|
|
|
310
302
|
|
|
311
303
|
def configure_action_mailer
|
|
312
304
|
action_mailer_host "development", %{"localhost:3000"}
|
|
305
|
+
action_mailer_asset_host "development", %{"localhost:3000"}
|
|
313
306
|
action_mailer_host "test", %{"www.example.com"}
|
|
307
|
+
action_mailer_asset_host "test", %{"www.example.com"}
|
|
314
308
|
action_mailer_host "production", %{ENV.fetch("APPLICATION_HOST")}
|
|
309
|
+
action_mailer_asset_host(
|
|
310
|
+
"production",
|
|
311
|
+
%{ENV.fetch("ASSET_HOST", ENV.fetch("APPLICATION_HOST"))},
|
|
312
|
+
)
|
|
315
313
|
end
|
|
316
314
|
|
|
317
315
|
def configure_active_job
|
|
@@ -351,10 +349,6 @@ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
|
|
|
351
349
|
directory("dotfiles", ".")
|
|
352
350
|
end
|
|
353
351
|
|
|
354
|
-
def init_git
|
|
355
|
-
run 'git init'
|
|
356
|
-
end
|
|
357
|
-
|
|
358
352
|
def create_heroku_apps(flags)
|
|
359
353
|
create_staging_heroku_app(flags)
|
|
360
354
|
create_production_heroku_app(flags)
|
|
@@ -370,8 +364,8 @@ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
|
|
|
370
364
|
If you have previously run the `./bin/setup` script,
|
|
371
365
|
you can deploy to staging and production with:
|
|
372
366
|
|
|
373
|
-
|
|
374
|
-
|
|
367
|
+
% ./bin/deploy staging
|
|
368
|
+
% ./bin/deploy production
|
|
375
369
|
MARKDOWN
|
|
376
370
|
|
|
377
371
|
append_file "README.md", instructions
|
|
@@ -401,7 +395,7 @@ you can deploy to staging and production with:
|
|
|
401
395
|
|
|
402
396
|
def setup_bundler_audit
|
|
403
397
|
copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake"
|
|
404
|
-
append_file "Rakefile", %{\ntask default: "
|
|
398
|
+
append_file "Rakefile", %{\ntask default: "bundle:audit"\n}
|
|
405
399
|
end
|
|
406
400
|
|
|
407
401
|
def setup_spring
|
|
@@ -29,6 +29,12 @@ module Suspenders
|
|
|
29
29
|
class_option :skip_test, type: :boolean, default: true,
|
|
30
30
|
desc: "Skip Test Unit"
|
|
31
31
|
|
|
32
|
+
class_option :skip_system_test,
|
|
33
|
+
type: :boolean, default: true, desc: "Skip system test files"
|
|
34
|
+
|
|
35
|
+
class_option :skip_turbolinks,
|
|
36
|
+
type: :boolean, default: true, desc: "Skip turbolinks gem"
|
|
37
|
+
|
|
32
38
|
def finish_template
|
|
33
39
|
invoke :suspenders_customization
|
|
34
40
|
super
|
|
@@ -47,7 +53,6 @@ module Suspenders
|
|
|
47
53
|
invoke :remove_config_comment_lines
|
|
48
54
|
invoke :remove_routes_comment_lines
|
|
49
55
|
invoke :setup_dotfiles
|
|
50
|
-
invoke :setup_git
|
|
51
56
|
invoke :setup_database
|
|
52
57
|
invoke :create_local_heroku_setup
|
|
53
58
|
invoke :create_heroku_apps
|
|
@@ -56,6 +61,7 @@ module Suspenders
|
|
|
56
61
|
invoke :setup_bundler_audit
|
|
57
62
|
invoke :setup_spring
|
|
58
63
|
invoke :generate_default
|
|
64
|
+
invoke :setup_default_directories
|
|
59
65
|
invoke :outro
|
|
60
66
|
end
|
|
61
67
|
|
|
@@ -80,7 +86,6 @@ module Suspenders
|
|
|
80
86
|
say 'Setting up the development environment'
|
|
81
87
|
build :raise_on_missing_assets_in_test
|
|
82
88
|
build :raise_on_delivery_errors
|
|
83
|
-
build :remove_turbolinks
|
|
84
89
|
build :set_test_delivery_method
|
|
85
90
|
build :add_bullet_gem_configuration
|
|
86
91
|
build :raise_on_unpermitted_parameters
|
|
@@ -142,14 +147,6 @@ module Suspenders
|
|
|
142
147
|
build :setup_rack_mini_profiler
|
|
143
148
|
end
|
|
144
149
|
|
|
145
|
-
def setup_git
|
|
146
|
-
if !options[:skip_git]
|
|
147
|
-
say "Initializing git"
|
|
148
|
-
invoke :setup_default_directories
|
|
149
|
-
invoke :init_git
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
|
|
153
150
|
def create_local_heroku_setup
|
|
154
151
|
say "Creating local Heroku setup"
|
|
155
152
|
build :create_review_apps_setup_script
|
|
@@ -164,6 +161,8 @@ module Suspenders
|
|
|
164
161
|
build :set_heroku_remotes
|
|
165
162
|
build :set_heroku_rails_secrets
|
|
166
163
|
build :set_heroku_application_host
|
|
164
|
+
build :set_heroku_honeybadger_env
|
|
165
|
+
build :set_heroku_backup_schedule
|
|
167
166
|
build :create_heroku_pipeline
|
|
168
167
|
build :configure_automatic_deployment
|
|
169
168
|
end
|
|
@@ -199,10 +198,6 @@ module Suspenders
|
|
|
199
198
|
build :setup_spring
|
|
200
199
|
end
|
|
201
200
|
|
|
202
|
-
def init_git
|
|
203
|
-
build :init_git
|
|
204
|
-
end
|
|
205
|
-
|
|
206
201
|
def copy_miscellaneous_files
|
|
207
202
|
say 'Copying miscellaneous support files'
|
|
208
203
|
build :copy_miscellaneous_files
|
|
@@ -223,6 +218,8 @@ module Suspenders
|
|
|
223
218
|
|
|
224
219
|
def generate_default
|
|
225
220
|
run("spring stop")
|
|
221
|
+
generate("suspenders:initialize_active_job")
|
|
222
|
+
generate("suspenders:enforce_ssl")
|
|
226
223
|
generate("suspenders:static")
|
|
227
224
|
generate("suspenders:stylesheet_base")
|
|
228
225
|
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require "rails/generators"
|
|
2
|
+
require_relative "../actions"
|
|
3
|
+
|
|
4
|
+
module Suspenders
|
|
5
|
+
class EnforceSslGenerator < Rails::Generators::Base
|
|
6
|
+
include Suspenders::Actions
|
|
7
|
+
|
|
8
|
+
def enforce_ssl
|
|
9
|
+
configure_environment "production", "config.force_ssl = true"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "rails/generators"
|
|
2
|
+
|
|
3
|
+
module Suspenders
|
|
4
|
+
class InitializeActiveJobGenerator < Rails::Generators::Base
|
|
5
|
+
source_root(
|
|
6
|
+
File.expand_path(
|
|
7
|
+
File.join("..", "..", "..", "templates"),
|
|
8
|
+
File.dirname(__FILE__),
|
|
9
|
+
),
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
def initialize_active_job
|
|
13
|
+
copy_file(
|
|
14
|
+
"active_job.rb",
|
|
15
|
+
"config/initializers/active_job.rb",
|
|
16
|
+
)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -7,8 +7,8 @@ module Suspenders
|
|
|
7
7
|
File.dirname(__FILE__))
|
|
8
8
|
|
|
9
9
|
def add_stylesheet_gems
|
|
10
|
-
gem "bourbon", "~> 5.0.0.beta.
|
|
11
|
-
gem "neat", "~> 2.
|
|
10
|
+
gem "bourbon", "~> 5.0.0.beta.8"
|
|
11
|
+
gem "neat", "~> 2.1"
|
|
12
12
|
gem "refills", group: [:development, :test]
|
|
13
13
|
Bundler.with_clean_env { run "bundle install" }
|
|
14
14
|
end
|
|
@@ -33,5 +33,9 @@ module Suspenders
|
|
|
33
33
|
def install_bitters
|
|
34
34
|
run "bitters install --path app/assets/stylesheets"
|
|
35
35
|
end
|
|
36
|
+
|
|
37
|
+
def install_normalize_css
|
|
38
|
+
run "bin/yarn add normalize.css"
|
|
39
|
+
end
|
|
36
40
|
end
|
|
37
41
|
end
|
data/lib/suspenders/version.rb
CHANGED
|
@@ -30,6 +30,16 @@ module Suspenders
|
|
|
30
30
|
)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
it "sets the heroku backup schedule" do
|
|
34
|
+
app_builder = double(app_name: app_name)
|
|
35
|
+
allow(app_builder).to receive(:run)
|
|
36
|
+
|
|
37
|
+
Heroku.new(app_builder).set_heroku_backup_schedule
|
|
38
|
+
|
|
39
|
+
expect(app_builder).to have_backup_schedule("staging")
|
|
40
|
+
expect(app_builder).to have_backup_schedule("production")
|
|
41
|
+
end
|
|
42
|
+
|
|
33
43
|
it "sets the application host" do
|
|
34
44
|
app_builder = double(app_name: app_name)
|
|
35
45
|
allow(app_builder).to receive(:run)
|
|
@@ -49,6 +59,11 @@ module Suspenders
|
|
|
49
59
|
SuspendersTestHelpers::APP_NAME
|
|
50
60
|
end
|
|
51
61
|
|
|
62
|
+
def have_backup_schedule(remote_name)
|
|
63
|
+
have_received(:run).
|
|
64
|
+
with(/pg:backups:schedule DATABASE_URL --at '10:00 UTC' --remote #{remote_name}/)
|
|
65
|
+
end
|
|
66
|
+
|
|
52
67
|
def have_configured_var(remote_name, var)
|
|
53
68
|
have_received(:run).with(/config:add #{var}=.+ --remote #{remote_name}/)
|
|
54
69
|
end
|
|
@@ -18,14 +18,10 @@ RSpec.describe "Heroku" do
|
|
|
18
18
|
"production",
|
|
19
19
|
"SECRET_KEY_BASE",
|
|
20
20
|
)
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
expect(FakeHeroku).to have_configured_vars(
|
|
26
|
-
"production",
|
|
27
|
-
"APPLICATION_HOST",
|
|
28
|
-
)
|
|
21
|
+
%w(staging production).each do |env|
|
|
22
|
+
expect(FakeHeroku).to have_configured_vars(env, "APPLICATION_HOST")
|
|
23
|
+
expect(FakeHeroku).to have_configured_vars(env, "HONEYBADGER_ENV")
|
|
24
|
+
end
|
|
29
25
|
expect(FakeHeroku).to have_setup_pipeline_for(app_name)
|
|
30
26
|
|
|
31
27
|
bin_setup_path = "#{project_path}/bin/setup"
|
|
@@ -29,6 +29,14 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
it "includes the bundle:audit task" do
|
|
33
|
+
Dir.chdir(project_path) do
|
|
34
|
+
Bundler.with_clean_env do
|
|
35
|
+
expect(`rails -T`).to include("rails bundle:audit")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
32
40
|
it "creates .ruby-version from Suspenders .ruby-version" do
|
|
33
41
|
ruby_version_file = IO.read("#{project_path}/.ruby-version")
|
|
34
42
|
|
|
@@ -92,6 +100,11 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
92
100
|
expect(env).to include "RACK_MINI_PROFILER=0"
|
|
93
101
|
end
|
|
94
102
|
|
|
103
|
+
it "initializes ActiveJob to avoid memory bloat" do
|
|
104
|
+
expect(File).
|
|
105
|
+
to exist("#{project_path}/config/initializers/active_job.rb")
|
|
106
|
+
end
|
|
107
|
+
|
|
95
108
|
it "creates a rack-mini-profiler initializer" do
|
|
96
109
|
expect(File).
|
|
97
110
|
to exist("#{project_path}/config/initializers/rack_mini_profiler.rb")
|
|
@@ -101,7 +114,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
101
114
|
expect(analytics_partial).
|
|
102
115
|
to include(%{<% if ENV["SEGMENT_KEY"] %>})
|
|
103
116
|
expect(analytics_partial).
|
|
104
|
-
to include(%{
|
|
117
|
+
to include(%{analytics.load("<%= ENV["SEGMENT_KEY"] %>");})
|
|
105
118
|
end
|
|
106
119
|
|
|
107
120
|
it "raises on unpermitted parameters in all environments" do
|
|
@@ -124,6 +137,12 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
124
137
|
)
|
|
125
138
|
end
|
|
126
139
|
|
|
140
|
+
it "configures production environment to enforce SSL" do
|
|
141
|
+
expect(production_config).to match(
|
|
142
|
+
/^ +config.force_ssl = true/,
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
|
|
127
146
|
it "raises on missing translations in development and test" do
|
|
128
147
|
[development_config, test_config].each do |environment_file|
|
|
129
148
|
expect(environment_file).to match(
|
|
@@ -147,6 +166,13 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
147
166
|
to match(/^ +config.action_mailer.delivery_method = :file$/)
|
|
148
167
|
end
|
|
149
168
|
|
|
169
|
+
it "sets action mailer default host and asset host" do
|
|
170
|
+
config_key = 'config\.action_mailer\.asset_host'
|
|
171
|
+
config_value =
|
|
172
|
+
'{ host: ENV\.fetch\("ASSET_HOST", ENV\.fetch\("APPLICATION_HOST"\)\) }'
|
|
173
|
+
expect(production_config).to match(/#{config_key} = #{config_value}/)
|
|
174
|
+
end
|
|
175
|
+
|
|
150
176
|
it "uses APPLICATION_HOST, not HOST in the production config" do
|
|
151
177
|
expect(production_config).to match(/"APPLICATION_HOST"/)
|
|
152
178
|
expect(production_config).not_to match(/"HOST"/)
|
|
@@ -221,7 +247,8 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
221
247
|
|
|
222
248
|
expect(bin_setup).to include("PARENT_APP_NAME=#{app_name.dasherize}-staging")
|
|
223
249
|
expect(bin_setup).to include("APP_NAME=#{app_name.dasherize}-staging-pr-$1")
|
|
224
|
-
expect(bin_setup).
|
|
250
|
+
expect(bin_setup).
|
|
251
|
+
to include("heroku run rails db:migrate --exit-code --app $APP_NAME")
|
|
225
252
|
expect(bin_setup).to include("heroku ps:scale worker=1 --app $APP_NAME")
|
|
226
253
|
expect(bin_setup).to include("heroku restart --app $APP_NAME")
|
|
227
254
|
|
|
@@ -232,7 +259,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
232
259
|
bin_deploy_path = "#{project_path}/bin/deploy"
|
|
233
260
|
bin_deploy = IO.read(bin_deploy_path)
|
|
234
261
|
|
|
235
|
-
expect(bin_deploy).to include("heroku run
|
|
262
|
+
expect(bin_deploy).to include("heroku run rails db:migrate --exit-code")
|
|
236
263
|
expect(File.stat(bin_deploy_path)).to be_executable
|
|
237
264
|
end
|
|
238
265
|
|
|
@@ -264,7 +291,9 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
264
291
|
expect(read_project_file(flashes_path)).to match(/\$flashes/m)
|
|
265
292
|
|
|
266
293
|
app_css = read_project_file(%w(app assets stylesheets application.scss))
|
|
267
|
-
expect(app_css).to match(
|
|
294
|
+
expect(app_css).to match(
|
|
295
|
+
/normalize\.css\/normalize\.css.*bourbon.*neat.*base.*refills/m,
|
|
296
|
+
)
|
|
268
297
|
end
|
|
269
298
|
|
|
270
299
|
it "doesn't use turbolinks" do
|
|
@@ -272,6 +301,11 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
|
272
301
|
expect(app_js).not_to match(/turbolinks/)
|
|
273
302
|
end
|
|
274
303
|
|
|
304
|
+
it "configures Timecop safe mode" do
|
|
305
|
+
spec_helper = read_project_file(%w(spec spec_helper.rb))
|
|
306
|
+
expect(spec_helper).to match(/Timecop.safe_mode = true/)
|
|
307
|
+
end
|
|
308
|
+
|
|
275
309
|
def development_config
|
|
276
310
|
@_development_config ||=
|
|
277
311
|
read_project_file %w(config environments development.rb)
|
data/spec/support/suspenders.rb
CHANGED
|
@@ -17,6 +17,12 @@ module SuspendersTestHelpers
|
|
|
17
17
|
`
|
|
18
18
|
#{suspenders_bin} #{APP_NAME} #{arguments}
|
|
19
19
|
`
|
|
20
|
+
Dir.chdir(APP_NAME) do
|
|
21
|
+
with_env("HOME", tmp_path) do
|
|
22
|
+
`git add .`
|
|
23
|
+
`git commit -m 'Initial commit'`
|
|
24
|
+
end
|
|
25
|
+
end
|
|
20
26
|
end
|
|
21
27
|
end
|
|
22
28
|
end
|
|
@@ -45,7 +51,7 @@ module SuspendersTestHelpers
|
|
|
45
51
|
if File.exist?(project_path)
|
|
46
52
|
Dir.chdir(project_path) do
|
|
47
53
|
Bundler.with_clean_env do
|
|
48
|
-
`
|
|
54
|
+
`rails db:drop`
|
|
49
55
|
end
|
|
50
56
|
end
|
|
51
57
|
end
|
|
@@ -80,4 +86,14 @@ module SuspendersTestHelpers
|
|
|
80
86
|
def root_path
|
|
81
87
|
File.expand_path('../../../', __FILE__)
|
|
82
88
|
end
|
|
89
|
+
|
|
90
|
+
def with_env(name, new_value)
|
|
91
|
+
prior = ENV[name]
|
|
92
|
+
ENV[name] = new_value.to_s
|
|
93
|
+
|
|
94
|
+
yield
|
|
95
|
+
|
|
96
|
+
ensure
|
|
97
|
+
ENV[name] = prior
|
|
98
|
+
end
|
|
83
99
|
end
|
data/suspenders.gemspec
CHANGED
|
@@ -27,7 +27,7 @@ rush to build something amazing; don't use it if you like missing deadlines.
|
|
|
27
27
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
28
28
|
s.version = Suspenders::VERSION
|
|
29
29
|
|
|
30
|
-
s.add_dependency 'bitters', '~> 1.
|
|
30
|
+
s.add_dependency 'bitters', '~> 1.7'
|
|
31
31
|
s.add_dependency 'bundler', '~> 1.3'
|
|
32
32
|
s.add_dependency 'rails', Suspenders::RAILS_VERSION
|
|
33
33
|
|
data/templates/Gemfile.erb
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
source "https://rubygems.org"
|
|
2
2
|
|
|
3
|
+
git_source(:github) do |repo_name|
|
|
4
|
+
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
|
|
5
|
+
"https://github.com/#{repo_name}.git"
|
|
6
|
+
end
|
|
7
|
+
|
|
3
8
|
ruby "<%= Suspenders::RUBY_VERSION %>"
|
|
4
9
|
|
|
5
10
|
gem "autoprefixer-rails"
|
|
@@ -7,7 +12,6 @@ gem "delayed_job_active_record"
|
|
|
7
12
|
gem "flutie"
|
|
8
13
|
gem "honeybadger"
|
|
9
14
|
gem "jquery-rails"
|
|
10
|
-
gem "normalize-rails", "~> 3.0.0"
|
|
11
15
|
gem "pg"
|
|
12
16
|
gem "puma"
|
|
13
17
|
gem "rack-canonical-host"
|
|
@@ -20,9 +24,13 @@ gem "sprockets", ">= 3.0.0"
|
|
|
20
24
|
gem "suspenders"
|
|
21
25
|
gem "title"
|
|
22
26
|
gem "uglifier"
|
|
27
|
+
<% if options[:webpack] %>
|
|
28
|
+
gem "webpacker"
|
|
29
|
+
<% end %>
|
|
23
30
|
|
|
24
31
|
group :development do
|
|
25
32
|
gem "listen"
|
|
33
|
+
gem "rack-mini-profiler", require: false
|
|
26
34
|
gem "spring"
|
|
27
35
|
gem "spring-commands-rspec"
|
|
28
36
|
gem "web-console"
|
|
@@ -36,11 +44,7 @@ group :development, :test do
|
|
|
36
44
|
gem "factory_girl_rails"
|
|
37
45
|
gem "pry-byebug"
|
|
38
46
|
gem "pry-rails"
|
|
39
|
-
gem "rspec-rails", "~> 3.
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
group :development, :staging do
|
|
43
|
-
gem "rack-mini-profiler", require: false
|
|
47
|
+
gem "rspec-rails", "~> 3.6"
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
group :test do
|
|
@@ -54,6 +58,6 @@ group :test do
|
|
|
54
58
|
gem "webmock"
|
|
55
59
|
end
|
|
56
60
|
|
|
57
|
-
group :
|
|
61
|
+
group :production do
|
|
58
62
|
gem "rack-timeout"
|
|
59
63
|
end
|
data/templates/Procfile
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
web: bundle exec puma -p $PORT -C ./config/puma.rb
|
|
2
|
-
worker: bundle exec
|
|
2
|
+
worker: bundle exec rails jobs:work
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<% if ENV["SEGMENT_KEY"] %>
|
|
2
2
|
<script type="text/javascript">
|
|
3
|
-
window.analytics=window.analytics||[]
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="4.0.0";
|
|
4
|
+
analytics.load("<%= ENV["SEGMENT_KEY"] %>");
|
|
5
|
+
analytics.page();
|
|
6
|
+
}}();
|
|
6
7
|
</script>
|
|
7
8
|
<% end %>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require "active_job/logging"
|
|
2
|
+
|
|
3
|
+
ActiveSupport::Notifications.unsubscribe("enqueue.active_job")
|
|
4
|
+
|
|
5
|
+
module ActiveJob
|
|
6
|
+
module Logging
|
|
7
|
+
class EnqueueLogSubscriber < LogSubscriber
|
|
8
|
+
define_method :enqueue, instance_method(:enqueue)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
ActiveJob::Logging::EnqueueLogSubscriber.attach_to(:active_job)
|
data/templates/application.scss
CHANGED
data/templates/bin_deploy
CHANGED
data/templates/bin_setup
CHANGED
|
@@ -11,10 +11,14 @@ gem install bundler --conservative
|
|
|
11
11
|
bundle check || bundle install
|
|
12
12
|
|
|
13
13
|
# Set up database and add any development seed data
|
|
14
|
-
bin/
|
|
14
|
+
bin/rails dev:prime
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
if [ ! -d .git/safe ] && echo $PATH | grep .git/safe > /dev/null; then
|
|
17
|
+
echo "-----------------------------------------------------------------------"
|
|
18
|
+
echo
|
|
19
|
+
echo "-> When you trust this repo, remember to run: mkdir -p .git/safe"
|
|
20
|
+
echo
|
|
21
|
+
fi
|
|
18
22
|
|
|
19
23
|
# Only if this isn't CI
|
|
20
24
|
# if [ -z "$CI" ]; then
|
|
@@ -11,9 +11,12 @@ fi
|
|
|
11
11
|
|
|
12
12
|
PARENT_APP_NAME=<%= app_name.dasherize %>-staging
|
|
13
13
|
APP_NAME=<%= app_name.dasherize %>-staging-pr-$1
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
heroku pg:backups:capture --app $PARENT_APP_NAME
|
|
16
|
+
|
|
17
|
+
URL=`heroku pg:backups public-url --app $PARENT_APP_NAME`
|
|
15
18
|
|
|
16
19
|
heroku pg:backups restore $URL DATABASE_URL --confirm $APP_NAME --app $APP_NAME
|
|
17
|
-
heroku run
|
|
20
|
+
heroku run rails db:migrate --exit-code --app $APP_NAME
|
|
18
21
|
heroku ps:scale worker=1 --app $APP_NAME
|
|
19
22
|
heroku restart --app $APP_NAME
|
|
@@ -1,12 +1,4 @@
|
|
|
1
1
|
if Rails.env.development? || Rails.env.test?
|
|
2
|
-
require "bundler/audit/
|
|
3
|
-
|
|
4
|
-
namespace :bundler do
|
|
5
|
-
desc "Updates the ruby-advisory-db and runs audit"
|
|
6
|
-
task :audit do
|
|
7
|
-
%w(update check).each do |command|
|
|
8
|
-
Bundler::Audit::CLI.start [command]
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
2
|
+
require "bundler/audit/task"
|
|
3
|
+
Bundler::Audit::Task.new
|
|
12
4
|
end
|
data/templates/secrets.yml
CHANGED
data/templates/spec_helper.rb
CHANGED
|
@@ -10,6 +10,7 @@ if ENV.fetch("COVERAGE", false)
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
require "webmock/rspec"
|
|
13
|
+
require "timecop"
|
|
13
14
|
|
|
14
15
|
# http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
|
15
16
|
RSpec.configure do |config|
|
|
@@ -27,3 +28,6 @@ RSpec.configure do |config|
|
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
WebMock.disable_net_connect!(allow_localhost: true)
|
|
31
|
+
|
|
32
|
+
# Only allow Timecop with block syntax
|
|
33
|
+
Timecop.safe_mode = true
|
|
@@ -2,12 +2,17 @@
|
|
|
2
2
|
*.DS_Store
|
|
3
3
|
*.swo
|
|
4
4
|
*.swp
|
|
5
|
+
.byebug_history
|
|
5
6
|
/.bundle
|
|
6
7
|
/.env.local
|
|
7
8
|
/coverage/*
|
|
8
9
|
/db/*.sqlite3
|
|
10
|
+
/db/*.sqlite3-journal
|
|
9
11
|
/log/*
|
|
10
|
-
/
|
|
12
|
+
/node_modules
|
|
11
13
|
/public/assets
|
|
14
|
+
/public/packs
|
|
15
|
+
/public/system
|
|
12
16
|
/tags
|
|
13
17
|
/tmp/*
|
|
18
|
+
/yarn-error.log
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: suspenders
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.45.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoughtbot
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-
|
|
11
|
+
date: 2017-09-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bitters
|
|
@@ -16,14 +16,14 @@ dependencies:
|
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.
|
|
19
|
+
version: '1.7'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.
|
|
26
|
+
version: '1.7'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -44,14 +44,14 @@ dependencies:
|
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: 5.
|
|
47
|
+
version: 5.1.3
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: 5.
|
|
54
|
+
version: 5.1.3
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -98,6 +98,8 @@ files:
|
|
|
98
98
|
- lib/suspenders/adapters/heroku.rb
|
|
99
99
|
- lib/suspenders/app_builder.rb
|
|
100
100
|
- lib/suspenders/generators/app_generator.rb
|
|
101
|
+
- lib/suspenders/generators/enforce_ssl_generator.rb
|
|
102
|
+
- lib/suspenders/generators/initialize_active_job_generator.rb
|
|
101
103
|
- lib/suspenders/generators/static_generator.rb
|
|
102
104
|
- lib/suspenders/generators/stylesheet_base_generator.rb
|
|
103
105
|
- lib/suspenders/version.rb
|
|
@@ -121,6 +123,7 @@ files:
|
|
|
121
123
|
- templates/_flashes.html.erb
|
|
122
124
|
- templates/_javascript.html.erb
|
|
123
125
|
- templates/action_mailer.rb
|
|
126
|
+
- templates/active_job.rb
|
|
124
127
|
- templates/app.json.erb
|
|
125
128
|
- templates/application.scss
|
|
126
129
|
- templates/bin_deploy
|
|
@@ -165,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
165
168
|
requirements:
|
|
166
169
|
- - ">="
|
|
167
170
|
- !ruby/object:Gem::Version
|
|
168
|
-
version: 2.4.
|
|
171
|
+
version: 2.4.1
|
|
169
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
173
|
requirements:
|
|
171
174
|
- - ">="
|
|
@@ -173,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
173
176
|
version: '0'
|
|
174
177
|
requirements: []
|
|
175
178
|
rubyforge_project:
|
|
176
|
-
rubygems_version: 2.6.
|
|
179
|
+
rubygems_version: 2.6.13
|
|
177
180
|
signing_key:
|
|
178
181
|
specification_version: 4
|
|
179
182
|
summary: Generate a Rails app using thoughtbot's best practices.
|