underwear 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) 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 +38 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +123 -0
  8. data/LICENSE +21 -0
  9. data/NEWS.md +0 -0
  10. data/README.md +194 -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/underwear +13 -0
  16. data/lib/underwear.rb +4 -0
  17. data/lib/underwear/actions.rb +33 -0
  18. data/lib/underwear/app_builder.rb +511 -0
  19. data/lib/underwear/generators/app_generator.rb +239 -0
  20. data/lib/underwear/version.rb +5 -0
  21. data/spec/fakes/bin/heroku +5 -0
  22. data/spec/fakes/bin/hub +5 -0
  23. data/spec/features/github_spec.rb +15 -0
  24. data/spec/features/heroku_spec.rb +46 -0
  25. data/spec/features/new_project_spec.rb +113 -0
  26. data/spec/spec_helper.rb +20 -0
  27. data/spec/support/fake_github.rb +21 -0
  28. data/spec/support/fake_heroku.rb +43 -0
  29. data/spec/support/underwear.rb +49 -0
  30. data/templates/Gemfile.erb +65 -0
  31. data/templates/Procfile +3 -0
  32. data/templates/README.md.erb +32 -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/application.scss +1 -0
  38. data/templates/bin_deploy +12 -0
  39. data/templates/bin_setup.erb +36 -0
  40. data/templates/browserslist +4 -0
  41. data/templates/bundler_audit.rake +12 -0
  42. data/templates/circle.yml.erb +8 -0
  43. data/templates/config_i18n_tasks.yml +11 -0
  44. data/templates/config_locales_en.yml.erb +16 -0
  45. data/templates/database_cleaner_rspec.rb +21 -0
  46. data/templates/dev.rake +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/i18n.rb +3 -0
  52. data/templates/json_encoding.rb +1 -0
  53. data/templates/newrelic.yml.erb +34 -0
  54. data/templates/postgresql_database.yml.erb +22 -0
  55. data/templates/puma.rb +19 -0
  56. data/templates/rails_helper.rb +17 -0
  57. data/templates/sample.env +6 -0
  58. data/templates/secrets.yml +14 -0
  59. data/templates/sidekiq.rb +1 -0
  60. data/templates/smtp.rb +9 -0
  61. data/templates/spec_helper.rb +23 -0
  62. data/templates/staging.rb +5 -0
  63. data/templates/test.rb +48 -0
  64. data/templates/underwear_gitignore +14 -0
  65. data/templates/underwear_layout.html.erb.erb +21 -0
  66. data/underwear.gemspec +33 -0
  67. metadata +166 -0
