slining 1.0.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.
Files changed (66) 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/CONTRIBUTING.md +48 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +120 -0
  8. data/LICENSE +40 -0
  9. data/NEWS.md +2 -0
  10. data/README.md +207 -0
  11. data/Rakefile +8 -0
  12. data/bin/rake +16 -0
  13. data/bin/rspec +16 -0
  14. data/bin/setup +13 -0
  15. data/bin/slining +18 -0
  16. data/lib/slining.rb +4 -0
  17. data/lib/slining/actions.rb +33 -0
  18. data/lib/slining/app_builder.rb +499 -0
  19. data/lib/slining/generators/app_generator.rb +238 -0
  20. data/lib/slining/version.rb +5 -0
  21. data/slining.gemspec +34 -0
  22. data/spec/fakes/bin/heroku +5 -0
  23. data/spec/fakes/bin/hub +5 -0
  24. data/spec/features/github_spec.rb +15 -0
  25. data/spec/features/heroku_spec.rb +46 -0
  26. data/spec/features/new_project_spec.rb +135 -0
  27. data/spec/spec_helper.rb +20 -0
  28. data/spec/support/fake_github.rb +21 -0
  29. data/spec/support/fake_heroku.rb +43 -0
  30. data/spec/support/slining.rb +49 -0
  31. data/templates/Gemfile.erb +58 -0
  32. data/templates/Procfile +2 -0
  33. data/templates/README.md.erb +32 -0
  34. data/templates/_analytics.html.erb +7 -0
  35. data/templates/_flashes.html.erb +7 -0
  36. data/templates/_javascript.html.erb +12 -0
  37. data/templates/action_mailer.rb +5 -0
  38. data/templates/application.scss +8 -0
  39. data/templates/bin_deploy +12 -0
  40. data/templates/bin_setup.erb +36 -0
  41. data/templates/browserslist +4 -0
  42. data/templates/bundler_audit.rake +12 -0
  43. data/templates/config_i18n_tasks.yml +13 -0
  44. data/templates/config_locales_en.yml.erb +19 -0
  45. data/templates/database_cleaner_rspec.rb +21 -0
  46. data/templates/development_seeds.rb +12 -0
  47. data/templates/disable_xml_params.rb +3 -0
  48. data/templates/errors.rb +34 -0
  49. data/templates/factory_girl_rspec.rb +3 -0
  50. data/templates/flashes_helper.rb +5 -0
  51. data/templates/hound.yml +17 -0
  52. data/templates/i18n.rb +3 -0
  53. data/templates/json_encoding.rb +1 -0
  54. data/templates/newrelic.yml.erb +34 -0
  55. data/templates/postgresql_database.yml.erb +12 -0
  56. data/templates/rails_helper.rb +23 -0
  57. data/templates/sample.env +6 -0
  58. data/templates/secrets.yml +14 -0
  59. data/templates/slining_gitignore +14 -0
  60. data/templates/slining_layout.html.erb.erb +21 -0
  61. data/templates/smtp.rb +9 -0
  62. data/templates/spec_helper.rb +22 -0
  63. data/templates/staging.rb +5 -0
  64. data/templates/travis.yml.erb +21 -0
  65. data/templates/unicorn.rb +30 -0
  66. metadata +156 -0
