suspenders 1.53.0 → 1.54.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +4 -3
- data/CONTRIBUTING.md +15 -15
- data/GOALS.md +65 -0
- data/NEWS.md +29 -0
- data/README.md +2 -4
- data/docs/heroku_deploy.md +2 -5
- data/lib/suspenders.rb +6 -0
- data/lib/suspenders/actions.rb +2 -2
- data/lib/suspenders/adapters/heroku.rb +14 -1
- data/lib/suspenders/app_builder.rb +3 -71
- data/lib/suspenders/generators/advisories_generator.rb +19 -0
- data/lib/suspenders/generators/app_generator.rb +7 -33
- data/lib/suspenders/generators/base.rb +39 -0
- data/lib/suspenders/generators/ci_generator.rb +19 -9
- data/lib/suspenders/generators/db_optimizations_generator.rb +3 -15
- data/lib/suspenders/generators/js_driver_generator.rb +1 -2
- data/lib/suspenders/generators/preloader_generator.rb +122 -0
- data/lib/suspenders/generators/production/compression_generator.rb +14 -0
- data/lib/suspenders/generators/production/deployment_generator.rb +1 -12
- data/lib/suspenders/generators/production/email_generator.rb +5 -8
- data/lib/suspenders/generators/production/manifest_generator.rb +1 -0
- data/lib/suspenders/generators/production/single_redirect.rb +15 -0
- data/lib/suspenders/generators/production/timeout_generator.rb +1 -0
- data/lib/suspenders/generators/profiler_generator.rb +35 -0
- data/lib/suspenders/generators/runner_generator.rb +48 -0
- data/lib/suspenders/generators/staging/pull_requests_generator.rb +2 -10
- data/lib/suspenders/generators/static_generator.rb +4 -0
- data/lib/suspenders/generators/stylesheet_base_generator.rb +5 -6
- data/lib/suspenders/generators/testing_generator.rb +0 -11
- data/lib/suspenders/version.rb +1 -1
- data/spec/adapters/heroku_spec.rb +28 -2
- data/spec/expand_json_spec.rb +89 -0
- data/spec/features/advisories_spec.rb +24 -0
- data/spec/features/ci_spec.rb +31 -0
- data/spec/features/db_optimizations_spec.rb +19 -0
- data/spec/features/heroku_spec.rb +6 -13
- data/spec/features/new_project_spec.rb +5 -27
- data/spec/features/preloader_spec.rb +25 -0
- data/spec/features/production/compression_spec.rb +23 -0
- data/spec/features/production/manifest_spec.rb +2 -0
- data/spec/features/production/single_redirect_spec.rb +25 -0
- data/spec/features/profiler_spec.rb +20 -0
- data/spec/features/runner_spec.rb +30 -0
- data/spec/features/static_spec.rb +17 -0
- data/spec/support/contain_json_matcher.rb +16 -10
- data/spec/support/project_files.rb +12 -0
- data/spec/support/rails_template.rb +1 -0
- data/spec/support/suspenders.rb +16 -13
- data/suspenders.gemspec +1 -2
- data/templates/Gemfile.erb +1 -6
- data/templates/application.scss +0 -1
- data/templates/bin_auto_migrate +5 -0
- data/templates/bin_deploy +0 -2
- data/templates/bin_setup +2 -2
- data/templates/bin_setup_review_app.erb +0 -1
- data/templates/chromedriver.rb +10 -0
- data/templates/descriptions/advisories.md +5 -0
- data/templates/descriptions/analytics.md +4 -0
- data/templates/descriptions/ci.md +4 -0
- data/templates/descriptions/compression.md +4 -0
- data/templates/descriptions/db_optimizations.md +2 -0
- data/templates/descriptions/deployment.md +5 -0
- data/templates/descriptions/email.md +9 -0
- data/templates/descriptions/factories.md +12 -0
- data/templates/descriptions/force_tls.md +1 -0
- data/templates/descriptions/forms.md +1 -0
- data/templates/descriptions/inline_svg.md +2 -0
- data/templates/descriptions/jobs.md +3 -0
- data/templates/descriptions/js_driver.md +4 -0
- data/templates/descriptions/json.md +1 -0
- data/templates/descriptions/lint.md +3 -0
- data/templates/descriptions/manifest.md +2 -0
- data/templates/descriptions/preloader.md +3 -0
- data/templates/descriptions/profiler.md +7 -0
- data/templates/descriptions/pull_requests.md +4 -0
- data/templates/descriptions/runner.md +10 -0
- data/templates/descriptions/single_redirect.md +1 -0
- data/templates/descriptions/static.md +5 -0
- data/templates/descriptions/stylelint.md +3 -0
- data/templates/descriptions/stylesheet_base.md +4 -0
- data/templates/descriptions/testing.md +9 -0
- data/templates/descriptions/timeout.md +4 -0
- data/templates/descriptions/views.md +8 -0
- data/templates/partials/ci_simplecov.rb +16 -0
- data/templates/partials/db_optimizations_configuration.rb +7 -0
- data/templates/partials/deployment_readme.md +8 -0
- data/templates/partials/email_smtp.rb +3 -0
- data/templates/partials/profiler_readme.md +8 -0
- data/templates/partials/pull_requests_config.rb +5 -0
- data/templates/partials/runner_readme.md +31 -0
- data/templates/partials/runner_setup.rb +3 -0
- data/templates/rack_mini_profiler.rb +2 -0
- data/templates/rails_helper.rb +4 -1
- data/templates/{dotfiles/.env → sample_env} +0 -1
- data/templates/spec_helper.rb +4 -7
- data/templates/spring.rb +6 -0
- data/templates/suspenders_gitignore +1 -1
- metadata +75 -25
- data/templates/dotfiles/.ctags +0 -2
- data/templates/puma.rb +0 -28
@@ -8,6 +8,7 @@ RSpec.describe "suspenders:production:manifest", type: :generator do
|
|
8
8
|
name: SuspendersTestHelpers::APP_NAME.dasherize,
|
9
9
|
env: {
|
10
10
|
APPLICATION_HOST: { required: true },
|
11
|
+
AUTO_MIGRATE_DB: { value: true },
|
11
12
|
EMAIL_RECIPIENTS: { required: true },
|
12
13
|
HEROKU_APP_NAME: { required: true },
|
13
14
|
HEROKU_PARENT_APP_NAME: { required: true },
|
@@ -24,6 +25,7 @@ RSpec.describe "suspenders:production:manifest", type: :generator do
|
|
24
25
|
name: SuspendersTestHelpers::APP_NAME.dasherize,
|
25
26
|
env: {
|
26
27
|
APPLICATION_HOST: { required: true },
|
28
|
+
AUTO_MIGRATE_DB: { value: true },
|
27
29
|
EMAIL_RECIPIENTS: { required: true },
|
28
30
|
HEROKU_APP_NAME: { required: true },
|
29
31
|
HEROKU_PARENT_APP_NAME: { required: true },
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:production:single_redirect", type: :generator do
|
4
|
+
context "generate" do
|
5
|
+
it "adds Rack::CanonicalHost to the production middleware" do
|
6
|
+
with_app { generate("suspenders:production:single_redirect") }
|
7
|
+
middleware_canonical_host = %r{config.middleware.use Rack::CanonicalHost, ENV.fetch\("APPLICATION_HOST"\)}
|
8
|
+
|
9
|
+
expect("config/environments/production.rb").to match_contents(
|
10
|
+
middleware_canonical_host,
|
11
|
+
)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "destroy" do
|
16
|
+
it "removes Rack::CanonicalHost from the production middleware" do
|
17
|
+
with_app { destroy("suspenders:production:single_redirect") }
|
18
|
+
middleware_canonical_host = %r{config.middleware.use Rack::CanonicalHost, ENV.fetch\("APPLICATION_HOST"\)}
|
19
|
+
|
20
|
+
expect("config/environments/production.rb").not_to match_contents(
|
21
|
+
middleware_canonical_host,
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:profiler", type: :generator do
|
4
|
+
it "sets up rack-min-profiler" do
|
5
|
+
with_app { generate("suspenders:profiler") }
|
6
|
+
|
7
|
+
expect("config/initializers/rack_mini_profiler.rb").to \
|
8
|
+
match_contents(/Rack::MiniProfilerRails.initialize/)
|
9
|
+
expect("Gemfile").to match_contents(/rack-mini-profiler/)
|
10
|
+
expect(".env").to match_contents(/RACK_MINI_PROFILER=0/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "removes rack-min-profiler" do
|
14
|
+
with_app { destroy("suspenders:profiler") }
|
15
|
+
|
16
|
+
expect("config/initializers/rack_mini_profiler.rb").not_to exist_as_a_file
|
17
|
+
expect("Gemfile").not_to match_contents(/rack-mini-profiler/)
|
18
|
+
expect(".env").not_to exist_as_a_file
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:runner", type: :generator do
|
4
|
+
it "configures the app for running" do
|
5
|
+
with_app { generate("suspenders:runner") }
|
6
|
+
|
7
|
+
expect("Procfile").to exist_as_a_file
|
8
|
+
expect(".sample.env").to exist_as_a_file
|
9
|
+
expect("bin/setup").to match_contents(/\.sample\.env/)
|
10
|
+
expect("README.md").to match_contents(/\.sample\.env/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "removes custom app running configuration" do
|
14
|
+
with_app { destroy("suspenders:runner") }
|
15
|
+
|
16
|
+
expect("README.md").not_to match_contents(/\.sample\.env/)
|
17
|
+
expect("bin/setup").not_to match_contents(/\.sample\.env/)
|
18
|
+
expect(".sample.env").not_to exist_as_a_file
|
19
|
+
expect("Procfile").not_to exist_as_a_file
|
20
|
+
end
|
21
|
+
|
22
|
+
it "configures the app with a shell script bin/setup" do
|
23
|
+
with_app do
|
24
|
+
copy_file "bin_setup", "bin/setup"
|
25
|
+
generate("suspenders:runner")
|
26
|
+
end
|
27
|
+
|
28
|
+
expect("bin/setup").to match_contents(/\.sample\.env/)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:static", type: :generator do
|
4
|
+
it "adds the gem and pages directory" do
|
5
|
+
with_app { generate("suspenders:static") }
|
6
|
+
|
7
|
+
expect("Gemfile").to match_contents(/high_voltage/)
|
8
|
+
expect("app/views/pages/.keep").to exist_as_a_file
|
9
|
+
end
|
10
|
+
|
11
|
+
it "removes the gem and pages directory" do
|
12
|
+
with_app { destroy("suspenders:static") }
|
13
|
+
|
14
|
+
expect("app/views/pages/.keep").not_to exist_as_a_file
|
15
|
+
expect("Gemfile").not_to match_contents(/high_voltage/)
|
16
|
+
end
|
17
|
+
end
|
@@ -4,21 +4,27 @@ require "json"
|
|
4
4
|
|
5
5
|
RSpec::Matchers.define :contain_json do
|
6
6
|
match do
|
7
|
-
sub_json = expected
|
8
|
-
filename = actual
|
7
|
+
@sub_json = expected
|
8
|
+
@filename = actual
|
9
9
|
|
10
|
-
filepath = File.join(project_path, filename)
|
11
|
-
json = JSON.parse(IO.read(filepath), symbolize_names: true)
|
12
|
-
|
10
|
+
@filepath = File.join(project_path, @filename)
|
11
|
+
@json = JSON.parse(IO.read(@filepath), symbolize_names: true)
|
12
|
+
|
13
|
+
subhash?(@sub_json, @json)
|
13
14
|
end
|
14
15
|
|
15
16
|
failure_message do
|
16
|
-
|
17
|
-
|
17
|
+
"in #{@filename}, expected to find\n#{@sub_json.inspect}\n" \
|
18
|
+
"in\n#{@json.inspect}"
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
json = JSON.parse(IO.read(filepath), symbolize_names: true)
|
21
|
+
private
|
21
22
|
|
22
|
-
|
23
|
+
def subhash?(inner, outer)
|
24
|
+
if inner.is_a?(Hash) && outer.is_a?(Hash)
|
25
|
+
inner.all? { |key, value| subhash?(value, outer[key]) }
|
26
|
+
else
|
27
|
+
inner == outer
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
@@ -10,4 +10,16 @@ module ProjectFiles
|
|
10
10
|
path = File.join(project_path, filename)
|
11
11
|
FileUtils.rm_rf(path)
|
12
12
|
end
|
13
|
+
|
14
|
+
def copy_file(from_in_templates, to_in_project)
|
15
|
+
destination = File.join(project_path, to_in_project)
|
16
|
+
destination_dirname = File.dirname(destination)
|
17
|
+
|
18
|
+
FileUtils.mkdir_p(destination_dirname)
|
19
|
+
|
20
|
+
FileUtils.cp(
|
21
|
+
File.join(root_path, "templates", from_in_templates),
|
22
|
+
destination,
|
23
|
+
)
|
24
|
+
end
|
13
25
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
gem "suspenders", path: File.expand_path("../..", __dir__)
|
data/spec/support/suspenders.rb
CHANGED
@@ -19,10 +19,7 @@ module SuspendersTestHelpers
|
|
19
19
|
end
|
20
20
|
|
21
21
|
Dir.chdir(APP_NAME) do
|
22
|
-
|
23
|
-
debug `git add .`
|
24
|
-
debug `git commit -m 'Initial commit'`
|
25
|
-
end
|
22
|
+
commit_all
|
26
23
|
end
|
27
24
|
end
|
28
25
|
end
|
@@ -41,18 +38,11 @@ module SuspendersTestHelpers
|
|
41
38
|
add_fakes_to_path
|
42
39
|
|
43
40
|
with_revision_for_honeybadger do
|
44
|
-
debug `#{system_rails_bin} new #{APP_NAME}`
|
41
|
+
debug `#{system_rails_bin} new #{APP_NAME} -m #{rails_template_path}`
|
45
42
|
end
|
46
43
|
|
47
44
|
Dir.chdir(APP_NAME) do
|
48
|
-
|
49
|
-
file.puts %{gem "suspenders", path: #{root_path.inspect}}
|
50
|
-
end
|
51
|
-
|
52
|
-
with_env("HOME", tmp_path) do
|
53
|
-
debug `git add .`
|
54
|
-
debug `git commit -m 'Initial commit'`
|
55
|
-
end
|
45
|
+
commit_all
|
56
46
|
end
|
57
47
|
end
|
58
48
|
end
|
@@ -135,6 +125,19 @@ module SuspendersTestHelpers
|
|
135
125
|
File.expand_path('../../../', __FILE__)
|
136
126
|
end
|
137
127
|
|
128
|
+
def rails_template_path
|
129
|
+
File.join(root_path, "spec", "support", "rails_template.rb")
|
130
|
+
end
|
131
|
+
|
132
|
+
def commit_all
|
133
|
+
with_env("HOME", tmp_path) do
|
134
|
+
debug `git config user.email suspenders@example.com`
|
135
|
+
debug `git config user.name "Suspenders Boy"`
|
136
|
+
debug `git add .`
|
137
|
+
debug `git commit -m 'Initial commit'`
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
138
141
|
def with_env(name, new_value)
|
139
142
|
had_key = ENV.has_key?(name)
|
140
143
|
prior = ENV[name]
|
data/suspenders.gemspec
CHANGED
@@ -28,9 +28,8 @@ rush to build something amazing; don't use it if you like missing deadlines.
|
|
28
28
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
29
|
s.version = Suspenders::VERSION
|
30
30
|
|
31
|
-
s.add_dependency 'bitters', '
|
31
|
+
s.add_dependency 'bitters', '>= 2.0.4'
|
32
32
|
s.add_dependency 'rails', Suspenders::RAILS_VERSION
|
33
33
|
|
34
34
|
s.add_development_dependency 'rspec', '~> 3.2'
|
35
|
-
s.add_development_dependency 'rack-timeout'
|
36
35
|
end
|
data/templates/Gemfile.erb
CHANGED
@@ -19,22 +19,18 @@ gem "rails", "<%= Suspenders::RAILS_VERSION %>"
|
|
19
19
|
gem "recipient_interceptor"
|
20
20
|
gem "sassc-rails"
|
21
21
|
gem "skylight"
|
22
|
-
gem "sprockets", "
|
22
|
+
gem "sprockets", "< 4"
|
23
23
|
gem "title"
|
24
24
|
gem "tzinfo-data", platforms: [:mingw, :x64_mingw, :mswin, :jruby]
|
25
25
|
gem "webpacker"
|
26
26
|
|
27
27
|
group :development do
|
28
28
|
gem "listen"
|
29
|
-
gem "rack-mini-profiler", require: false
|
30
|
-
gem "spring"
|
31
29
|
gem "web-console"
|
32
30
|
end
|
33
31
|
|
34
32
|
group :development, :test do
|
35
33
|
gem "awesome_print"
|
36
|
-
gem "bundler-audit", ">= 0.5.0", require: false
|
37
|
-
gem "dotenv-rails"
|
38
34
|
gem "pry-byebug"
|
39
35
|
gem "pry-rails"
|
40
36
|
end
|
@@ -42,7 +38,6 @@ end
|
|
42
38
|
group :test do
|
43
39
|
gem "formulaic"
|
44
40
|
gem "launchy"
|
45
|
-
gem "simplecov", require: false
|
46
41
|
gem "timecop"
|
47
42
|
gem "webmock"
|
48
43
|
end
|
data/templates/application.scss
CHANGED
data/templates/bin_deploy
CHANGED
data/templates/bin_setup
CHANGED
@@ -17,6 +17,5 @@ heroku pg:backups:capture --app $PARENT_APP_NAME
|
|
17
17
|
URL=`heroku pg:backups public-url --app $PARENT_APP_NAME`
|
18
18
|
|
19
19
|
heroku pg:backups restore $URL DATABASE_URL --confirm $APP_NAME --app $APP_NAME
|
20
|
-
heroku run rails db:migrate --exit-code --app $APP_NAME
|
21
20
|
heroku ps:scale worker=1 --app $APP_NAME
|
22
21
|
heroku restart --app $APP_NAME
|
data/templates/chromedriver.rb
CHANGED
@@ -15,3 +15,13 @@ Capybara.register_driver :headless_chrome do |app|
|
|
15
15
|
end
|
16
16
|
|
17
17
|
Capybara.javascript_driver = :headless_chrome
|
18
|
+
|
19
|
+
RSpec.configure do |config|
|
20
|
+
config.before(:each, type: :system) do
|
21
|
+
driven_by :rack_test
|
22
|
+
end
|
23
|
+
|
24
|
+
config.before(:each, type: :system, js: true) do
|
25
|
+
driven_by Capybara.javascript_driver
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Build test data with clarity and ease.
|
2
|
+
|
3
|
+
This uses FactoryBot to help you define dummy and test data for your test
|
4
|
+
suite. The `create`, `build`, and `build_stubbed` class methods are directly
|
5
|
+
available to all tests.
|
6
|
+
|
7
|
+
We recommend putting FactoryBot definitions in one `spec/factories.rb` file, at
|
8
|
+
least until it grows unwieldy. This helps reduce confusion around circular
|
9
|
+
dependencies and makes it easy to jump between definitions.
|
10
|
+
|
11
|
+
Outside of the tests, the `dev:prime` rake task can be used to insert initial
|
12
|
+
development data into the database. You can use FactoryBot here, too.
|
@@ -0,0 +1 @@
|
|
1
|
+
Redirect users to the HTTPS URL on the production Web site.
|
@@ -0,0 +1 @@
|
|
1
|
+
Make forms easier to make with form helpers. This mostly involves SimpleForm.
|
@@ -0,0 +1 @@
|
|
1
|
+
Use the fastest JSON parser available.
|
@@ -0,0 +1,7 @@
|
|
1
|
+
Show runtime profiling for your Rails app as you develop it.
|
2
|
+
|
3
|
+
This uses the `rack-mini-profiler` gem to show a speed badge on every page.
|
4
|
+
This is controlled by the `RACK_MINI_PROFILER` environment variable which
|
5
|
+
defaults to `0` in the `.sample.env`. Set it to `1` to enable profiling.
|
6
|
+
|
7
|
+
Updates your README.md to explain this environment variable.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Set up the app to run locally with ease.
|
2
|
+
|
3
|
+
Use Puma and the Rails jobs runner to run the app. This can be done via either
|
4
|
+
`heroku local` or any Foreman-compatible project runner (e.g. `foreman start`).
|
5
|
+
|
6
|
+
Configure your app using `.env`. Installs a basic `.sample.env` that is meant
|
7
|
+
to be checked into git and used as a template for your `.env`. The `bin/setup`
|
8
|
+
script is modified to safely copy `.sample.env` to `.env` for you.
|
9
|
+
|
10
|
+
Document all of this in the README.
|