underlay 1.50.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +87 -0
  4. data/.ruby-version +1 -0
  5. data/CONTRIBUTING.md +46 -0
  6. data/Gemfile +5 -0
  7. data/LICENSE +21 -0
  8. data/README.md +218 -0
  9. data/RELEASING.md +16 -0
  10. data/Rakefile +10 -0
  11. data/USAGE +13 -0
  12. data/bin/rake +18 -0
  13. data/bin/rspec +18 -0
  14. data/bin/setup +13 -0
  15. data/bin/underlay +29 -0
  16. data/circle.yml +3 -0
  17. data/lib/underlay/actions.rb +41 -0
  18. data/lib/underlay/adapters/heroku.rb +133 -0
  19. data/lib/underlay/app_builder.rb +556 -0
  20. data/lib/underlay/generators/app_generator.rb +280 -0
  21. data/lib/underlay/generators/enforce_ssl_generator.rb +14 -0
  22. data/lib/underlay/generators/initialize_active_job_generator.rb +21 -0
  23. data/lib/underlay/generators/static_generator.rb +12 -0
  24. data/lib/underlay/generators/stylesheet_base_generator.rb +36 -0
  25. data/lib/underlay/version.rb +10 -0
  26. data/lib/underlay.rb +11 -0
  27. data/spec/adapters/heroku_spec.rb +78 -0
  28. data/spec/fakes/bin/heroku +9 -0
  29. data/spec/fakes/bin/hub +9 -0
  30. data/spec/features/cli_help_spec.rb +38 -0
  31. data/spec/features/github_spec.rb +18 -0
  32. data/spec/features/heroku_spec.rb +72 -0
  33. data/spec/features/new_project_spec.rb +308 -0
  34. data/spec/spec_helper.rb +22 -0
  35. data/spec/support/fake_github.rb +26 -0
  36. data/spec/support/fake_heroku.rb +58 -0
  37. data/spec/support/underlay.rb +100 -0
  38. data/templates/Gemfile.erb +81 -0
  39. data/templates/Procfile +2 -0
  40. data/templates/README.md.erb +21 -0
  41. data/templates/_analytics.html.slim +10 -0
  42. data/templates/_css_overrides.html.slim +5 -0
  43. data/templates/_flashes.html.slim +8 -0
  44. data/templates/_flashes.scss +21 -0
  45. data/templates/_javascript.html.slim +10 -0
  46. data/templates/action_mailer.rb +7 -0
  47. data/templates/active_job.rb +15 -0
  48. data/templates/app.json.erb +45 -0
  49. data/templates/application.example.yml +19 -0
  50. data/templates/application.scss +5 -0
  51. data/templates/bin_deploy +12 -0
  52. data/templates/bin_rake +12 -0
  53. data/templates/bin_setup +31 -0
  54. data/templates/bin_setup_review_app.erb +22 -0
  55. data/templates/bin_update +26 -0
  56. data/templates/browserslist +3 -0
  57. data/templates/bundler_audit.rake +6 -0
  58. data/templates/capybara.rb +22 -0
  59. data/templates/circle.yml.erb +38 -0
  60. data/templates/config_locales_en.yml.erb +19 -0
  61. data/templates/database_cleaner_rspec.rb +23 -0
  62. data/templates/dev.rake +14 -0
  63. data/templates/dvelp_gitignore +18 -0
  64. data/templates/dvelp_layout.html.slim +17 -0
  65. data/templates/errors.rb +36 -0
  66. data/templates/factories.rb +4 -0
  67. data/templates/factory_bot_rspec.rb +5 -0
  68. data/templates/flashes_helper.rb +7 -0
  69. data/templates/i18n.rb +5 -0
  70. data/templates/json_encoding.rb +3 -0
  71. data/templates/lograge.rb +11 -0
  72. data/templates/postgresql_database.yml.erb +19 -0
  73. data/templates/puma.rb +14 -0
  74. data/templates/rack_mini_profiler.rb +7 -0
  75. data/templates/rails_helper.rb +27 -0
  76. data/templates/rubocop.yml.erb +85 -0
  77. data/templates/scss-lint.yml.erb +167 -0
  78. data/templates/secrets.yml +8 -0
  79. data/templates/sentry.rb +6 -0
  80. data/templates/shoulda_matchers_config_rspec.rb +8 -0
  81. data/templates/sidekiq.yml +3 -0
  82. data/templates/slim-lint.yml.erb +28 -0
  83. data/templates/smtp.rb +15 -0
  84. data/templates/spec_helper.rb +35 -0
  85. data/underlay.gemspec +33 -0
  86. metadata +187 -0