@@ -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,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')
@@ -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,13 @@
1
+ #!/usr/bin/env sh
2
+
3
+ # Run this script immediately after cloning the codebase.
4
+
5
+ # Exit if any subcommand fails
6
+ set -e
7
+
8
+ # Set up Ruby dependencies via Bundler
9
+ bundle install
10
+
11
+ # Add binstubs to PATH in ~/.zshenv like this:
12
+ # export PATH=".git/safe/../../bin:$PATH"
13
+ mkdir -p .git/safe
@@ -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 'slining'
8
+
9
+ if ['create', '--create'].include? ARGV[0]
10
+ ARGV.shift
11
+ puts "[WARNING] the slining create argument is deprecated. Just use `slining #{ARGV.join}` instead"
12
+ end
13
+
14
+ templates_root = File.expand_path(File.join("..", "templates"), File.dirname(__FILE__))
15
+ Slining::AppGenerator.source_root templates_root
16
+ Slining::AppGenerator.source_paths << Rails::Generators::AppGenerator.source_root << templates_root
17
+
18
+ Slining::AppGenerator.start
@@ -0,0 +1,4 @@
1
+ require 'slining/version'
2
+ require 'slining/generators/app_generator'
3
+ require 'slining/actions'
4
+ require 'slining/app_builder'
@@ -0,0 +1,33 @@
1
+ module Slining
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,499 @@
1
+ module Slining
2
+ class AppBuilder < Rails::AppBuilder
3
+ include Slining::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 "bin_setup.erb", "bin/setup", port_number: port, force: true
32
+ run "chmod a+x bin/setup"
33
+ end
34
+
35
+ def provide_dev_prime_task
36
+ copy_file 'development_seeds.rb', 'lib/tasks/development_seeds.rake'
37
+ end
38
+
39
+ def configure_generators
40
+ config = <<-RUBY
41
+
42
+ config.generators do |generate|
43
+ generate.helper false
44
+ generate.javascript_engine false
45
+ generate.request_specs false
46
+ generate.routing_specs false
47
+ generate.stylesheets false
48
+ generate.test_framework :rspec
49
+ generate.view_specs false
50
+ end
51
+
52
+ RUBY
53
+
54
+ inject_into_class 'config/application.rb', 'Application', config
55
+ end
56
+
57
+ def set_up_factory_girl_for_rspec
58
+ copy_file 'factory_girl_rspec.rb', 'spec/support/factory_girl.rb'
59
+ end
60
+
61
+ def set_up_hound
62
+ copy_file "hound.yml", ".hound.yml"
63
+ end
64
+
65
+ def configure_newrelic
66
+ template 'newrelic.yml.erb', 'config/newrelic.yml'
67
+ end
68
+
69
+ def configure_smtp
70
+ copy_file 'smtp.rb', 'config/smtp.rb'
71
+
72
+ prepend_file 'config/environments/production.rb',
73
+ %{require Rails.root.join("config/smtp")\n}
74
+
75
+ config = <<-RUBY
76
+
77
+ config.action_mailer.delivery_method = :smtp
78
+ config.action_mailer.smtp_settings = SMTP_SETTINGS
79
+ RUBY
80
+
81
+ inject_into_file 'config/environments/production.rb', config,
82
+ :after => 'config.action_mailer.raise_delivery_errors = false'
83
+ end
84
+
85
+ def enable_rack_canonical_host
86
+ config = <<-RUBY
87
+
88
+ # Ensure requests are only served from one, canonical host name
89
+ config.middleware.use Rack::CanonicalHost, ENV.fetch("HOST")
90
+ RUBY
91
+
92
+ inject_into_file(
93
+ "config/environments/production.rb",
94
+ config,
95
+ after: serve_static_files_line
96
+ )
97
+ end
98
+
99
+ def enable_rack_deflater
100
+ config = <<-RUBY
101
+
102
+ # Enable deflate / gzip compression of controller-generated responses
103
+ config.middleware.use Rack::Deflater
104
+ RUBY
105
+
106
+ inject_into_file(
107
+ "config/environments/production.rb",
108
+ config,
109
+ after: serve_static_files_line
110
+ )
111
+ end
112
+
113
+ def setup_asset_host
114
+ replace_in_file 'config/environments/production.rb',
115
+ "# config.action_controller.asset_host = 'http://assets.example.com'",
116
+ 'config.action_controller.asset_host = ENV.fetch("ASSET_HOST", ENV.fetch("HOST"))'
117
+
118
+ replace_in_file 'config/initializers/assets.rb',
119
+ "config.assets.version = '1.0'",
120
+ 'config.assets.version = (ENV["ASSETS_VERSION"] || "1.0")'
121
+
122
+ inject_into_file(
123
+ "config/environments/production.rb",
124
+ ' config.static_cache_control = "public, max-age=#{1.year.to_i}"',
125
+ after: serve_static_files_line
126
+ )
127
+ end
128
+
129
+ def setup_staging_environment
130
+ staging_file = 'config/environments/staging.rb'
131
+ copy_file 'staging.rb', staging_file
132
+
133
+ config = <<-RUBY
134
+
135
+ Rails.application.configure do
136
+ # ...
137
+ end
138
+ RUBY
139
+
140
+ append_file staging_file, config
141
+ end
142
+
143
+ def setup_secret_token
144
+ template 'secrets.yml', 'config/secrets.yml', force: true
145
+ end
146
+
147
+ def disallow_wrapping_parameters
148
+ remove_file "config/initializers/wrap_parameters.rb"
149
+ end
150
+
151
+ def create_partials_directory
152
+ empty_directory 'app/views/application'
153
+ end
154
+
155
+ def create_shared_flashes
156
+ copy_file "_flashes.html.erb", "app/views/application/_flashes.html.erb"
157
+ copy_file "flashes_helper.rb", "app/helpers/flashes_helper.rb"
158
+ end
159
+
160
+ def create_shared_javascripts
161
+ copy_file '_javascript.html.erb', 'app/views/application/_javascript.html.erb'
162
+ end
163
+
164
+ def create_application_layout
165
+ template 'slining_layout.html.erb.erb',
166
+ 'app/views/layouts/application.html.erb',
167
+ force: true
168
+ end
169
+
170
+ def use_postgres_config_template
171
+ template 'postgresql_database.yml.erb', 'config/database.yml',
172
+ force: true
173
+ end
174
+
175
+ def create_database
176
+ bundle_command 'exec rake db:create db:migrate'
177
+ end
178
+
179
+ def replace_gemfile
180
+ remove_file 'Gemfile'
181
+ template 'Gemfile.erb', 'Gemfile'
182
+ end
183
+
184
+ def set_ruby_to_version_being_used
185
+ create_file '.ruby-version', "#{Slining::RUBY_VERSION}\n"
186
+ end
187
+
188
+ def setup_heroku_specific_gems
189
+ inject_into_file(
190
+ "Gemfile",
191
+ %{\n\s\sgem "rails_stdout_logging"},
192
+ after: /group :staging, :production do/
193
+ )
194
+ end
195
+
196
+ def enable_database_cleaner
197
+ copy_file 'database_cleaner_rspec.rb', 'spec/support/database_cleaner.rb'
198
+ end
199
+
200
+ def configure_spec_support_features
201
+ empty_directory_with_keep_file 'spec/features'
202
+ empty_directory_with_keep_file 'spec/support/features'
203
+ end
204
+
205
+ def configure_rspec
206
+ remove_file "spec/rails_helper.rb"
207
+ remove_file "spec/spec_helper.rb"
208
+ copy_file "rails_helper.rb", "spec/rails_helper.rb"
209
+ copy_file "spec_helper.rb", "spec/spec_helper.rb"
210
+ end
211
+
212
+ def configure_travis
213
+ template 'travis.yml.erb', '.travis.yml'
214
+ end
215
+
216
+ def configure_i18n_for_test_environment
217
+ copy_file "i18n.rb", "spec/support/i18n.rb"
218
+ end
219
+
220
+ def configure_i18n_for_missing_translations
221
+ raise_on_missing_translations_in("development")
222
+ raise_on_missing_translations_in("test")
223
+ end
224
+
225
+ def configure_i18n_tasks
226
+ run "cp $(i18n-tasks gem-path)/templates/rspec/i18n_spec.rb spec/"
227
+ copy_file "config_i18n_tasks.yml", "config/i18n-tasks.yml"
228
+ end
229
+
230
+ def configure_background_jobs_for_rspec
231
+ run 'rails g delayed_job:active_record'
232
+ end
233
+
234
+ def configure_action_mailer_in_specs
235
+ copy_file 'action_mailer.rb', 'spec/support/action_mailer.rb'
236
+ end
237
+
238
+ def configure_time_formats
239
+ remove_file "config/locales/en.yml"
240
+ template "config_locales_en.yml.erb", "config/locales/en.yml"
241
+ end
242
+
243
+ def configure_rack_timeout
244
+ rack_timeout_config = <<-RUBY
245
+ Rack::Timeout.timeout = (ENV["RACK_TIMEOUT"] || 10).to_i
246
+ RUBY
247
+
248
+ append_file "config/environments/production.rb", rack_timeout_config
249
+ end
250
+
251
+ def configure_simple_form
252
+ bundle_command "exec rails generate simple_form:install"
253
+ end
254
+
255
+ def configure_action_mailer
256
+ action_mailer_host "development", %{"localhost:#{port}"}
257
+ action_mailer_host "test", %{"www.example.com"}
258
+ action_mailer_host "staging", %{ENV.fetch("HOST")}
259
+ action_mailer_host "production", %{ENV.fetch("HOST")}
260
+ end
261
+
262
+ def configure_active_job
263
+ configure_application_file(
264
+ "config.active_job.queue_adapter = :delayed_job"
265
+ )
266
+ configure_environment "test", "config.active_job.queue_adapter = :inline"
267
+ end
268
+
269
+ def fix_i18n_deprecation_warning
270
+ config = <<-RUBY
271
+ config.i18n.enforce_available_locales = true
272
+ RUBY
273
+
274
+ inject_into_class 'config/application.rb', 'Application', config
275
+ end
276
+
277
+ def generate_rspec
278
+ generate 'rspec:install'
279
+ end
280
+
281
+ def configure_unicorn
282
+ copy_file 'unicorn.rb', 'config/unicorn.rb'
283
+ end
284
+
285
+ def setup_foreman
286
+ copy_file 'sample.env', '.sample.env'
287
+ copy_file 'Procfile', 'Procfile'
288
+ end
289
+
290
+ def setup_stylesheets
291
+ remove_file "app/assets/stylesheets/application.css"
292
+ copy_file "application.scss",
293
+ "app/assets/stylesheets/application.scss"
294
+ end
295
+
296
+ def install_refills
297
+ run "rails generate refills:import flashes"
298
+ run "rm app/views/refills/_flashes.html.erb"
299
+ run "rmdir app/views/refills"
300
+ end
301
+
302
+ def install_bitters
303
+ run "bitters install --path app/assets/stylesheets"
304
+ end
305
+
306
+ def gitignore_files
307
+ remove_file '.gitignore'
308
+ copy_file 'slining_gitignore', '.gitignore'
309
+ [
310
+ 'app/views/pages',
311
+ 'spec/lib',
312
+ 'spec/controllers',
313
+ 'spec/helpers',
314
+ 'spec/support/matchers',
315
+ 'spec/support/mixins',
316
+ 'spec/support/shared_examples'
317
+ ].each do |dir|
318
+ run "mkdir #{dir}"
319
+ run "touch #{dir}/.keep"
320
+ end
321
+ end
322
+
323
+ def init_git
324
+ run 'git init'
325
+ end
326
+
327
+ def create_staging_heroku_app(flags)
328
+ rack_env = "RACK_ENV=staging RAILS_ENV=staging"
329
+ app_name = heroku_app_name_for("staging")
330
+
331
+ run_heroku "create #{app_name} #{flags}", "staging"
332
+ run_heroku "config:add #{rack_env}", "staging"
333
+ end
334
+
335
+ def create_production_heroku_app(flags)
336
+ app_name = heroku_app_name_for("production")
337
+
338
+ run_heroku "create #{app_name} #{flags}", "production"
339
+ end
340
+
341
+ def create_heroku_apps(flags)
342
+ create_staging_heroku_app(flags)
343
+ create_production_heroku_app(flags)
344
+ end
345
+
346
+ def set_heroku_remotes
347
+ remotes = <<-SHELL
348
+
349
+ # Set up the staging and production apps.
350
+ #{join_heroku_app('staging')}
351
+ #{join_heroku_app('production')}
352
+ SHELL
353
+
354
+ append_file 'bin/setup', remotes
355
+ end
356
+
357
+ def join_heroku_app(environment)
358
+ heroku_app_name = heroku_app_name_for(environment)
359
+ <<-SHELL
360
+ if heroku join --app #{heroku_app_name} &> /dev/null; then
361
+ git remote add #{environment} git@heroku.com:#{heroku_app_name}.git || true
362
+ printf 'You are a collaborator on the "#{heroku_app_name}" Heroku app\n'
363
+ else
364
+ printf 'Ask for access to the "#{heroku_app_name}" Heroku app\n'
365
+ fi
366
+ SHELL
367
+ end
368
+
369
+ def set_heroku_rails_secrets
370
+ %w(staging production).each do |environment|
371
+ run_heroku "config:add SECRET_KEY_BASE=#{generate_secret}", environment
372
+ end
373
+ end
374
+
375
+ def set_heroku_serve_static_files
376
+ %w(staging production).each do |environment|
377
+ run_heroku "config:add RAILS_SERVE_STATIC_FILES=true", environment
378
+ end
379
+ end
380
+
381
+ def provide_deploy_script
382
+ copy_file "bin_deploy", "bin/deploy"
383
+
384
+ instructions = <<-MARKDOWN
385
+
386
+ ## Deploying
387
+
388
+ If you have previously run the `./bin/setup` script,
389
+ you can deploy to staging and production with:
390
+
391
+ $ ./bin/deploy staging
392
+ $ ./bin/deploy production
393
+ MARKDOWN
394
+
395
+ append_file "README.md", instructions
396
+ run "chmod a+x bin/deploy"
397
+ end
398
+
399
+ def create_github_repo(repo_name)
400
+ path_addition = override_path_for_tests
401
+ run "#{path_addition} hub create #{repo_name}"
402
+ end
403
+
404
+ def setup_segment
405
+ copy_file '_analytics.html.erb',
406
+ 'app/views/application/_analytics.html.erb'
407
+ end
408
+
409
+ def setup_bundler_audit
410
+ copy_file "bundler_audit.rake", "lib/tasks/bundler_audit.rake"
411
+ append_file "Rakefile", %{\ntask default: "bundler:audit"\n}
412
+ end
413
+
414
+ def setup_spring
415
+ bundle_command "exec spring binstub --all"
416
+ end
417
+
418
+ def copy_miscellaneous_files
419
+ copy_file "browserslist", "browserslist"
420
+ copy_file "errors.rb", "config/initializers/errors.rb"
421
+ copy_file "json_encoding.rb", "config/initializers/json_encoding.rb"
422
+ end
423
+
424
+ def customize_error_pages
425
+ meta_tags =<<-EOS
426
+ <meta charset="utf-8" />
427
+ <meta name="ROBOTS" content="NOODP" />
428
+ <meta name="viewport" content="initial-scale=1" />
429
+ EOS
430
+
431
+ %w(500 404 422).each do |page|
432
+ inject_into_file "public/#{page}.html", meta_tags, :after => "<head>\n"
433
+ replace_in_file "public/#{page}.html", /<!--.+-->\n/, ''
434
+ end
435
+ end
436
+
437
+ def remove_routes_comment_lines
438
+ replace_in_file 'config/routes.rb',
439
+ /Rails\.application\.routes\.draw do.*end/m,
440
+ "Rails.application.routes.draw do\nend"
441
+ end
442
+
443
+ def disable_xml_params
444
+ copy_file 'disable_xml_params.rb', 'config/initializers/disable_xml_params.rb'
445
+ end
446
+
447
+ def setup_default_rake_task
448
+ append_file 'Rakefile' do
449
+ <<-EOS
450
+ task(:default).clear
451
+ task default: [:spec]
452
+
453
+ if defined? RSpec
454
+ task(:spec).clear
455
+ RSpec::Core::RakeTask.new(:spec) do |t|
456
+ t.verbose = false
457
+ end
458
+ end
459
+ EOS
460
+ end
461
+ end
462
+
463
+ private
464
+
465
+ def raise_on_missing_translations_in(environment)
466
+ config = 'config.action_view.raise_on_missing_translations = true'
467
+
468
+ uncomment_lines("config/environments/#{environment}.rb", config)
469
+ end
470
+
471
+ def override_path_for_tests
472
+ if ENV['TESTING']
473
+ support_bin = File.expand_path(File.join('..', '..', 'spec', 'fakes', 'bin'))
474
+ "PATH=#{support_bin}:$PATH"
475
+ end
476
+ end
477
+
478
+ def run_heroku(command, environment)
479
+ path_addition = override_path_for_tests
480
+ run "#{path_addition} heroku #{command} --remote #{environment}"
481
+ end
482
+
483
+ def generate_secret
484
+ SecureRandom.hex(64)
485
+ end
486
+
487
+ def port
488
+ @port ||= [3000, 4000, 5000, 7000, 8000, 9000].sample
489
+ end
490
+
491
+ def serve_static_files_line
492
+ "config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?\n"
493
+ end
494
+
495
+ def heroku_app_name_for(environment)
496
+ "#{app_name.dasherize}-#{environment}"
497
+ end
498
+ end
499
+ end