underlay 1.50.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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rubocop.yml +87 -0
- data/.ruby-version +1 -0
- data/CONTRIBUTING.md +46 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/README.md +218 -0
- data/RELEASING.md +16 -0
- data/Rakefile +10 -0
- data/USAGE +13 -0
- data/bin/rake +18 -0
- data/bin/rspec +18 -0
- data/bin/setup +13 -0
- data/bin/underlay +29 -0
- data/circle.yml +3 -0
- data/lib/underlay/actions.rb +41 -0
- data/lib/underlay/adapters/heroku.rb +133 -0
- data/lib/underlay/app_builder.rb +556 -0
- data/lib/underlay/generators/app_generator.rb +280 -0
- data/lib/underlay/generators/enforce_ssl_generator.rb +14 -0
- data/lib/underlay/generators/initialize_active_job_generator.rb +21 -0
- data/lib/underlay/generators/static_generator.rb +12 -0
- data/lib/underlay/generators/stylesheet_base_generator.rb +36 -0
- data/lib/underlay/version.rb +10 -0
- data/lib/underlay.rb +11 -0
- data/spec/adapters/heroku_spec.rb +78 -0
- data/spec/fakes/bin/heroku +9 -0
- data/spec/fakes/bin/hub +9 -0
- data/spec/features/cli_help_spec.rb +38 -0
- data/spec/features/github_spec.rb +18 -0
- data/spec/features/heroku_spec.rb +72 -0
- data/spec/features/new_project_spec.rb +308 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/fake_github.rb +26 -0
- data/spec/support/fake_heroku.rb +58 -0
- data/spec/support/underlay.rb +100 -0
- data/templates/Gemfile.erb +81 -0
- data/templates/Procfile +2 -0
- data/templates/README.md.erb +21 -0
- data/templates/_analytics.html.slim +10 -0
- data/templates/_css_overrides.html.slim +5 -0
- data/templates/_flashes.html.slim +8 -0
- data/templates/_flashes.scss +21 -0
- data/templates/_javascript.html.slim +10 -0
- data/templates/action_mailer.rb +7 -0
- data/templates/active_job.rb +15 -0
- data/templates/app.json.erb +45 -0
- data/templates/application.example.yml +19 -0
- data/templates/application.scss +5 -0
- data/templates/bin_deploy +12 -0
- data/templates/bin_rake +12 -0
- data/templates/bin_setup +31 -0
- data/templates/bin_setup_review_app.erb +22 -0
- data/templates/bin_update +26 -0
- data/templates/browserslist +3 -0
- data/templates/bundler_audit.rake +6 -0
- data/templates/capybara.rb +22 -0
- data/templates/circle.yml.erb +38 -0
- data/templates/config_locales_en.yml.erb +19 -0
- data/templates/database_cleaner_rspec.rb +23 -0
- data/templates/dev.rake +14 -0
- data/templates/dvelp_gitignore +18 -0
- data/templates/dvelp_layout.html.slim +17 -0
- data/templates/errors.rb +36 -0
- data/templates/factories.rb +4 -0
- data/templates/factory_bot_rspec.rb +5 -0
- data/templates/flashes_helper.rb +7 -0
- data/templates/i18n.rb +5 -0
- data/templates/json_encoding.rb +3 -0
- data/templates/lograge.rb +11 -0
- data/templates/postgresql_database.yml.erb +19 -0
- data/templates/puma.rb +14 -0
- data/templates/rack_mini_profiler.rb +7 -0
- data/templates/rails_helper.rb +27 -0
- data/templates/rubocop.yml.erb +85 -0
- data/templates/scss-lint.yml.erb +167 -0
- data/templates/secrets.yml +8 -0
- data/templates/sentry.rb +6 -0
- data/templates/shoulda_matchers_config_rspec.rb +8 -0
- data/templates/sidekiq.yml +3 -0
- data/templates/slim-lint.yml.erb +28 -0
- data/templates/smtp.rb +15 -0
- data/templates/spec_helper.rb +35 -0
- data/underlay.gemspec +33 -0
- metadata +187 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe 'Suspend a new project with default configuration' do
|
6
|
+
before(:all) do
|
7
|
+
drop_dummy_database
|
8
|
+
remove_project_directory
|
9
|
+
run_underlay
|
10
|
+
setup_app_dependencies
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'uses custom Gemfile' do
|
14
|
+
gemfile_file = IO.read("#{project_path}/Gemfile")
|
15
|
+
expect(gemfile_file).to match(
|
16
|
+
/^ruby "#{Underlay::RUBY_VERSION}"$/
|
17
|
+
)
|
18
|
+
expect(gemfile_file).to match(
|
19
|
+
/^gem "autoprefixer-rails"$/
|
20
|
+
)
|
21
|
+
expect(gemfile_file).to match(
|
22
|
+
/^gem "rails", "#{Underlay::RAILS_VERSION}"$/
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'ensures project specs pass' do
|
27
|
+
Dir.chdir(project_path) do
|
28
|
+
Bundler.with_clean_env do
|
29
|
+
expect(`rake`).to include('0 failures')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'includes the bundle:audit task' do
|
35
|
+
Dir.chdir(project_path) do
|
36
|
+
Bundler.with_clean_env do
|
37
|
+
expect(`rails -T`).to include('rails bundle:audit')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'creates .ruby-version from Underlay .ruby-version' do
|
43
|
+
ruby_version_file = IO.read("#{project_path}/.ruby-version")
|
44
|
+
|
45
|
+
expect(ruby_version_file).to eq "#{RUBY_VERSION}\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "doesn't generate test directory" do
|
49
|
+
expect(File).not_to exist("#{project_path}/test")
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'loads secret_key_base from env' do
|
53
|
+
secrets_file = IO.read("#{project_path}/config/secrets.yml")
|
54
|
+
|
55
|
+
expect(secrets_file)
|
56
|
+
.to match(/secret_key_base: <%= ENV\["SECRET_KEY_BASE"\] %>/)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'adds bin/setup file' do
|
60
|
+
expect(File).to exist("#{project_path}/bin/setup")
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'makes bin/setup executable' do
|
64
|
+
bin_setup_path = "#{project_path}/bin/setup"
|
65
|
+
|
66
|
+
expect(File.stat(bin_setup_path)).to be_executable
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'adds support file for action mailer' do
|
70
|
+
expect(File).to exist("#{project_path}/spec/support/action_mailer.rb")
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'configures capybara' do
|
74
|
+
expect(File).to exist("#{project_path}/spec/support/capybara.rb")
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'adds support file for i18n' do
|
78
|
+
expect(File).to exist("#{project_path}/spec/support/i18n.rb")
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'ensures Gemfile contains `rack-mini-profiler`' do
|
82
|
+
gemfile = IO.read("#{project_path}/Gemfile")
|
83
|
+
|
84
|
+
expect(gemfile).to include %(gem "rack-mini-profiler", require: false)
|
85
|
+
end
|
86
|
+
|
87
|
+
it 'initializes ActiveJob to avoid memory bloat' do
|
88
|
+
expect(File)
|
89
|
+
.to exist("#{project_path}/config/initializers/active_job.rb")
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'creates a rack-mini-profiler initializer' do
|
93
|
+
expect(File)
|
94
|
+
.to exist("#{project_path}/config/initializers/rack_mini_profiler.rb")
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'records pageviews through Google Tag Manager if ENV variable set' do
|
98
|
+
expect(analytics_partial).to include(%(if ENV['GOOGLE_TAG_ID']))
|
99
|
+
expect(analytics_partial).to include(
|
100
|
+
"https://www.googletagmanager.com/ns.html?id=\#{ENV['GOOGLE_TAG_ID']}"
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'raises on unpermitted parameters in all environments' do
|
105
|
+
result = IO.read("#{project_path}/config/application.rb")
|
106
|
+
|
107
|
+
expect(result).to match(
|
108
|
+
/^ +config.action_controller.action_on_unpermitted_parameters = :raise$/
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'adds explicit quiet_assets configuration' do
|
113
|
+
result = IO.read("#{project_path}/config/application.rb")
|
114
|
+
|
115
|
+
expect(result).to match(/^ +config.assets.quiet = true$/)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'configures public_file_server.headers in production' do
|
119
|
+
expect(production_config).to match(
|
120
|
+
/^ +config.public_file_server.headers = {\n +"Cache-Control" => "public,/
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'configures production environment to enforce SSL' do
|
125
|
+
expect(production_config).to match(
|
126
|
+
/^ +config.force_ssl = true/
|
127
|
+
)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'raises on missing translations in development and test' do
|
131
|
+
[development_config, test_config].each do |environment_file|
|
132
|
+
expect(environment_file).to match(
|
133
|
+
/^ +config.action_view.raise_on_missing_translations = true$/
|
134
|
+
)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'evaluates en.yml.erb' do
|
139
|
+
locales_en_file = IO.read("#{project_path}/config/locales/en.yml")
|
140
|
+
|
141
|
+
expect(locales_en_file).to match(/application: #{app_name.humanize}/)
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'configs simple_form' do
|
145
|
+
expect(File).to exist("#{project_path}/config/initializers/simple_form.rb")
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'configs :test email delivery method for development' do
|
149
|
+
expect(development_config)
|
150
|
+
.to match(/^ +config.action_mailer.delivery_method = :file$/)
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'sets action mailer default host and asset host' do
|
154
|
+
config_key = 'config\.action_mailer\.asset_host'
|
155
|
+
config_value =
|
156
|
+
%q{ENV\.fetch\("ASSET_HOST", ENV\.fetch\("APPLICATION_HOST"\)\)}
|
157
|
+
expect(production_config).to match(/#{config_key} = #{config_value}/)
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'uses APPLICATION_HOST, not HOST in the production config' do
|
161
|
+
expect(production_config).to match(/"APPLICATION_HOST"/)
|
162
|
+
expect(production_config).not_to match(/"HOST"/)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'configures email interceptor in smtp config' do
|
166
|
+
smtp_file = IO.read("#{project_path}/config/smtp.rb")
|
167
|
+
expect(smtp_file)
|
168
|
+
.to match(/RecipientInterceptor.new\(ENV\["EMAIL_RECIPIENTS"\]\)/)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'configures language in html element' do
|
172
|
+
layout_path = '/app/views/layouts/application.html.slim'
|
173
|
+
layout_file = IO.read("#{project_path}#{layout_path}")
|
174
|
+
expect(layout_file).to match(/html lang="\#{I18n.locale}\"/)
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'configs active job queue adapter' do
|
178
|
+
application_config = IO.read("#{project_path}/config/application.rb")
|
179
|
+
|
180
|
+
expect(application_config).to match(
|
181
|
+
/^ +config.active_job.queue_adapter = :sidekiq$/
|
182
|
+
)
|
183
|
+
expect(test_config).to match(
|
184
|
+
/^ +config.active_job.queue_adapter = :inline$/
|
185
|
+
)
|
186
|
+
expect(File).to exist("#{project_path}/config/sidekiq.yml")
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'configs bullet gem in development' do
|
190
|
+
expect(development_config).to match(/^ +Bullet.enable = true$/)
|
191
|
+
expect(development_config).to match(/^ +Bullet.bullet_logger = true$/)
|
192
|
+
expect(development_config).to match(/^ +Bullet.rails_logger = true$/)
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'configs missing assets to raise in test' do
|
196
|
+
expect(test_config).to match(
|
197
|
+
/^ +config.assets.raise_runtime_errors = true$/
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'adds spring to binstubs' do
|
202
|
+
expect(File).to exist("#{project_path}/bin/spring")
|
203
|
+
|
204
|
+
bin_stubs = %w[rake rails rspec]
|
205
|
+
bin_stubs.each do |bin_stub|
|
206
|
+
expect(IO.read("#{project_path}/bin/#{bin_stub}")).to match(/spring/)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'removes comments and extra newlines from config files' do
|
211
|
+
config_files = [
|
212
|
+
IO.read("#{project_path}/config/application.rb"),
|
213
|
+
IO.read("#{project_path}/config/environment.rb"),
|
214
|
+
development_config,
|
215
|
+
test_config,
|
216
|
+
production_config
|
217
|
+
]
|
218
|
+
|
219
|
+
config_files.each do |file|
|
220
|
+
expect(file).not_to match(/.*#.*/)
|
221
|
+
expect(file).not_to match(/^$\n/)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'copies factories.rb' do
|
226
|
+
expect(File).to exist("#{project_path}/spec/factories.rb")
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'creates review apps setup script' do
|
230
|
+
bin_setup_path = "#{project_path}/bin/setup_review_app"
|
231
|
+
bin_setup = IO.read(bin_setup_path)
|
232
|
+
|
233
|
+
expect(bin_setup).to include(
|
234
|
+
"PARENT_APP_NAME=#{app_name.dasherize}-staging"
|
235
|
+
)
|
236
|
+
expect(bin_setup).to include("APP_NAME=#{app_name.dasherize}-staging-pr-$1")
|
237
|
+
expect(bin_setup)
|
238
|
+
.to include('heroku run rails db:migrate --exit-code --app $APP_NAME')
|
239
|
+
expect(bin_setup).to include('heroku ps:scale worker=1 --app $APP_NAME')
|
240
|
+
expect(bin_setup).to include('heroku restart --app $APP_NAME')
|
241
|
+
|
242
|
+
expect(File.stat(bin_setup_path)).to be_executable
|
243
|
+
end
|
244
|
+
|
245
|
+
it 'creates deploy script' do
|
246
|
+
bin_deploy_path = "#{project_path}/bin/deploy"
|
247
|
+
bin_deploy = IO.read(bin_deploy_path)
|
248
|
+
|
249
|
+
expect(bin_deploy).to include('heroku run rails db:migrate --exit-code')
|
250
|
+
expect(File.stat(bin_deploy_path)).to be_executable
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'creates heroku application manifest file with application name in it' do
|
254
|
+
app_json_file = IO.read("#{project_path}/app.json")
|
255
|
+
|
256
|
+
expect(app_json_file).to match(/"name":"#{app_name.dasherize}"/)
|
257
|
+
end
|
258
|
+
|
259
|
+
def app_name
|
260
|
+
UnderlayTestHelpers::APP_NAME
|
261
|
+
end
|
262
|
+
|
263
|
+
it 'adds high_voltage' do
|
264
|
+
gemfile = IO.read("#{project_path}/Gemfile")
|
265
|
+
expect(gemfile).to match(/high_voltage/)
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'configures flashes' do
|
269
|
+
flashes_path = %w[app assets stylesheets partials _flashes.scss]
|
270
|
+
expect(read_project_file(flashes_path)).to match(/\.flash-alert/m)
|
271
|
+
|
272
|
+
app_css = read_project_file(%w[app assets stylesheets application.scss])
|
273
|
+
expect(app_css).to match(%r{normalize\.css\/normalize\.css/})
|
274
|
+
expect(app_css).to match(%r{partials\/_flashes.scss/})
|
275
|
+
end
|
276
|
+
|
277
|
+
it "doesn't use turbolinks" do
|
278
|
+
app_js = read_project_file(%w[app assets javascripts application.js])
|
279
|
+
expect(app_js).not_to match(/turbolinks/)
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'configures Timecop safe mode' do
|
283
|
+
spec_helper = read_project_file(%w[spec spec_helper.rb])
|
284
|
+
expect(spec_helper).to match(/Timecop.safe_mode = true/)
|
285
|
+
end
|
286
|
+
|
287
|
+
def development_config
|
288
|
+
@development_config ||=
|
289
|
+
read_project_file %w[config environments development.rb]
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_config
|
293
|
+
@test_config ||= read_project_file %w[config environments test.rb]
|
294
|
+
end
|
295
|
+
|
296
|
+
def production_config
|
297
|
+
@production_config ||=
|
298
|
+
read_project_file %w[config environments production.rb]
|
299
|
+
end
|
300
|
+
|
301
|
+
def analytics_partial
|
302
|
+
IO.read("#{project_path}/app/views/application/_analytics.html.slim")
|
303
|
+
end
|
304
|
+
|
305
|
+
def read_project_file(path)
|
306
|
+
IO.read(File.join(project_path, *path))
|
307
|
+
end
|
308
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
|
5
|
+
Bundler.require(:default, :test)
|
6
|
+
|
7
|
+
require(Pathname.new(__FILE__).dirname + '../lib/underlay').expand_path
|
8
|
+
|
9
|
+
Dir['./spec/support/**/*.rb'].each { |file| require file }
|
10
|
+
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.include UnderlayTestHelpers
|
13
|
+
|
14
|
+
config.before(:all) do
|
15
|
+
add_fakes_to_path
|
16
|
+
create_tmp_directory
|
17
|
+
end
|
18
|
+
|
19
|
+
config.before(:each) do
|
20
|
+
FakeGithub.clear!
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FakeGithub
|
4
|
+
RECORDER = File.expand_path(
|
5
|
+
File.join('..', '..', 'tmp', 'hub_commands'),
|
6
|
+
File.dirname(__FILE__)
|
7
|
+
)
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
@args = args
|
11
|
+
end
|
12
|
+
|
13
|
+
def run!
|
14
|
+
File.open(RECORDER, 'a') do |file|
|
15
|
+
file.write @args.join(' ')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.clear!
|
20
|
+
FileUtils.rm_rf RECORDER
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.has_created_repo?(repo_name)
|
24
|
+
File.read(RECORDER) == "create #{repo_name}"
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class FakeHeroku
|
4
|
+
RECORDER = File.expand_path(
|
5
|
+
File.join('..', '..', 'tmp', 'heroku_commands'),
|
6
|
+
File.dirname(__FILE__)
|
7
|
+
)
|
8
|
+
|
9
|
+
def initialize(args)
|
10
|
+
@args = args
|
11
|
+
end
|
12
|
+
|
13
|
+
def run!
|
14
|
+
if @args.first == 'help'
|
15
|
+
puts 'pipelines # manage collections of apps in pipelines'
|
16
|
+
end
|
17
|
+
File.open(RECORDER, 'a') do |file|
|
18
|
+
file.puts @args.join(' ')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.clear!
|
23
|
+
FileUtils.rm_rf RECORDER
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.has_gem_included?(project_path, gem_name)
|
27
|
+
gemfile = File.open(File.join(project_path, 'Gemfile'), 'a')
|
28
|
+
|
29
|
+
File.foreach(gemfile).any? do |line|
|
30
|
+
line.match(/#{Regexp.quote(gem_name)}/)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.has_created_app_for?(environment, flags = nil)
|
35
|
+
app_name = "#{UnderlayTestHelpers::APP_NAME.dasherize}-#{environment}"
|
36
|
+
|
37
|
+
command = if flags
|
38
|
+
"create #{app_name} #{flags} --remote #{environment}\n"
|
39
|
+
else
|
40
|
+
"create #{app_name} --remote #{environment}\n"
|
41
|
+
end
|
42
|
+
|
43
|
+
File.foreach(RECORDER).any? { |line| line == command }
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.has_configured_vars?(remote_name, var)
|
47
|
+
commands_ran =~ /^config:add #{var}=.+ --remote #{remote_name}\n/
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.has_setup_pipeline_for?(app_name)
|
51
|
+
commands_ran =~ /^pipelines:create #{app_name} -a #{app_name}-staging --stage staging/ &&
|
52
|
+
commands_ran =~ /^pipelines:add #{app_name} -a #{app_name}-production --stage production/
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.commands_ran
|
56
|
+
@commands_ran ||= File.read(RECORDER)
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module UnderlayTestHelpers
|
4
|
+
APP_NAME = 'dummy_app'
|
5
|
+
|
6
|
+
def remove_project_directory
|
7
|
+
FileUtils.rm_rf(project_path)
|
8
|
+
end
|
9
|
+
|
10
|
+
def create_tmp_directory
|
11
|
+
FileUtils.mkdir_p(tmp_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
def run_underlay(arguments = nil)
|
15
|
+
arguments = "--path=#{root_path} #{arguments}"
|
16
|
+
Dir.chdir(tmp_path) do
|
17
|
+
Bundler.with_clean_env do
|
18
|
+
add_fakes_to_path
|
19
|
+
`
|
20
|
+
#{underlay_bin} #{APP_NAME} #{arguments}
|
21
|
+
`
|
22
|
+
Dir.chdir(APP_NAME) do
|
23
|
+
with_env('HOME', tmp_path) do
|
24
|
+
`git add .`
|
25
|
+
`git commit -m 'Initial commit'`
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def underlay_help_command
|
33
|
+
Dir.chdir(tmp_path) do
|
34
|
+
Bundler.with_clean_env do
|
35
|
+
`
|
36
|
+
#{underlay_bin} -h
|
37
|
+
`
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def setup_app_dependencies
|
43
|
+
if File.exist?(project_path)
|
44
|
+
Dir.chdir(project_path) do
|
45
|
+
Bundler.with_clean_env do
|
46
|
+
`bundle check || bundle install`
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def drop_dummy_database
|
53
|
+
if File.exist?(project_path)
|
54
|
+
Dir.chdir(project_path) do
|
55
|
+
Bundler.with_clean_env do
|
56
|
+
`rails db:drop`
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_fakes_to_path
|
63
|
+
ENV['PATH'] = "#{support_bin}:#{ENV['PATH']}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def project_path
|
67
|
+
@project_path ||= Pathname.new("#{tmp_path}/#{APP_NAME}")
|
68
|
+
end
|
69
|
+
|
70
|
+
def usage_file
|
71
|
+
@usage_file ||= File.join(root_path, 'USAGE')
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def tmp_path
|
77
|
+
@tmp_path ||= Pathname.new("#{root_path}/tmp")
|
78
|
+
end
|
79
|
+
|
80
|
+
def underlay_bin
|
81
|
+
File.join(root_path, 'bin', 'underlay')
|
82
|
+
end
|
83
|
+
|
84
|
+
def support_bin
|
85
|
+
File.join(root_path, 'spec', 'fakes', 'bin')
|
86
|
+
end
|
87
|
+
|
88
|
+
def root_path
|
89
|
+
File.expand_path('../..', __dir__)
|
90
|
+
end
|
91
|
+
|
92
|
+
def with_env(name, new_value)
|
93
|
+
prior = ENV[name]
|
94
|
+
ENV[name] = new_value.to_s
|
95
|
+
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
ENV[name] = prior
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
git_source(:github) do |repo_name|
|
6
|
+
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?('/')
|
7
|
+
"https://github.com/#{repo_name}.git"
|
8
|
+
end
|
9
|
+
|
10
|
+
ruby '<%= Underlay::RUBY_VERSION %>'
|
11
|
+
|
12
|
+
<% unless options[:api] -%>
|
13
|
+
gem 'autoprefixer-rails'
|
14
|
+
gem 'flutie'
|
15
|
+
gem 'jquery-rails'
|
16
|
+
gem 'sass-rails', '~> 5.0'
|
17
|
+
gem 'simple_form'
|
18
|
+
gem 'slim'
|
19
|
+
gem 'sprockets', '>= 3.0.0'
|
20
|
+
gem 'uglifier'
|
21
|
+
<% end -%>
|
22
|
+
gem 'figaro'
|
23
|
+
gem 'lograge'
|
24
|
+
gem 'pg'
|
25
|
+
gem 'puma'
|
26
|
+
gem 'rack-canonical-host'
|
27
|
+
gem 'rails', '<%= Underlay::RAILS_VERSION %>'
|
28
|
+
gem 'recipient_interceptor'
|
29
|
+
gem 'sentry-raven'
|
30
|
+
gem 'sidekiq'
|
31
|
+
gem 'skylight'
|
32
|
+
<% if options[:twilio_base] -%>
|
33
|
+
gem 'twilio_base', '~> 0.3.7', git: 'https://github.com/DVELP/twilio_base'
|
34
|
+
<% end -%>
|
35
|
+
<% if options[:webpack] %>
|
36
|
+
gem 'webpacker'
|
37
|
+
<% end -%>
|
38
|
+
|
39
|
+
group :development do
|
40
|
+
gem 'listen'
|
41
|
+
gem 'rack-mini-profiler', require: false
|
42
|
+
gem 'spring'
|
43
|
+
gem 'spring-commands-rspec'
|
44
|
+
<% unless options[:api] -%>
|
45
|
+
gem 'web-console'
|
46
|
+
<% end -%>
|
47
|
+
end
|
48
|
+
|
49
|
+
group :development, :test do
|
50
|
+
gem 'awesome_print'
|
51
|
+
gem 'bullet'
|
52
|
+
gem 'bundler-audit', '>= 0.5.0', require: false
|
53
|
+
gem 'factory_bot_rails'
|
54
|
+
gem 'pry-byebug'
|
55
|
+
gem 'pry-rails'
|
56
|
+
gem 'rspec-rails', '~> 3.6'
|
57
|
+
gem 'rubocop', require: false
|
58
|
+
<% unless options[:api] -%>
|
59
|
+
gem 'scss_lint', require: false
|
60
|
+
gem 'slim_lint', require: false
|
61
|
+
<% end -%>
|
62
|
+
end
|
63
|
+
|
64
|
+
group :test do
|
65
|
+
<% unless options[:api] %>
|
66
|
+
gem 'capybara'
|
67
|
+
gem 'formulaic'
|
68
|
+
gem 'phantomjs'
|
69
|
+
gem 'poltergeist'
|
70
|
+
<% end -%>
|
71
|
+
gem 'database_cleaner'
|
72
|
+
gem 'launchy'
|
73
|
+
gem 'shoulda-matchers'
|
74
|
+
gem 'simplecov', require: false
|
75
|
+
gem 'timecop'
|
76
|
+
gem 'webmock'
|
77
|
+
end
|
78
|
+
|
79
|
+
group :production do
|
80
|
+
gem 'rack-timeout'
|
81
|
+
end
|
data/templates/Procfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# <%= app_name.humanize %>
|
2
|
+
|
3
|
+
## Getting Started
|
4
|
+
Run the setup script to install dependencies and get the app running on your machine
|
5
|
+
:
|
6
|
+
% ./bin/setup
|
7
|
+
|
8
|
+
After setting up, you can run the application using [Heroku Local]:
|
9
|
+
|
10
|
+
% heroku local
|
11
|
+
|
12
|
+
Learn more about [Heroku Local](https://devcenter.heroku.com/articles/heroku-local)
|
13
|
+
|
14
|
+
## Guidelines
|
15
|
+
Use the following guide for programming well, programming in style and getting things done:
|
16
|
+
|
17
|
+
* [DVELP Cookbook](https://github.com/DVELP/cookbook)
|
18
|
+
|
19
|
+
## Specs & Linting
|
20
|
+
CI is setup to run both linting and rspec. To avoid unnecessary delay with code
|
21
|
+
reviews ensure you run `bin/rake` before raising a pull request.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- if ENV['GOOGLE_TAG_ID']
|
2
|
+
/! Google Tag Manager (noscript)
|
3
|
+
noscript
|
4
|
+
iframe{
|
5
|
+
src="https://www.googletagmanager.com/ns.html?id=#{ENV['GOOGLE_TAG_ID'}"
|
6
|
+
height="0"
|
7
|
+
width="0"
|
8
|
+
style="display:none;visibility:hidden"
|
9
|
+
}
|
10
|
+
/! End Google Tag Manager (noscript)
|
@@ -0,0 +1,8 @@
|
|
1
|
+
- if user_facing_flashes.any?
|
2
|
+
.notification-wrap
|
3
|
+
- user_facing_flashes.each do |alert_type, msg|
|
4
|
+
.notification class=(alert_type + ' js-flash-alert')
|
5
|
+
.notification-body
|
6
|
+
= msg
|
7
|
+
= link_to(sprite_tag('cross', class: 'svgIcon'), '#',
|
8
|
+
class: 'notification-close js-flash-alert-close')
|
@@ -0,0 +1,21 @@
|
|
1
|
+
.flash-alert {
|
2
|
+
border-radius: 5px;
|
3
|
+
height: 60px;
|
4
|
+
margin: rem-calc(20 0);
|
5
|
+
position: relative;
|
6
|
+
transition: height 0.8s ease, opacity 0.4s ease;
|
7
|
+
}
|
8
|
+
.flash-alert.is-transparent {
|
9
|
+
height: 0;
|
10
|
+
margin: 0;
|
11
|
+
opacity: 0;
|
12
|
+
}
|
13
|
+
.flash-alert p {
|
14
|
+
padding: rem-calc(20);
|
15
|
+
}
|
16
|
+
.flash-alert-close {
|
17
|
+
cursor: pointer;
|
18
|
+
position: absolute;
|
19
|
+
right: rem-calc(35);
|
20
|
+
top: rem-calc(20);
|
21
|
+
}
|