@@ -0,0 +1,280 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/rails/app/app_generator'
5
+
6
+ module Underlay
7
+ class AppGenerator < Rails::Generators::AppGenerator
8
+ hide!
9
+
10
+ class_option :database,
11
+ type: :string, aliases: '-d', default: 'postgresql',
12
+ desc: "Configure for selected database (options: #{DATABASES.join('/')})"
13
+
14
+ class_option :github,
15
+ type: :string, default: nil,
16
+ desc: 'Create Github repository and add remote origin pointed to repo'
17
+
18
+ class_option :help,
19
+ type: :boolean, aliases: '-h', group: :underlay,
20
+ desc: 'Show this help message and quit'
21
+
22
+ class_option :heroku,
23
+ type: :boolean, aliases: '-H', default: false,
24
+ desc: 'Create staging and production Heroku apps'
25
+
26
+ class_option :heroku_flags,
27
+ type: :string, default: '',
28
+ desc: 'Set extra Heroku flags'
29
+
30
+ class_option :path,
31
+ type: :string, default: nil,
32
+ desc: 'Path to the gem'
33
+
34
+ class_option :skip_system_test,
35
+ type: :boolean, default: true,
36
+ desc: 'Skip system test files'
37
+
38
+ class_option :skip_test,
39
+ type: :boolean, default: true,
40
+ desc: 'Skip Test Unit'
41
+
42
+ class_option :skip_turbolinks,
43
+ type: :boolean, default: true,
44
+ desc: 'Skip turbolinks gem'
45
+
46
+ class_option :version,
47
+ type: :boolean, aliases: '-v', group: :underlay,
48
+ desc: 'Show Underlay version number and quit'
49
+
50
+ def finish_template
51
+ invoke :underlay_customization
52
+ super
53
+ end
54
+
55
+ def underlay_customization
56
+ invoke :customize_gemfile
57
+ invoke :setup_development_environment
58
+ invoke :setup_test_environment
59
+ invoke :setup_production_environment
60
+ invoke :setup_secret_token
61
+ invoke :create_underlay_views
62
+ invoke :configure_app
63
+ invoke :copy_miscellaneous_files
64
+ invoke :customize_error_pages
65
+ invoke :remove_config_comment_lines
66
+ invoke :remove_routes_comment_lines
67
+ invoke :setup_figaro
68
+ invoke :setup_database
69
+ invoke :create_local_heroku_setup
70
+ invoke :create_heroku_apps
71
+ invoke :create_github_repo
72
+ invoke :setup_google_tag_manager
73
+ invoke :setup_bundler_audit
74
+ invoke :setup_spring
75
+ invoke :generate_default
76
+ invoke :setup_default_directories
77
+ invoke :clean_up
78
+ invoke :outro
79
+ end
80
+
81
+ def customize_gemfile
82
+ build :replace_gemfile, options[:path]
83
+ build :set_ruby_to_version_being_used
84
+ bundle_command 'install'
85
+ build_for_non_api :configure_simple_form
86
+ end
87
+
88
+ def setup_database
89
+ say 'Setting up database'
90
+
91
+ if options[:database] == 'postgresql'
92
+ build :use_postgres_config_template
93
+ end
94
+
95
+ build :create_database
96
+ end
97
+
98
+ def setup_development_environment
99
+ say 'Setting up the development environment'
100
+ build_for_non_api :raise_on_missing_assets_in_test
101
+ build :raise_on_delivery_errors
102
+ build :set_test_delivery_method
103
+ build :add_bullet_gem_configuration
104
+ build :raise_on_unpermitted_parameters
105
+ build :provide_setup_script
106
+ build :provide_rake_script
107
+ build :provide_update_script
108
+ build :provide_dev_prime_task
109
+ build :configure_generators
110
+ build :configure_i18n_for_missing_translations
111
+ build_for_non_api :configure_quiet_assets
112
+ end
113
+
114
+ def setup_test_environment
115
+ say 'Setting up the test environment'
116
+ build :set_up_factory_bot_for_rspec
117
+ build :generate_factories_file
118
+ build :generate_rspec
119
+ build :configure_rspec
120
+ build :enable_database_cleaner
121
+ build :provide_shoulda_matchers_config
122
+ build :configure_spec_support_features
123
+ build :configure_ci
124
+ build :configure_rubocop
125
+ build_for_non_api :configure_linters
126
+ build :configure_i18n_for_test_environment
127
+ build :configure_action_mailer_in_specs
128
+ build_for_non_api :configure_capybara
129
+ end
130
+
131
+ def setup_production_environment
132
+ say 'Setting up the production environment'
133
+ build :configure_smtp
134
+ build :configure_rack_timeout
135
+ build :enable_rack_canonical_host
136
+ build :enable_rack_deflater
137
+ build_for_non_api :setup_asset_host
138
+ end
139
+
140
+ def setup_secret_token
141
+ say 'Moving secret token out of version control'
142
+ build :setup_secret_token
143
+ end
144
+
145
+ def create_underlay_views
146
+ say 'Creating underlay views'
147
+ build :create_partials_directory
148
+ build_for_non_api :create_shared_flashes
149
+ build_for_non_api :create_shared_javascripts
150
+ build_for_non_api :create_shared_css_overrides
151
+ build_for_non_api :create_application_layout
152
+ end
153
+
154
+ def configure_app
155
+ say 'Configuring app'
156
+ build :configure_action_mailer
157
+ build :configure_active_job
158
+ build :configure_time_formats
159
+ build :setup_default_rake_task
160
+ build :replace_default_puma_configuration
161
+ build :set_up_forego
162
+ build :setup_rack_mini_profiler
163
+ end
164
+
165
+ def create_local_heroku_setup
166
+ say 'Creating local Heroku setup'
167
+ build :create_review_apps_setup_script
168
+ build :create_deploy_script
169
+ build :create_heroku_application_manifest_file
170
+ end
171
+
172
+ def create_heroku_apps
173
+ if options[:heroku]
174
+ say 'Creating Heroku apps'
175
+ build :create_heroku_apps, options[:heroku_flags]
176
+ build :set_heroku_remotes
177
+ build :set_heroku_rails_secrets
178
+ build :set_heroku_application_host
179
+ build :set_heroku_backup_schedule
180
+ build :create_heroku_pipeline
181
+ build :configure_automatic_deployment
182
+ end
183
+ end
184
+
185
+ def create_github_repo
186
+ if !options[:skip_git] && options[:github]
187
+ say 'Creating Github repo'
188
+ build :create_github_repo, options[:github]
189
+ end
190
+ end
191
+
192
+ def setup_google_tag_manager
193
+ say 'Setting up Google Tage Manager' unless options[:api]
194
+ build_for_non_api :setup_google_tag_manager
195
+ end
196
+
197
+ def setup_figaro
198
+ build :copy_figaro_files
199
+ end
200
+
201
+ def setup_default_directories
202
+ build :setup_default_directories
203
+ end
204
+
205
+ def setup_bundler_audit
206
+ say 'Setting up bundler-audit'
207
+ build :setup_bundler_audit
208
+ end
209
+
210
+ def clean_up
211
+ say 'Code cleaning'
212
+ build :rubocop_autocorrect
213
+ build :manual_code_correct
214
+ build_for_api :non_api_files_removal
215
+ end
216
+
217
+ def setup_spring
218
+ say 'Springifying binstubs'
219
+ build :setup_spring
220
+ end
221
+
222
+ def copy_miscellaneous_files
223
+ say 'Copying miscellaneous support files'
224
+ build :copy_miscellaneous_files
225
+ end
226
+
227
+ def customize_error_pages
228
+ say 'Customizing the 500/404/422 pages' unless options[:api]
229
+ build_for_non_api :customize_error_pages
230
+ end
231
+
232
+ def remove_config_comment_lines
233
+ build :remove_config_comment_lines
234
+ end
235
+
236
+ def remove_routes_comment_lines
237
+ build :remove_routes_comment_lines
238
+ end
239
+
240
+ def generate_default
241
+ run('spring stop')
242
+ generate('underlay:initialize_active_job')
243
+ generate('underlay:enforce_ssl')
244
+ generate('underlay:static')
245
+ generate('underlay:stylesheet_base')
246
+ end
247
+
248
+ def outro
249
+ say 'You just laid the underlay. Time to add some value!'
250
+ end
251
+
252
+ def self.banner
253
+ "underlay #{arguments.map(&:usage).join(' ')} [options]"
254
+ end
255
+
256
+ protected
257
+
258
+ # rubocop:disable AccessorMethodName
259
+ def get_builder_class
260
+ Underlay::AppBuilder
261
+ end
262
+ # rubocop:enable AccessorMethodName
263
+
264
+ def using_active_record?
265
+ !options[:skip_active_record]
266
+ end
267
+
268
+ def build_for_non_api(args)
269
+ return if options[:api]
270
+
271
+ build args
272
+ end
273
+
274
+ def build_for_api(args)
275
+ return unless options[:api]
276
+
277
+ build args
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+ require_relative '../actions'
5
+
6
+ module Underlay
7
+ class EnforceSslGenerator < Rails::Generators::Base
8
+ include Underlay::Actions
9
+
10
+ def enforce_ssl
11
+ configure_environment 'production', 'config.force_ssl = true'
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module Underlay
6
+ class InitializeActiveJobGenerator < Rails::Generators::Base
7
+ source_root(
8
+ File.expand_path(
9
+ File.join('..', '..', '..', 'templates'),
10
+ File.dirname(__FILE__)
11
+ )
12
+ )
13
+
14
+ def initialize_active_job
15
+ copy_file(
16
+ 'active_job.rb',
17
+ 'config/initializers/active_job.rb'
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module Underlay
6
+ class StaticGenerator < Rails::Generators::Base
7
+ def add_high_voltage
8
+ gem 'high_voltage'
9
+ Bundler.with_clean_env { run 'bundle install' }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ module Underlay
6
+ class StylesheetBaseGenerator < Rails::Generators::Base
7
+ source_root File.expand_path(
8
+ File.join('..', '..', '..', 'templates'),
9
+ File.dirname(__FILE__)
10
+ )
11
+
12
+ def add_css_config
13
+ copy_file(
14
+ 'application.scss',
15
+ 'app/assets/stylesheets/application.scss',
16
+ force: true
17
+ )
18
+ end
19
+
20
+ def add_flashes_css
21
+ copy_file(
22
+ '_flashes.scss',
23
+ 'app/assets/stylesheets/partials/_flashes.scss',
24
+ force: true
25
+ )
26
+ end
27
+
28
+ def remove_prior_config
29
+ remove_file 'app/assets/stylesheets/application.css'
30
+ end
31
+
32
+ def install_normalize_css
33
+ run 'bin/yarn add normalize.css'
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Underlay
4
+ RAILS_VERSION = '~> 5.1.3'
5
+ RUBY_VERSION = IO
6
+ .read("#{File.dirname(__FILE__)}/../../.ruby-version")
7
+ .strip
8
+ .freeze
9
+ VERSION = '1.50.1'
10
+ end
data/lib/underlay.rb ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'underlay/version'
4
+ require 'underlay/generators/app_generator'
5
+ require 'underlay/generators/enforce_ssl_generator'
6
+ require 'underlay/generators/initialize_active_job_generator'
7
+ require 'underlay/generators/static_generator'
8
+ require 'underlay/generators/stylesheet_base_generator'
9
+ require 'underlay/actions'
10
+ require 'underlay/adapters/heroku'
11
+ require 'underlay/app_builder'
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Underlay
6
+ module Adapters
7
+ RSpec.describe Heroku do
8
+ it 'sets the heroku remotes' do
9
+ setup_file = 'bin/setup'
10
+ app_builder = double(app_name: app_name)
11
+ allow(app_builder).to receive(:append_file)
12
+
13
+ Heroku.new(app_builder).set_heroku_remotes
14
+
15
+ expect(app_builder).to have_received(:append_file).with(
16
+ setup_file, /heroku join --app #{app_name.dasherize}-production/
17
+ )
18
+ expect(app_builder).to have_received(:append_file).with(
19
+ setup_file, /heroku join --app #{app_name.dasherize}-staging/
20
+ )
21
+ end
22
+
23
+ it 'sets the heroku rails secrets' do
24
+ app_builder = double(app_name: app_name)
25
+ allow(app_builder).to receive(:run)
26
+
27
+ Heroku.new(app_builder).set_heroku_rails_secrets
28
+
29
+ expect(app_builder).to(
30
+ have_configured_var('staging', 'SECRET_KEY_BASE')
31
+ )
32
+ expect(app_builder).to(
33
+ have_configured_var('production', 'SECRET_KEY_BASE')
34
+ )
35
+ end
36
+
37
+ it 'sets the heroku backup schedule' do
38
+ app_builder = double(app_name: app_name)
39
+ allow(app_builder).to receive(:run)
40
+
41
+ Heroku.new(app_builder).set_heroku_backup_schedule
42
+
43
+ expect(app_builder).to have_backup_schedule('staging')
44
+ expect(app_builder).to have_backup_schedule('production')
45
+ end
46
+
47
+ it 'sets the application host' do
48
+ app_builder = double(app_name: app_name)
49
+ allow(app_builder).to receive(:run)
50
+
51
+ Heroku.new(app_builder).set_heroku_application_host
52
+
53
+ expect(app_builder).to(
54
+ have_configured_var('staging', 'APPLICATION_HOST')
55
+ )
56
+
57
+ expect(app_builder).to(
58
+ have_configured_var('production', 'APPLICATION_HOST')
59
+ )
60
+ end
61
+
62
+ def app_name
63
+ UnderlayTestHelpers::APP_NAME
64
+ end
65
+
66
+ def have_backup_schedule(remote_name)
67
+ have_received(:run).with(
68
+ /pg:backups:schedule DATABASE_URL --at '10:00 UTC'/ +
69
+ /--remote #{remote_name}/
70
+ )
71
+ end
72
+
73
+ def have_configured_var(remote_name, var)
74
+ have_received(:run).with(/config:add #{var}=.+ --remote #{remote_name}/)
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require File.expand_path(
5
+ File.join('..', '..', 'support', 'fake_heroku'),
6
+ File.dirname(__FILE__)
7
+ )
8
+
9
+ FakeHeroku.new(ARGV).run!
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require File.expand_path(
5
+ File.join('..', '..', 'support', 'fake_github'),
6
+ File.dirname(__FILE__)
7
+ )
8
+
9
+ FakeGithub.new(ARGV).run!
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'Command line help output' do
6
+ let(:help_text) { underlay_help_command }
7
+
8
+ it 'does not contain the default rails usage statement' do
9
+ expect(help_text).not_to include('rails new APP_PATH [options]')
10
+ end
11
+
12
+ it 'provides the correct usage statement for underlay' do
13
+ expect(help_text).to include <<~HERE
14
+ Usage:
15
+ underlay APP_PATH [options]
16
+ HERE
17
+ end
18
+
19
+ it 'does not contain the default rails group' do
20
+ expect(help_text).not_to include('Rails options:')
21
+ end
22
+
23
+ it 'provides help and version usage within the underlay group' do
24
+ expect(help_text).to include <<~HERE
25
+ Underlay options:
26
+ -h, [--help], [--no-help] # Show this help message and quit
27
+ -v, [--version], [--no-version] # Show Underlay version number and quit
28
+ HERE
29
+ end
30
+
31
+ it 'does not show the default extended rails help section' do
32
+ expect(help_text).not_to include('Create underlay files for app generator.')
33
+ end
34
+
35
+ it 'contains the usage statement from the underlay gem' do
36
+ expect(help_text).to include IO.read(usage_file)
37
+ end
38
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'GitHub' do
6
+ before do
7
+ drop_dummy_database
8
+ remove_project_directory
9
+ end
10
+
11
+ it 'suspends a project with --github option' do
12
+ repo_name = 'test'
13
+ run_underlay("--github=#{repo_name}")
14
+ setup_app_dependencies
15
+
16
+ expect(FakeGithub).to have_created_repo(repo_name)
17
+ end
18
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe 'Heroku' do
6
+ context '--heroku' do
7
+ before(:all) do
8
+ clean_up
9
+ run_underlay('--heroku=true')
10
+ setup_app_dependencies
11
+ end
12
+
13
+ it 'suspends a project for Heroku' do
14
+ app_name = UnderlayTestHelpers::APP_NAME.dasherize
15
+
16
+ expect(FakeHeroku).to have_created_app_for('staging')
17
+ expect(FakeHeroku).to have_created_app_for('production')
18
+ expect(FakeHeroku).to have_configured_vars('staging', 'SECRET_KEY_BASE')
19
+ expect(FakeHeroku).to have_configured_vars(
20
+ 'production',
21
+ 'SECRET_KEY_BASE'
22
+ )
23
+ %w[staging production].each do |env|
24
+ expect(FakeHeroku).to have_configured_vars(env, 'APPLICATION_HOST')
25
+ end
26
+ expect(FakeHeroku).to have_setup_pipeline_for(app_name)
27
+
28
+ bin_setup_path = "#{project_path}/bin/setup"
29
+ bin_setup = IO.read(bin_setup_path)
30
+
31
+ expect(bin_setup).to match(/^if heroku join --app #{app_name}-production/)
32
+ expect(bin_setup).to match(/^if heroku join --app #{app_name}-staging/)
33
+ expect(bin_setup).to match(/^git config heroku.remote staging/)
34
+ expect(File.stat(bin_setup_path)).to be_executable
35
+
36
+ readme = IO.read("#{project_path}/README.md")
37
+
38
+ expect(readme).to include('./bin/deploy staging')
39
+ expect(readme).to include('./bin/deploy production')
40
+
41
+ circle_yml_path = "#{project_path}/circle.yml"
42
+ circle_yml = IO.read(circle_yml_path)
43
+
44
+ expect(circle_yml).to include <<-YML.strip_heredoc
45
+ deployment:
46
+ staging:
47
+ branch: master
48
+ commands:
49
+ - bin/deploy staging
50
+ YML
51
+ end
52
+ end
53
+
54
+ context '--heroku with region flag' do
55
+ before(:all) do
56
+ clean_up
57
+ run_underlay(%(--heroku=true --heroku-flags="--region eu"))
58
+ setup_app_dependencies
59
+ end
60
+
61
+ it 'suspends a project with extra Heroku flags' do
62
+ expect(FakeHeroku).to have_created_app_for('staging', '--region eu')
63
+ expect(FakeHeroku).to have_created_app_for('production', '--region eu')
64
+ end
65
+ end
66
+
67
+ def clean_up
68
+ drop_dummy_database
69
+ remove_project_directory
70
+ FakeHeroku.clear!
71
+ end
72
+ end