philosophies-suspenders 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +11 -0
  5. data/Gemfile +3 -0
  6. data/Gemfile.lock +123 -0
  7. data/LICENSE +21 -0
  8. data/NEWS.md +399 -0
  9. data/README.md +194 -0
  10. data/Rakefile +8 -0
  11. data/bin/philosophies-suspenders +18 -0
  12. data/bin/rake +16 -0
  13. data/bin/rspec +16 -0
  14. data/lib/suspenders/actions.rb +33 -0
  15. data/lib/suspenders/app_builder.rb +512 -0
  16. data/lib/suspenders/generators/app_generator.rb +249 -0
  17. data/lib/suspenders/version.rb +5 -0
  18. data/lib/suspenders.rb +4 -0
  19. data/spec/fakes/bin/heroku +5 -0
  20. data/spec/fakes/bin/hub +5 -0
  21. data/spec/features/github_spec.rb +10 -0
  22. data/spec/features/heroku_spec.rb +20 -0
  23. data/spec/features/new_project_spec.rb +157 -0
  24. data/spec/spec_helper.rb +23 -0
  25. data/spec/support/fake_github.rb +21 -0
  26. data/spec/support/fake_heroku.rb +43 -0
  27. data/spec/support/suspenders.rb +49 -0
  28. data/suspenders.gemspec +34 -0
  29. data/templates/.rubocop.yml +25 -0
  30. data/templates/Gemfile.erb +58 -0
  31. data/templates/Procfile +2 -0
  32. data/templates/README.md.erb +39 -0
  33. data/templates/_analytics.html.erb +7 -0
  34. data/templates/_flashes.html.erb +7 -0
  35. data/templates/_javascript.html.erb +12 -0
  36. data/templates/action_mailer.rb +5 -0
  37. data/templates/airbrake.rb +5 -0
  38. data/templates/application.js +4 -0
  39. data/templates/application.scss +1 -0
  40. data/templates/bundler_audit.rake +12 -0
  41. data/templates/config_i18n_tasks.yml +13 -0
  42. data/templates/config_locales_en.yml.erb +19 -0
  43. data/templates/database_cleaner_rspec.rb +21 -0
  44. data/templates/disable_xml_params.rb +3 -0
  45. data/templates/errors.rb +34 -0
  46. data/templates/factory_girl_rspec.rb +3 -0
  47. data/templates/flashes_helper.rb +5 -0
  48. data/templates/i18n.rb +3 -0
  49. data/templates/json_encoding.rb +1 -0
  50. data/templates/newrelic.yml.erb +34 -0
  51. data/templates/postgresql_database.yml.erb +26 -0
  52. data/templates/rails_helper.rb +17 -0
  53. data/templates/secrets.yml +14 -0
  54. data/templates/setup.rb +5 -0
  55. data/templates/smtp.rb +17 -0
  56. data/templates/spec_helper.rb +13 -0
  57. data/templates/staging.rb +1 -0
  58. data/templates/suspenders_gitignore +34 -0
  59. data/templates/suspenders_layout.html.erb.erb +21 -0
  60. data/templates/unicorn.rb +30 -0
  61. metadata +160 -0
