underwear 0.0.1

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 (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