@@ -0,0 +1,239 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/rails/app/app_generator'
3
+
4
+ module Underwear
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 :heroku, type: :boolean, aliases: "-H", default: false,
10
+ desc: "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 :skip_test_unit, type: :boolean, aliases: "-T", default: true,
19
+ desc: "Skip Test::Unit files"
20
+
21
+ class_option :skip_turbolinks, type: :boolean, default: true,
22
+ desc: "Skip turbolinks gem"
23
+
24
+ class_option :skip_bundle, type: :boolean, aliases: "-B", default: true,
25
+ desc: "Don't run bundle install"
26
+
27
+ def finish_template
28
+ invoke :underwear_customization
29
+ super
30
+ end
31
+
32
+ def underwear_customization
33
+ invoke :customize_gemfile
34
+ invoke :setup_development_environment
35
+ invoke :setup_test_environment
36
+ invoke :setup_production_environment
37
+ invoke :setup_staging_environment
38
+ invoke :setup_secret_token
39
+ invoke :create_underwear_views
40
+ invoke :configure_app
41
+ invoke :setup_stylesheets
42
+ invoke :setup_javascripts
43
+ invoke :copy_miscellaneous_files
44
+ invoke :customize_error_pages
45
+ invoke :remove_routes_comment_lines
46
+ invoke :setup_git
47
+ invoke :setup_database
48
+ invoke :create_heroku_apps
49
+ invoke :create_github_repo
50
+ invoke :setup_segment
51
+ invoke :setup_bundler_audit
52
+ invoke :setup_spring
53
+ invoke :setup_pages
54
+ invoke :outro
55
+ end
56
+
57
+ def customize_gemfile
58
+ build :replace_gemfile
59
+ build :set_ruby_to_version_being_used
60
+
61
+ if options[:heroku]
62
+ build :setup_heroku_specific_gems
63
+ end
64
+
65
+ bundle_command 'install'
66
+ end
67
+
68
+ def setup_database
69
+ say 'Setting up database'
70
+
71
+ if 'postgresql' == options[:database]
72
+ build :use_postgres_config_template
73
+ end
74
+
75
+ build :create_database
76
+ end
77
+
78
+ def setup_development_environment
79
+ say 'Setting up the development environment'
80
+ build :raise_on_delivery_errors
81
+ build :set_test_delivery_method
82
+ build :raise_on_unpermitted_parameters
83
+ build :provide_setup_script
84
+ build :provide_dev_prime_task
85
+ build :configure_generators
86
+ build :configure_i18n_for_missing_translations
87
+ end
88
+
89
+ def setup_test_environment
90
+ say 'Setting up the test environment'
91
+ build :set_up_factory_girl_for_rspec
92
+ build :generate_rspec
93
+ build :configure_rspec
94
+ build :configure_background_jobs_for_rspec
95
+ build :enable_database_cleaner
96
+ build :configure_spec_support_features
97
+ build :configure_ci
98
+ build :configure_i18n_for_test_environment
99
+ build :configure_i18n_tasks
100
+ build :configure_action_mailer_in_specs
101
+ end
102
+
103
+ def setup_production_environment
104
+ say 'Setting up the production environment'
105
+ build :configure_newrelic
106
+ build :configure_smtp
107
+ build :configure_rack_timeout
108
+ build :enable_rack_canonical_host
109
+ build :enable_rack_deflater
110
+ build :setup_asset_host
111
+ end
112
+
113
+ def setup_staging_environment
114
+ say 'Setting up the staging environment'
115
+ build :setup_staging_environment
116
+ end
117
+
118
+ def setup_secret_token
119
+ say 'Moving secret token out of version control'
120
+ build :setup_secret_token
121
+ end
122
+
123
+ def create_underwear_views
124
+ say 'Creating underwear views'
125
+ build :create_partials_directory
126
+ build :create_shared_flashes
127
+ build :create_shared_javascripts
128
+ build :create_application_layout
129
+ end
130
+
131
+ def configure_app
132
+ say 'Configuring app'
133
+ build :configure_action_mailer
134
+ build :setup_sidekiq
135
+ build :configure_time_formats
136
+ build :disable_xml_params
137
+ build :fix_i18n_deprecation_warning
138
+ build :setup_default_rake_task
139
+ build :configure_puma
140
+ build :setup_foreman
141
+ build :setup_devise
142
+ build :setup_friendly_id
143
+ #build :setup_rails_admin
144
+ end
145
+
146
+ def setup_stylesheets
147
+ say 'Set up stylesheets'
148
+ build :setup_stylesheets
149
+ end
150
+
151
+ def setup_javascripts
152
+ say 'Set up javascripts'
153
+ build :setup_javascripts
154
+ end
155
+
156
+ def setup_git
157
+ if !options[:skip_git]
158
+ say 'Initializing git'
159
+ invoke :setup_gitignore
160
+ invoke :init_git
161
+ end
162
+ end
163
+
164
+ def create_heroku_apps
165
+ if options[:heroku]
166
+ say "Creating Heroku apps"
167
+ build :create_heroku_apps, options[:heroku_flags]
168
+ build :set_heroku_serve_static_files
169
+ build :set_heroku_remotes
170
+ build :set_heroku_rails_secrets
171
+ build :provide_deploy_script
172
+ end
173
+ end
174
+
175
+ def create_github_repo
176
+ if !options[:skip_git] && options[:github]
177
+ say 'Creating Github repo'
178
+ build :create_github_repo, options[:github]
179
+ end
180
+ end
181
+
182
+ def setup_segment
183
+ say 'Setting up Segment'
184
+ build :setup_segment
185
+ end
186
+
187
+ def setup_gitignore
188
+ build :gitignore_files
189
+ end
190
+
191
+ def setup_bundler_audit
192
+ say "Setting up bundler-audit"
193
+ build :setup_bundler_audit
194
+ end
195
+
196
+ def setup_spring
197
+ say "Springifying binstubs"
198
+ build :setup_spring
199
+ end
200
+
201
+ def setup_pages
202
+ say "Setting up pages"
203
+ build :setup_pages
204
+ end
205
+
206
+ def init_git
207
+ build :init_git
208
+ end
209
+
210
+ def copy_miscellaneous_files
211
+ say 'Copying miscellaneous support files'
212
+ build :copy_miscellaneous_files
213
+ end
214
+
215
+ def customize_error_pages
216
+ say 'Customizing the 500/404/422 pages'
217
+ build :customize_error_pages
218
+ end
219
+
220
+ def remove_routes_comment_lines
221
+ build :remove_routes_comment_lines
222
+ end
223
+
224
+ def outro
225
+ say 'Congratulations! You just pulled our underwear.'
226
+ say "Remember to run 'rails generate airbrake' with your API key."
227
+ end
228
+
229
+ protected
230
+
231
+ def get_builder_class
232
+ Underwear::AppBuilder
233
+ end
234
+
235
+ def using_active_record?
236
+ !options[:skip_active_record]
237
+ end
238
+ end
239
+ end
@@ -0,0 +1,5 @@
1
+ module Underwear
2
+ RAILS_VERSION = "~> 4.2.4"
3
+ RUBY_VERSION = IO.read("#{File.dirname(__FILE__)}/../../.ruby-version").strip
4
+ VERSION = "0.0.1"
5
+ end
@@ -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,15 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "GitHub" do
4
+ before do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ end
8
+
9
+ it "suspends a project with --github option" do
10
+ repo_name = 'test'
11
+ run_underwear("--github=#{repo_name}")
12
+
13
+ expect(FakeGithub).to have_created_repo(repo_name)
14
+ end
15
+ end
@@ -0,0 +1,46 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Heroku" do
4
+ before do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ end
8
+
9
+ it "suspends a project for Heroku" do
10
+ run_underwear("--heroku=true")
11
+
12
+ expect(FakeHeroku).to(
13
+ have_gem_included(project_path, "rails_stdout_logging")
14
+ )
15
+ expect(FakeHeroku).to have_created_app_for("staging")
16
+ expect(FakeHeroku).to have_created_app_for("production")
17
+ expect(FakeHeroku).to have_configured_vars("staging", "SECRET_KEY_BASE")
18
+ expect(FakeHeroku).to have_configured_vars("production", "SECRET_KEY_BASE")
19
+
20
+ bin_setup_path = "#{project_path}/bin/setup"
21
+ bin_setup = IO.read(bin_setup_path)
22
+ app_name = UnderwearTestHelpers::APP_NAME.dasherize
23
+
24
+ expect(bin_setup).to include("heroku join --app #{app_name}-production")
25
+ expect(bin_setup).to include("heroku join --app #{app_name}-staging")
26
+ expect(File.stat(bin_setup_path)).to be_executable
27
+
28
+ bin_deploy_path = "#{project_path}/bin/deploy"
29
+ bin_deploy = IO.read(bin_deploy_path)
30
+
31
+ expect(bin_deploy).to include("heroku run rake db:migrate")
32
+ expect(File.stat(bin_deploy_path)).to be_executable
33
+
34
+ readme = IO.read("#{project_path}/README.md")
35
+
36
+ expect(readme).to include("./bin/deploy staging")
37
+ expect(readme).to include("./bin/deploy production")
38
+ end
39
+
40
+ it "suspends a project with extra Heroku flags" do
41
+ run_underwear(%{--heroku=true --heroku-flags="--region eu"})
42
+
43
+ expect(FakeHeroku).to have_created_app_for("staging", "--region eu")
44
+ expect(FakeHeroku).to have_created_app_for("production", "--region eu")
45
+ end
46
+ end
@@ -0,0 +1,113 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Suspend a new project with default configuration" do
4
+ before(:all) do
5
+ drop_dummy_database
6
+ remove_project_directory
7
+ run_underwear
8
+ end
9
+
10
+ it "ensures project specs pass" do
11
+ Dir.chdir(project_path) do
12
+ Bundler.with_clean_env do
13
+ expect(`rake`).to include('0 failures')
14
+ end
15
+ end
16
+ end
17
+
18
+ it "inherits staging config from production" do
19
+ staging_file = IO.read("#{project_path}/config/environments/staging.rb")
20
+ config_stub = "Rails.application.configure do"
21
+
22
+ expect(staging_file).to match(/^require_relative "production"/)
23
+ expect(staging_file).to match(/#{config_stub}/), staging_file
24
+ end
25
+
26
+ it "creates .ruby-version from Underwear .ruby-version" do
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
+ secrets_file = IO.read("#{project_path}/config/secrets.yml")
34
+
35
+ expect(secrets_file).to match(/secret_key_base: <%= ENV\["SECRET_KEY_BASE"\] %>/)
36
+ end
37
+
38
+ it "adds support file for action mailer" do
39
+ expect(File).to exist("#{project_path}/spec/support/action_mailer.rb")
40
+ end
41
+
42
+ it "adds support file for i18n" do
43
+ expect(File).to exist("#{project_path}/spec/support/i18n.rb")
44
+ end
45
+
46
+ it "ensures newrelic.yml reads NewRelic license from env" do
47
+ newrelic_file = IO.read("#{project_path}/config/newrelic.yml")
48
+
49
+ expect(newrelic_file).to match(
50
+ /license_key: "<%= ENV\["NEW_RELIC_LICENSE_KEY"\] %>"/
51
+ )
52
+ end
53
+
54
+ it "records pageviews through Segment if ENV variable set" do
55
+ expect(analytics_partial).
56
+ to include(%{<% if ENV["SEGMENT_KEY"] %>})
57
+ expect(analytics_partial).
58
+ to include(%{window.analytics.load("<%= ENV["SEGMENT_KEY"] %>");})
59
+ end
60
+
61
+ it "raises on unpermitted parameters in all environments" do
62
+ result = IO.read("#{project_path}/config/application.rb")
63
+
64
+ expect(result).to match(
65
+ /^ +config.action_controller.action_on_unpermitted_parameters = :raise$/
66
+ )
67
+ end
68
+
69
+ it "raises on missing translations in development and test" do
70
+ %w[development test].each do |environment|
71
+ environment_file =
72
+ IO.read("#{project_path}/config/environments/#{environment}.rb")
73
+ expect(environment_file).to match(
74
+ /^ +config.action_view.raise_on_missing_translations = true$/
75
+ )
76
+ end
77
+ end
78
+
79
+ it "adds specs for missing or unused translations" do
80
+ expect(File).to exist("#{project_path}/spec/i18n_spec.rb")
81
+ end
82
+
83
+ it "configs i18n-tasks" do
84
+ expect(File).to exist("#{project_path}/config/i18n-tasks.yml")
85
+ end
86
+
87
+ it "evaluates en.yml.erb" do
88
+ locales_en_file = IO.read("#{project_path}/config/locales/en.yml")
89
+ app_name = UnderwearTestHelpers::APP_NAME
90
+
91
+ expect(locales_en_file).to match(/application: #{app_name.humanize}/)
92
+ end
93
+
94
+ it "configs :test email delivery method for development" do
95
+ dev_env_file = IO.read("#{project_path}/config/environments/development.rb")
96
+ expect(dev_env_file).
97
+ to match(/^ +config.action_mailer.delivery_method = :test$/)
98
+ end
99
+
100
+ it "adds spring to binstubs" do
101
+ expect(File).to exist("#{project_path}/bin/spring")
102
+
103
+ spring_line = /^ +load File.expand_path\("\.\.\/spring", __FILE__\)$/
104
+ bin_stubs = %w(rake rails rspec)
105
+ bin_stubs.each do |bin_stub|
106
+ expect(IO.read("#{project_path}/bin/#{bin_stub}")).to match(spring_line)
107
+ end
108
+ end
109
+
110
+ def analytics_partial
111
+ IO.read("#{project_path}/app/views/application/_analytics.html.erb")
112
+ end
113
+ end
@@ -0,0 +1,20 @@
1
+ require 'bundler/setup'
2
+
3
+ Bundler.require(:default, :test)
4
+
5
+ require (Pathname.new(__FILE__).dirname + '../lib/underwear').expand_path
6
+
7
+ Dir['./spec/support/**/*.rb'].each { |file| require file }
8
+
9
+ RSpec.configure do |config|
10
+ config.include UnderwearTestHelpers
11
+
12
+ config.before(:all) do
13
+ create_tmp_directory
14
+ end
15
+
16
+ config.before(:each) do
17
+ FakeHeroku.clear!
18
+ FakeGithub.clear!
19
+ end
20
+ end