data/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # Suspenders
2
+
3
+ This is Philosophie's fork of Suspenders, a Rails application template
4
+ originally created by thoughtbot. This repo has strayed significantly from
5
+ thoughtbot's and is not intended to go back upstream.
6
+
7
+ ## Installation
8
+
9
+ First install the gem:
10
+
11
+ gem install philosophies-suspenders
12
+
13
+ Then run:
14
+
15
+ philosophies-suspenders projectname
16
+
17
+ This will create a Rails app in `projectname` using the latest version of Rails.
18
+
19
+ ## Gemfile
20
+
21
+ To see the latest and greatest gems, look at Suspenders'
22
+ [Gemfile](templates/Gemfile.erb), which will be appended to the default
23
+ generated projectname/Gemfile. After the first bundle install, Suspenders will
24
+ apply pessimistic version-locking on the Gemfile to only allow patch-level
25
+ updates.
26
+
27
+ It includes application gems like:
28
+
29
+ * [Airbrake](https://github.com/airbrake/airbrake) for exception notification,
30
+ set your API key in the environment with `AIRBRAKE_API_KEY`
31
+ * [Autoprefixer Rails](https://github.com/ai/autoprefixer-rails) for CSS vendor prefixes
32
+ * [Sidekiq](https://github.com/mperham/sidekiq) for background processing
33
+ * [Flutie](https://github.com/thoughtbot/flutie) for `page_title` and `body_class` view
34
+ helpers
35
+ * [High Voltage](https://github.com/thoughtbot/high_voltage) for static pages
36
+ * [Rails Assets](https://rails-assets.org/) for managing frontend dependencies,
37
+ including by default:
38
+ * jquery
39
+ * jquery-ujs
40
+ * [New Relic RPM](https://github.com/newrelic/rpm) for monitoring performance
41
+ * [Postgres](https://github.com/ged/ruby-pg) for access to the Postgres database
42
+ * [Rack Canonical Host](https://github.com/tylerhunt/rack-canonical-host) to
43
+ ensure all requests are served from the same domain
44
+ * [Rack Timeout](https://github.com/kch/rack-timeout) to abort requests that are
45
+ taking too long
46
+ * [Simple Form](https://github.com/plataformatec/simple_form) for form markup
47
+ and style
48
+ * [Title](https://github.com/calebthompson/title) for storing titles in
49
+ translations
50
+ * [Unicorn](https://github.com/defunkt/unicorn) to serve HTTP requests
51
+
52
+ And development gems like:
53
+
54
+ * [Dotenv](https://github.com/bkeepers/dotenv) for loading environment variables
55
+ * [Pry Rails](https://github.com/rweng/pry-rails) for interactively exploring
56
+ objects
57
+ * [Pry ByeBug](https://github.com/deivid-rodriguez/pry-byebug) for interactively
58
+ debugging behavior
59
+ * [Bundler Audit](https://github.com/rubysec/bundler-audit) for scanning the
60
+ Gemfile for insecure dependencies based on published CVEs
61
+ * [Spring](https://github.com/rails/spring) for fast Rails actions via
62
+ pre-loading
63
+ * [Better Errors](https://github.com/charliesome/better_errors) for better
64
+ debugging via in-browser IRB consoles.
65
+ * [RuboCop](https://github.com/bbatsov/rubocop) with Philosophie's default
66
+ configuration to enforce Ruby Community Styleguide.
67
+
68
+ And testing gems like:
69
+
70
+ * [Capybara](https://github.com/jnicklas/capybara) and
71
+ [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
72
+ integration testing
73
+ * [Factory Girl](https://github.com/thoughtbot/factory_girl) for test data
74
+ * [RSpec](https://github.com/rspec/rspec) for unit testing
75
+ * [RSpec Mocks](https://github.com/rspec/rspec-mocks) for stubbing and spying
76
+ * [Shoulda Matchers](https://github.com/thoughtbot/shoulda-matchers) for common
77
+ RSpec matchers
78
+ * [Timecop](https://github.com/jtrupiano/timecop-console) for testing time
79
+
80
+ ## Other goodies
81
+
82
+ Suspenders also comes with:
83
+
84
+ * [Stairs][stairs] for new developer setup
85
+ * Rails' flashes set up and in application layout
86
+ * A few nice time formats set up for localization
87
+ * `Rack::Deflater` to [compress responses with Gzip][compress]
88
+ * A [low database connection pool limit][pool]
89
+ * [Safe binstubs][binstub]
90
+ * [t() and l() in specs without prefixing with I18n][i18n]
91
+ * An automatically-created `SECRET_KEY_BASE` environment variable in all
92
+ environments
93
+ * The analytics adapter [Segment][segment] (and therefore config for Google
94
+ Analytics, Intercom, Facebook Ads, Twitter Ads, etc.)
95
+
96
+ [stairs]: https://github.com/philosophie/stairs
97
+ [compress]: http://robots.thoughtbot.com/content-compression-with-rack-deflater/
98
+ [pool]: https://devcenter.heroku.com/articles/concurrency-and-database-connections
99
+ [binstub]: https://github.com/thoughtbot/suspenders/pull/282
100
+ [i18n]: https://github.com/thoughtbot/suspenders/pull/304
101
+ [segment]: https://segment.com
102
+
103
+ ## Heroku
104
+
105
+ By default, suspenders will:
106
+
107
+ * Creates a staging and production Heroku app
108
+ * Sets them as `staging` and `production` Git remotes
109
+ * Configures staging with `RACK_ENV` and `RAILS_ENV` environment variables set
110
+ to `staging`
111
+ * Adds the [Rails 12factor][rails-12factor] gem
112
+ * Adds free Mandrill add-on and configure SMTP settings to use it
113
+ * Adds free Airbrake add-on
114
+ * Adds free Papertrail add-on
115
+
116
+ [rails-12factor]: https://github.com/heroku/rails_12factor
117
+
118
+ You can optionally specify alternate Heroku flags:
119
+
120
+ suspenders app \
121
+ --heroku-flags "--region eu --addons newrelic,pgbackups,ssl"
122
+
123
+ See all possible Heroku flags:
124
+
125
+ heroku help create
126
+
127
+ You can bypass all Heroku functionality with the `--skip-heroku` option:
128
+
129
+ suspenders app --skip-heroku true
130
+
131
+ ## Git
132
+
133
+ By default, suspenders will:
134
+
135
+ * Initialize a new git repository
136
+ * Create `staging` and `production` branches for deployment
137
+ * Make an initial commit
138
+
139
+ You can optionally provide a remote URL via the `--origin` option and suspenders
140
+ will push all branches to that remote.
141
+
142
+ suspenders app --origin git@github.com:philosopie/app.git
143
+
144
+ You can bypass all git functionality with the `--skip-git` option:
145
+
146
+ suspenders app --skip-git true
147
+
148
+ ## GitHub
149
+
150
+ You can optionally create a GitHub repository for the suspended Rails app. It
151
+ requires that you have [Hub](https://github.com/github/hub) on your system:
152
+
153
+ curl http://hub.github.com/standalone -sLo ~/bin/hub && chmod +x ~/bin/hub
154
+ suspenders app --github organization/project
155
+
156
+ This has the same effect as running:
157
+
158
+ hub create organization/project
159
+
160
+ ## Spring
161
+
162
+ Suspenders uses [spring](https://github.com/rails/spring) by default.
163
+ It makes Rails applications load faster, but it might introduce confusing issues
164
+ around stale code not being refreshed.
165
+ If you think your application is running old code, run `spring stop`.
166
+ And if you'd rather not use spring, add `DISABLE_SPRING=1` to your login file.
167
+
168
+ ## Dependencies
169
+
170
+ Suspenders requires the latest version of Ruby.
171
+
172
+ Some gems included in Suspenders have native extensions. You should have GCC
173
+ installed on your machine before generating an app with Suspenders.
174
+
175
+ Use [OS X GCC Installer](https://github.com/kennethreitz/osx-gcc-installer/) for
176
+ Snow Leopard (OS X 10.6).
177
+
178
+ Use [Command Line Tools for XCode](https://developer.apple.com/downloads/index.action)
179
+ for Lion (OS X 10.7) or Mountain Lion (OS X 10.8).
180
+
181
+ We use [Capybara Webkit](https://github.com/thoughtbot/capybara-webkit) for
182
+ full-stack JavaScript integration testing. It requires QT. Instructions for
183
+ installing QT are
184
+ [here](https://github.com/thoughtbot/capybara-webkit/wiki/Installing-Qt-and-compiling-capybara-webkit).
185
+
186
+ PostgreSQL needs to be installed and running for the `db:create` rake task.
187
+
188
+ ## License
189
+
190
+ Suspenders is Copyright © 2008-2015 thoughtbot.
191
+ It is free software,
192
+ and may be redistributed under the terms specified in the [LICENSE] file.
193
+
194
+ [LICENSE]: LICENSE
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:rspec)
6
+
7
+ desc 'Run the test suite'
8
+ task :default => :rspec
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+
4
+ source_path = (Pathname.new(__FILE__).dirname + '../lib').expand_path
5
+ $LOAD_PATH << source_path
6
+
7
+ require 'suspenders'
8
+
9
+ if ['create', '--create'].include? ARGV[0]
10
+ ARGV.shift
11
+ puts "[WARNING] the suspenders create argument is deprecated. Just use `suspenders #{ARGV.join}` instead"
12
+ end
13
+
14
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
15
+ Suspenders::AppGenerator.source_root templates_root
16
+ Suspenders::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
17
+
18
+ Suspenders::AppGenerator.start
data/bin/rake ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
data/bin/rspec ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -0,0 +1,33 @@
1
+ module Suspenders
2
+ module Actions
3
+ def replace_in_file(relative_path, find, replace)
4
+ path = File.join(destination_root, relative_path)
5
+ contents = IO.read(path)
6
+ unless contents.gsub!(find, replace)
7
+ raise "#{find.inspect} not found in #{relative_path}"
8
+ end
9
+ File.open(path, "w") { |file| file.write(contents) }
10
+ end
11
+
12
+ def action_mailer_host(rails_env, host)
13
+ config = "config.action_mailer.default_url_options = { host: #{host} }"
14
+ configure_environment(rails_env, config)
15
+ end
16
+
17
+ def configure_application_file(config)
18
+ inject_into_file(
19
+ "config/application.rb",
20
+ "\n\n #{config}",
21
+ before: "\n end"
22
+ )
23
+ end
24
+
25
+ def configure_environment(rails_env, config)
26
+ inject_into_file(
27
+ "config/environments/#{rails_env}.rb",
28
+ "\n\n #{config}",
29
+ before: "\nend"
30
+ )
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,512 @@
1
+ module Suspenders
2
+ class AppBuilder < Rails::AppBuilder
3
+ include Suspenders::Actions
4
+
5
+ def readme
6
+ template 'README.md.erb', 'README.md'
7
+ end
8
+
9
+ def raise_on_delivery_errors
10
+ replace_in_file 'config/environments/development.rb',
11
+ 'raise_delivery_errors = false', 'raise_delivery_errors = true'
12
+ end
13
+
14
+ def set_test_delivery_method
15
+ inject_into_file(
16
+ "config/environments/development.rb",
17
+ "\n config.action_mailer.delivery_method = :test",
18
+ after: "config.action_mailer.raise_delivery_errors = true",
19
+ )
20
+ end
21
+
22
+ def raise_on_unpermitted_parameters
23
+ config = <<-RUBY
24
+ config.action_controller.action_on_unpermitted_parameters = :raise
25
+ RUBY
26
+
27
+ inject_into_class "config/application.rb", "Application", config
28
+ end
29
+
30
+ def provide_setup_script
31
+ template "setup.rb", "setup.rb"
32
+ end
33
+
34
+ def configure_generators
35
+ config = <<-RUBY
36
+
37
+ config.generators do |generate|
38
+ generate.helper false
39
+ generate.javascript_engine false
40
+ generate.request_specs false
41
+ generate.routing_specs false
42
+ generate.stylesheets false
43
+ generate.test_framework :rspec
44
+ generate.view_specs false
45
+ end
46
+
47
+ RUBY
48
+
49
+ inject_into_class 'config/application.rb', 'Application', config
50
+ end
51
+
52
+ def set_up_factory_girl_for_rspec
53
+ copy_file 'factory_girl_rspec.rb', 'spec/support/factory_girl.rb'
54
+ end
55
+
56
+ def configure_newrelic
57
+ template 'newrelic.yml.erb', 'config/newrelic.yml'
58
+ end
59
+
60
+ def configure_smtp
61
+ copy_file 'smtp.rb', 'config/smtp.rb'
62
+
63
+ prepend_file 'config/environments/production.rb',
64
+ %{require Rails.root.join("config/smtp")\n}
65
+
66
+ config = <<-RUBY
67
+
68
+ config.action_mailer.delivery_method = :smtp
69
+ config.action_mailer.smtp_settings = SMTP_SETTINGS
70
+ RUBY
71
+
72
+ inject_into_file 'config/environments/production.rb', config,
73
+ :after => 'config.action_mailer.raise_delivery_errors = false'
74
+ end
75
+
76
+ def enable_rack_canonical_host
77
+ config = <<-RUBY
78
+
79
+ # Ensure requests are only served from one, canonical host name
80
+ config.middleware.use Rack::CanonicalHost, ENV.fetch("HOST")
81
+ RUBY
82
+
83
+ inject_into_file(
84
+ "config/environments/production.rb",
85
+ config,
86
+ after: serve_static_files_line
87
+ )
88
+ end
89
+
90
+ def enable_rack_deflater
91
+ config = <<-RUBY
92
+
93
+ # Enable deflate / gzip compression of controller-generated responses
94
+ config.middleware.use Rack::Deflater
95
+ RUBY
96
+
97
+ inject_into_file(
98
+ "config/environments/production.rb",
99
+ config,
100
+ after: serve_static_files_line
101
+ )
102
+ end
103
+
104
+ def setup_asset_host
105
+ replace_in_file 'config/environments/production.rb',
106
+ "# config.action_controller.asset_host = 'http://assets.example.com'",
107
+ 'config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("HOST"))'
108
+
109
+ replace_in_file 'config/initializers/assets.rb',
110
+ "config.assets.version = '1.0'",
111
+ 'config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")'
112
+
113
+ inject_into_file(
114
+ "config/environments/production.rb",
115
+ ' config.static_cache_control = "public, max-age=#{1.year.to_i}"',
116
+ after: serve_static_files_line
117
+ )
118
+ end
119
+
120
+ def setup_staging_environment
121
+ staging_file = 'config/environments/staging.rb'
122
+ copy_file 'staging.rb', staging_file
123
+
124
+ config = <<-RUBY
125
+
126
+ Rails.application.configure do
127
+ # ...
128
+ end
129
+ RUBY
130
+
131
+ append_file staging_file, config
132
+ end
133
+
134
+ def setup_secret_token
135
+ template 'secrets.yml', 'config/secrets.yml', force: true
136
+ end
137
+
138
+ def disallow_wrapping_parameters
139
+ remove_file "config/initializers/wrap_parameters.rb"
140
+ end
141
+
142
+ def create_partials_directory
143
+ empty_directory 'app/views/application'
144
+ end
145
+
146
+ def create_shared_flashes
147
+ copy_file "_flashes.html.erb", "app/views/application/_flashes.html.erb"
148
+ copy_file "flashes_helper.rb", "app/helpers/flashes_helper.rb"
149
+ end
150
+
151
+ def create_shared_javascripts
152
+ copy_file '_javascript.html.erb', 'app/views/application/_javascript.html.erb'
153
+ end
154
+
155
+ def create_application_layout
156
+ template 'suspenders_layout.html.erb.erb',
157
+ 'app/views/layouts/application.html.erb',
158
+ force: true
159
+ end
160
+
161
+ def use_postgres_config_template
162
+ template 'postgresql_database.yml.erb', 'config/database.yml',
163
+ force: true
164
+ end
165
+
166
+ def create_database
167
+ bundle_command 'exec rake db:create db:migrate'
168
+ end
169
+
170
+ def replace_gemfile
171
+ remove_file 'Gemfile'
172
+ template 'Gemfile.erb', 'Gemfile'
173
+ end
174
+
175
+ def version_gems_in_gemfile
176
+ gemfile = File.read('Gemfile')
177
+
178
+ require 'bundler'
179
+ locks = Bundler.locked_gems
180
+ specs = locks.specs
181
+
182
+ # Naively convert to single quotes
183
+ gemfile.gsub! '"', "'"
184
+
185
+ specs.each do |gem|
186
+ name, version = gem.name, gem.version
187
+
188
+ # Don't try to set version if:
189
+ # * source is git or github
190
+ # * version is already set
191
+ gemfile.gsub! /^(?!.*, (git:|github:|'))( *gem '#{name}')/, "\\2, '~> #{version}'"
192
+ end
193
+
194
+ File.open 'Gemfile', 'w+' do |file|
195
+ file.puts gemfile
196
+ end
197
+ end
198
+
199
+ def set_ruby_to_version_being_used
200
+ create_file '.ruby-version', "#{Suspenders::RUBY_VERSION}\n"
201
+ end
202
+
203
+ def setup_heroku_specific_gems
204
+ inject_into_file(
205
+ "Gemfile",
206
+ %{\n\s\sgem "rails_12factor"},
207
+ after: /group :staging, :production do/
208
+ )
209
+ end
210
+
211
+ def enable_database_cleaner
212
+ copy_file 'database_cleaner_rspec.rb', 'spec/support/database_cleaner.rb'
213
+ end
214
+
215
+ def configure_spec_support_features
216
+ empty_directory_with_keep_file 'spec/features'
217
+ empty_directory_with_keep_file 'spec/support/features'
218
+ end
219
+
220
+ def configure_rspec
221
+ remove_file "spec/rails_helper.rb"
222
+ remove_file "spec/spec_helper.rb"
223
+ copy_file "rails_helper.rb", "spec/rails_helper.rb"
224
+ copy_file "spec_helper.rb", "spec/spec_helper.rb"
225
+ end
226
+
227
+ def configure_i18n_for_test_environment
228
+ copy_file "i18n.rb", "spec/support/i18n.rb"
229
+ end
230
+
231
+ def configure_i18n_for_missing_translations
232
+ raise_on_missing_translations_in("development")
233
+ raise_on_missing_translations_in("test")
234
+ end
235
+
236
+ def configure_i18n_tasks
237
+ run "cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/"
238
+ copy_file "config_i18n_tasks.yml", "config/i18n-tasks.yml"
239
+ end
240
+
241
+ def configure_action_mailer_in_specs
242
+ copy_file 'action_mailer.rb', 'spec/support/action_mailer.rb'
243
+ end
244
+
245
+ def configure_time_formats
246
+ remove_file "config/locales/en.yml"
247
+ template "config_locales_en.yml.erb", "config/locales/en.yml"
248
+ end
249
+
250
+ def configure_rack_timeout
251
+ rack_timeout_config = <<-RUBY
252
+ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
253
+ RUBY
254
+
255
+ append_file "config/environments/production.rb", rack_timeout_config
256
+ end
257
+
258
+ def configure_simple_form
259
+ bundle_command "exec rails generate simple_form:install"
260
+ end
261
+
262
+ def configure_action_mailer
263
+ action_mailer_host "development", %{"localhost:#{port}"}
264
+ action_mailer_host "test", %{"www.example.com"}
265
+ action_mailer_host "staging", %{ENV.fetch("HOST")}
266
+ action_mailer_host "production", %{ENV.fetch("HOST")}
267
+ end
268
+
269
+ def configure_active_job
270
+ configure_application_file(
271
+ "config.active_job.queue_adapter = :sidekiq"
272
+ )
273
+ configure_environment "test", "config.active_job.queue_adapter = :inline"
274
+ end
275
+
276
+ def fix_i18n_deprecation_warning
277
+ config = <<-RUBY
278
+ config.i18n.enforce_available_locales = true
279
+ RUBY
280
+
281
+ inject_into_class 'config/application.rb', 'Application', config
282
+ end
283
+
284
+ def generate_rspec
285
+ generate 'rspec:install'
286
+ end
287
+
288
+ def configure_unicorn
289
+ copy_file 'unicorn.rb', 'config/unicorn.rb'
290
+ end
291
+
292
+ def setup_foreman
293
+ copy_file 'Procfile', 'Procfile'
294
+ end
295
+
296
+ def setup_stylesheets
297
+ remove_file "app/assets/stylesheets/application.css"
298
+ copy_file "application.scss",
299
+ "app/assets/stylesheets/application.scss"
300
+ end
301
+
302
+ def setup_javascripts
303
+ remove_file "app/assets/javascripts/application.js"
304
+ copy_file "application.js", "app/assets/javascripts/application.js"
305
+ create_empty_directory('app/assets/javascripts/application')
306
+ end
307
+
308
+ def gitignore_files
309
+ remove_file '.gitignore'
310
+ copy_file 'suspenders_gitignore', '.gitignore'
311
+ [
312
+ 'app/views/pages',
313
+ 'app/workers',
314
+ 'spec/lib',
315
+ 'spec/controllers',
316
+ 'spec/helpers',
317
+ 'spec/support/matchers',
318
+ 'spec/support/mixins',
319
+ 'spec/support/shared_examples'
320
+ ].each do |dir|
321
+ create_empty_directory(dir)
322
+ end
323
+ end
324
+
325
+ def init_git
326
+ run 'git init'
327
+ end
328
+
329
+ def setup_deployment_environment_branches
330
+ run 'git branch staging'
331
+ run 'git branch production'
332
+ end
333
+
334
+ def create_initial_commit
335
+ run 'git add -A'
336
+ run 'git commit -m "Initial app setup."'
337
+ end
338
+
339
+ def setup_and_push_to_origin_remote(remote_url)
340
+ run "git remote add origin #{remote_url}"
341
+ run 'git push --all origin'
342
+ end
343
+
344
+ def create_staging_heroku_app(flags)
345
+ rack_env = "RACK_ENV=staging RAILS_ENV=staging"
346
+ app_name = heroku_app_name_for("staging")
347
+
348
+ run_heroku "create #{app_name} --ssh-git #{flags}", "staging"
349
+ run_heroku "config:add #{rack_env}", "staging"
350
+ configure_heroku_app("staging")
351
+ end
352
+
353
+ def create_production_heroku_app(flags)
354
+ app_name = heroku_app_name_for("production")
355
+
356
+ run_heroku "create #{app_name} --ssh-git #{flags}", "production"
357
+ configure_heroku_app("production")
358
+ end
359
+
360
+ def create_heroku_apps(flags)
361
+ create_staging_heroku_app(flags)
362
+ create_production_heroku_app(flags)
363
+ end
364
+
365
+ def configure_heroku_app(environment)
366
+ run_heroku "addons:create mandrill", environment
367
+ run_heroku "addons:create airbrake:free_heroku", environment
368
+ run_heroku "addons:create papertrail", environment
369
+
370
+ domain = "#{heroku_app_name_for(environment)}.herokuapp.com"
371
+
372
+ env_vars = [
373
+ 'SMTP_DOMAIN=heroku.com',
374
+ 'SMTP_ADDRESS=smtp.mandrillapp.com',
375
+ 'SMTP_PROVIDER=mandrill',
376
+ "HOST=#{domain}",
377
+ "ASSET_HOST=#{domain}"
378
+ ]
379
+
380
+ run_heroku "config:add #{env_vars.join(' ')}", environment
381
+ end
382
+
383
+ def set_heroku_rails_secrets
384
+ %w(staging production).each do |environment|
385
+ run_heroku "config:add SECRET_KEY_BASE=#{generate_secret}", environment
386
+ end
387
+ end
388
+
389
+ def set_heroku_serve_static_files
390
+ %w(staging production).each do |environment|
391
+ run_heroku "config:add RAILS_SERVE_STATIC_FILES=true", environment
392
+ end
393
+ end
394
+
395
+ def create_github_repo(repo_name)
396
+ path_addition = override_path_for_tests
397
+ run "#{path_addition} hub create #{repo_name} -p"
398
+ end
399
+
400
+ def setup_segment
401
+ copy_file '_analytics.html.erb',
402
+ 'app/views/application/_analytics.html.erb'
403
+ end
404
+
405
+ def setup_bundler_audit
406
+ copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake"
407
+ end
408
+
409
+ def setup_spring
410
+ bundle_command "exec spring binstub --all"
411
+ end
412
+
413
+ def copy_miscellaneous_files
414
+ copy_file "errors.rb", "config/initializers/errors.rb"
415
+ copy_file "json_encoding.rb", "config/initializers/json_encoding.rb"
416
+ end
417
+
418
+ def customize_error_pages
419
+ meta_tags =<<-EOS
420
+ <meta charset="utf-8" />
421
+ <meta name="ROBOTS" content="NOODP" />
422
+ <meta name="viewport" content="initial-scale=1" />
423
+ EOS
424
+
425
+ %w(500 404 422).each do |page|
426
+ inject_into_file "public/#{page}.html", meta_tags, :after => "<head>\n"
427
+ replace_in_file "public/#{page}.html", /<!--.+-->\n/, ''
428
+ end
429
+ end
430
+
431
+ def remove_routes_comment_lines
432
+ replace_in_file 'config/routes.rb',
433
+ /Rails\.application\.routes\.draw do.*end/m,
434
+ "Rails.application.routes.draw do\nend"
435
+ end
436
+
437
+ def disable_xml_params
438
+ copy_file 'disable_xml_params.rb', 'config/initializers/disable_xml_params.rb'
439
+ end
440
+
441
+ def setup_default_rake_task
442
+ append_file 'Rakefile' do
443
+ <<-EOS
444
+ task(:default).clear
445
+
446
+ if defined?(RSpec) && defined?(RuboCop)
447
+ require 'rubocop/rake_task'
448
+ require 'rspec/core/rake_task'
449
+
450
+ RuboCop::RakeTask.new
451
+
452
+ task default: [:spec, :rubocop]
453
+ end
454
+ EOS
455
+ end
456
+ end
457
+
458
+ def configure_rubocop
459
+ template '.rubocop.yml', '.rubocop.yml'
460
+ end
461
+
462
+ def configure_airbrake
463
+ template 'airbrake.rb', 'config/initializers/airbrake.rb'
464
+ end
465
+
466
+ def run_stairs
467
+ bundle_command 'install'
468
+ bundle_command 'exec stairs --use-defaults'
469
+ end
470
+
471
+ private
472
+
473
+ def raise_on_missing_translations_in(environment)
474
+ config = 'config.action_view.raise_on_missing_translations = true'
475
+
476
+ uncomment_lines("config/environments/#{environment}.rb", config)
477
+ end
478
+
479
+ def override_path_for_tests
480
+ if ENV['TESTING']
481
+ support_bin = File.expand_path(File.join('..', '..', 'spec', 'fakes', 'bin'))
482
+ "PATH=#{support_bin}:$PATH"
483
+ end
484
+ end
485
+
486
+ def run_heroku(command, environment)
487
+ path_addition = override_path_for_tests
488
+ run "#{path_addition} heroku #{command} --remote #{environment}"
489
+ end
490
+
491
+ def generate_secret
492
+ SecureRandom.hex(64)
493
+ end
494
+
495
+ def port
496
+ @port ||= [3000, 4000, 5000, 7000, 8000, 9000].sample
497
+ end
498
+
499
+ def serve_static_files_line
500
+ "config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?\n"
501
+ end
502
+
503
+ def heroku_app_name_for(environment)
504
+ "#{app_name.dasherize}-#{environment}"
505
+ end
506
+
507
+ def create_empty_directory(name)
508
+ run "mkdir #{name}"
509
+ run "touch #{name}/.keep"
510
+ end
511
+ end
512
+ end