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
@@ -0,0 +1,249 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/app/app_generator'
3
+
4
+ module Suspenders
5
+ class AppGenerator < Rails::Generators::AppGenerator
6
+ class_option :database, type: :string, aliases: "-d", default: "postgresql",
7
+ desc: "Configure for selected database (options: #{DATABASES.join("/")})"
8
+
9
+ class_option :skip_heroku, type: :boolean, aliases: "-H", default: false,
10
+ desc: "Don't create staging and production Heroku apps"
11
+
12
+ class_option :heroku_flags, type: :string, default: "",
13
+ desc: "Set extra Heroku flags"
14
+
15
+ class_option :github, type: :string, aliases: "-G", default: nil,
16
+ desc: "Create Github repository and add remote origin pointed to repo"
17
+
18
+ class_option :origin, type: :string, default: nil,
19
+ desc: "Add and push to git remote for origin"
20
+
21
+ class_option :skip_git, type: :boolean, default: false,
22
+ desc: "Don't create and commit to git repository"
23
+
24
+ def finish_template
25
+ invoke :suspenders_customization
26
+ super
27
+ end
28
+
29
+ def suspenders_customization
30
+ invoke :customize_gemfile
31
+ invoke :setup_development_environment
32
+ invoke :setup_test_environment
33
+ invoke :setup_production_environment
34
+ invoke :setup_staging_environment
35
+ invoke :setup_secret_token
36
+ invoke :create_suspenders_views
37
+ invoke :configure_app
38
+ invoke :setup_stylesheets
39
+ invoke :setup_javascripts
40
+ invoke :copy_miscellaneous_files
41
+ invoke :customize_error_pages
42
+ invoke :remove_routes_comment_lines
43
+ invoke :setup_git
44
+ invoke :setup_database
45
+ invoke :create_heroku_apps
46
+ invoke :create_github_repo
47
+ invoke :setup_segment
48
+ invoke :setup_bundler_audit
49
+ invoke :setup_spring
50
+ invoke :run_stairs
51
+ invoke :initial_commit_and_branching
52
+ invoke :push_to_origin
53
+ invoke :outro
54
+ end
55
+
56
+ def customize_gemfile
57
+ build :replace_gemfile
58
+ build :set_ruby_to_version_being_used
59
+
60
+ unless options[:skip_heroku]
61
+ build :setup_heroku_specific_gems
62
+ end
63
+
64
+ bundle_command 'install'
65
+
66
+ build :version_gems_in_gemfile
67
+ end
68
+
69
+ def setup_database
70
+ say 'Setting up database'
71
+
72
+ if 'postgresql' == options[:database]
73
+ build :use_postgres_config_template
74
+ end
75
+
76
+ build :create_database
77
+ end
78
+
79
+ def setup_development_environment
80
+ say 'Setting up the development environment'
81
+ build :raise_on_delivery_errors
82
+ build :set_test_delivery_method
83
+ build :raise_on_unpermitted_parameters
84
+ build :provide_setup_script
85
+ build :configure_generators
86
+ build :configure_i18n_for_missing_translations
87
+ build :configure_rubocop
88
+ end
89
+
90
+ def setup_test_environment
91
+ say 'Setting up the test environment'
92
+ build :set_up_factory_girl_for_rspec
93
+ build :generate_rspec
94
+ build :configure_rspec
95
+ build :enable_database_cleaner
96
+ build :configure_spec_support_features
97
+ build :configure_i18n_for_test_environment
98
+ build :configure_i18n_tasks
99
+ build :configure_action_mailer_in_specs
100
+ end
101
+
102
+ def setup_production_environment
103
+ say 'Setting up the production environment'
104
+ build :configure_newrelic
105
+ build :configure_smtp
106
+ build :configure_rack_timeout
107
+ build :enable_rack_canonical_host
108
+ build :enable_rack_deflater
109
+ build :setup_asset_host
110
+ end
111
+
112
+ def setup_staging_environment
113
+ say 'Setting up the staging environment'
114
+ build :setup_staging_environment
115
+ end
116
+
117
+ def setup_secret_token
118
+ say 'Moving secret token out of version control'
119
+ build :setup_secret_token
120
+ end
121
+
122
+ def create_suspenders_views
123
+ say 'Creating suspenders views'
124
+ build :create_partials_directory
125
+ build :create_shared_flashes
126
+ build :create_shared_javascripts
127
+ build :create_application_layout
128
+ end
129
+
130
+ def configure_app
131
+ say 'Configuring app'
132
+ build :configure_action_mailer
133
+ build :configure_active_job
134
+ build :configure_time_formats
135
+ build :configure_simple_form
136
+ build :disable_xml_params
137
+ build :fix_i18n_deprecation_warning
138
+ build :setup_default_rake_task
139
+ build :configure_unicorn
140
+ build :setup_foreman
141
+ build :configure_airbrake
142
+ end
143
+
144
+ def setup_stylesheets
145
+ say 'Set up stylesheets'
146
+ build :setup_stylesheets
147
+ end
148
+
149
+ def setup_javascripts
150
+ say 'Set up javascripts'
151
+ build :setup_javascripts
152
+ end
153
+
154
+ def setup_git
155
+ if !options[:skip_git]
156
+ say 'Initializing git'
157
+ invoke :setup_gitignore
158
+ invoke :init_git
159
+ end
160
+ end
161
+
162
+ def initial_commit_and_branching
163
+ if !options[:skip_git]
164
+ say 'Creating initial commit and branches'
165
+ build :create_initial_commit
166
+ build :setup_deployment_environment_branches
167
+ end
168
+ end
169
+
170
+ def push_to_origin
171
+ if !options[:skip_git] && options[:origin]
172
+ say 'Pushing to origin remote'
173
+ build :setup_and_push_to_origin_remote, options[:origin]
174
+ end
175
+ end
176
+
177
+ def create_heroku_apps
178
+ unless options[:skip_heroku]
179
+ say "Creating Heroku apps"
180
+ build :create_heroku_apps, options[:heroku_flags]
181
+ build :set_heroku_serve_static_files
182
+ build :set_heroku_rails_secrets
183
+ end
184
+ end
185
+
186
+ def create_github_repo
187
+ if !options[:skip_git] && options[:github]
188
+ say 'Creating Github repo'
189
+ build :create_github_repo, options[:github]
190
+ end
191
+ end
192
+
193
+ def setup_segment
194
+ say 'Setting up Segment'
195
+ build :setup_segment
196
+ end
197
+
198
+ def setup_gitignore
199
+ build :gitignore_files
200
+ end
201
+
202
+ def setup_bundler_audit
203
+ say "Setting up bundler-audit"
204
+ build :setup_bundler_audit
205
+ end
206
+
207
+ def setup_spring
208
+ say "Springifying binstubs"
209
+ build :setup_spring
210
+ end
211
+
212
+ def init_git
213
+ build :init_git
214
+ end
215
+
216
+ def copy_miscellaneous_files
217
+ say 'Copying miscellaneous support files'
218
+ build :copy_miscellaneous_files
219
+ end
220
+
221
+ def customize_error_pages
222
+ say 'Customizing the 500/404/422 pages'
223
+ build :customize_error_pages
224
+ end
225
+
226
+ def remove_routes_comment_lines
227
+ build :remove_routes_comment_lines
228
+ end
229
+
230
+ def run_stairs
231
+ build :run_stairs
232
+ end
233
+
234
+ def outro
235
+ say 'Congratulations! You just pulled our suspenders.'
236
+ say 'Remember to update the README with specifics for your project.'
237
+ end
238
+
239
+ protected
240
+
241
+ def get_builder_class
242
+ Suspenders::AppBuilder
243
+ end
244
+
245
+ def using_active_record?
246
+ !options[:skip_active_record]
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,5 @@
1
+ module Suspenders
2
+ RAILS_VERSION = "4.2.3"
3
+ RUBY_VERSION = IO.read("#{File.dirname(__FILE__)}/../../.ruby-version").strip
4
+ VERSION = "2.0.0"
5
+ end
data/lib/suspenders.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'suspenders/version'
2
+ require 'suspenders/generators/app_generator'
3
+ require 'suspenders/actions'
4
+ require 'suspenders/app_builder'
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join('..', '..', 'support', 'fake_heroku'), File.dirname(__FILE__))
4
+
5
+ FakeHeroku.new(ARGV).run!
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join('..', '..', 'support', 'fake_github'), File.dirname(__FILE__))
4
+
5
+ FakeGithub.new(ARGV).run!
@@ -0,0 +1,10 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "GitHub" do
4
+ it "suspends a project with --github option" do
5
+ repo_name = 'test'
6
+ run_suspenders("--github=#{repo_name}")
7
+
8
+ expect(FakeGithub).to have_created_repo(repo_name)
9
+ end
10
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Heroku" do
4
+ it "suspends a project for Heroku" do
5
+ expect(FakeHeroku).to(
6
+ have_gem_included(project_path, "rails_stdout_logging")
7
+ )
8
+ expect(FakeHeroku).to have_created_app_for("staging")
9
+ expect(FakeHeroku).to have_created_app_for("production")
10
+ expect(FakeHeroku).to have_configured_vars("staging", "SECRET_KEY_BASE")
11
+ expect(FakeHeroku).to have_configured_vars("production", "SECRET_KEY_BASE")
12
+ end
13
+
14
+ it "suspends a project with extra Heroku flags" do
15
+ run_suspenders(%{--heroku-flags="--region eu"})
16
+
17
+ expect(FakeHeroku).to have_created_app_for("staging", "--region eu")
18
+ expect(FakeHeroku).to have_created_app_for("production", "--region eu")
19
+ end
20
+ end
@@ -0,0 +1,157 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Suspend a new project with default configuration" do
4
+ it "ensures project specs pass" do
5
+ run_suspenders
6
+
7
+ Dir.chdir(project_path) do
8
+ Bundler.with_clean_env do
9
+ expect(`rake`).to include('0 failures')
10
+ end
11
+ end
12
+ end
13
+
14
+ it "inherits staging config from production" do
15
+ run_suspenders
16
+
17
+ staging_file = IO.read("#{project_path}/config/environments/staging.rb")
18
+ config_stub = "Rails.application.configure do"
19
+
20
+ expect(staging_file).to match(/^require_relative "production"/)
21
+ expect(staging_file).to match(/#{config_stub}/), staging_file
22
+ end
23
+
24
+ it "creates .ruby-version from Suspenders .ruby-version" do
25
+ run_suspenders
26
+
27
+ ruby_version_file = IO.read("#{project_path}/.ruby-version")
28
+
29
+ expect(ruby_version_file).to eq "#{RUBY_VERSION}\n"
30
+ end
31
+
32
+ it "loads secret_key_base from env" do
33
+ run_suspenders
34
+
35
+ secrets_file = IO.read("#{project_path}/config/secrets.yml")
36
+
37
+ expect(secrets_file).to match(/secret_key_base: <%= ENV\["SECRET_KEY_BASE"\] %>/)
38
+ end
39
+
40
+ it "adds support file for action mailer" do
41
+ run_suspenders
42
+
43
+ expect(File).to exist("#{project_path}/spec/support/action_mailer.rb")
44
+ end
45
+
46
+ it "adds support file for i18n" do
47
+ run_suspenders
48
+
49
+ expect(File).to exist("#{project_path}/spec/support/i18n.rb")
50
+ end
51
+
52
+ it "ensures newrelic.yml reads NewRelic license from env" do
53
+ run_suspenders
54
+
55
+ newrelic_file = IO.read("#{project_path}/config/newrelic.yml")
56
+
57
+ expect(newrelic_file).to match(
58
+ /license_key: "<%= ENV\["NEW_RELIC_LICENSE_KEY"\] %>"/
59
+ )
60
+ end
61
+
62
+ it "records pageviews through Segment if ENV variable set" do
63
+ run_suspenders
64
+
65
+ expect(analytics_partial).
66
+ to include(%{<% if ENV["SEGMENT_KEY"] %>})
67
+ expect(analytics_partial).
68
+ to include(%{window.analytics.load("<%= ENV["SEGMENT_KEY"] %>");})
69
+ end
70
+
71
+ it "raises on unpermitted parameters in all environments" do
72
+ run_suspenders
73
+
74
+ result = IO.read("#{project_path}/config/application.rb")
75
+
76
+ expect(result).to match(
77
+ /^ +config.action_controller.action_on_unpermitted_parameters = :raise$/
78
+ )
79
+ end
80
+
81
+ it "raises on missing translations in development and test" do
82
+ run_suspenders
83
+
84
+ %w[development test].each do |environment|
85
+ environment_file =
86
+ IO.read("#{project_path}/config/environments/#{environment}.rb")
87
+ expect(environment_file).to match(
88
+ /^ +config.action_view.raise_on_missing_translations = true$/
89
+ )
90
+ end
91
+ end
92
+
93
+ it "adds specs for missing or unused translations" do
94
+ run_suspenders
95
+
96
+ expect(File).to exist("#{project_path}/spec/i18n_spec.rb")
97
+ end
98
+
99
+ it "configs i18n-tasks" do
100
+ run_suspenders
101
+
102
+ expect(File).to exist("#{project_path}/config/i18n-tasks.yml")
103
+ end
104
+
105
+ it "evaluates en.yml.erb" do
106
+ run_suspenders
107
+
108
+ locales_en_file = IO.read("#{project_path}/config/locales/en.yml")
109
+ app_name = SuspendersTestHelpers::APP_NAME
110
+
111
+ expect(locales_en_file).to match(/application: #{app_name.humanize}/)
112
+ end
113
+
114
+ it "configs simple_form" do
115
+ run_suspenders
116
+
117
+ expect(File).to exist("#{project_path}/config/initializers/simple_form.rb")
118
+ end
119
+
120
+ it "configs :test email delivery method for development" do
121
+ run_suspenders
122
+
123
+ dev_env_file = IO.read("#{project_path}/config/environments/development.rb")
124
+ expect(dev_env_file).
125
+ to match(/^ +config.action_mailer.delivery_method = :test$/)
126
+ end
127
+
128
+ it "configs active job queue adapter" do
129
+ run_suspenders
130
+
131
+ application_config = IO.read("#{project_path}/config/application.rb")
132
+ test_config = IO.read("#{project_path}/config/environments/test.rb")
133
+
134
+ expect(application_config).to match(
135
+ /^ +config.active_job.queue_adapter = :sidekiq$/
136
+ )
137
+ expect(test_config).to match(
138
+ /^ +config.active_job.queue_adapter = :inline$/
139
+ )
140
+ end
141
+
142
+ it "adds spring to binstubs" do
143
+ run_suspenders
144
+
145
+ expect(File).to exist("#{project_path}/bin/spring")
146
+
147
+ spring_line = /^ +load File.expand_path\("\.\.\/spring", __FILE__\)$/
148
+ bin_stubs = %w(rake rails rspec)
149
+ bin_stubs.each do |bin_stub|
150
+ expect(IO.read("#{project_path}/bin/#{bin_stub}")).to match(spring_line)
151
+ end
152
+ end
153
+
154
+ def analytics_partial
155
+ IO.read("#{project_path}/app/views/application/_analytics.html.erb")
156
+ end
157
+ end