welaika-suspenders 2.29.0 → 2.30.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 +2 -3
- data/NEWS.md +18 -0
- data/README.md +2 -1
- data/lib/suspenders.rb +4 -0
- data/lib/suspenders/adapters/heroku.rb +13 -27
- data/lib/suspenders/app_builder.rb +2 -29
- data/lib/suspenders/generators/app_generator.rb +10 -16
- data/lib/suspenders/generators/base.rb +20 -0
- data/lib/suspenders/generators/ci_generator.rb +3 -10
- data/lib/suspenders/generators/db_optimizations_generator.rb +2 -2
- data/lib/suspenders/generators/decorator_generator.rb +1 -6
- data/lib/suspenders/generators/factories_generator.rb +2 -7
- data/lib/suspenders/generators/faker_generator.rb +1 -6
- data/lib/suspenders/generators/js_driver_generator.rb +2 -7
- data/lib/suspenders/generators/json_generator.rb +10 -0
- data/lib/suspenders/generators/lint_generator.rb +2 -7
- data/lib/suspenders/generators/production/deployment_generator.rb +27 -0
- data/lib/suspenders/generators/production/email_generator.rb +3 -11
- data/lib/suspenders/generators/production/error_reporting_generator.rb +1 -8
- data/lib/suspenders/generators/production/force_tls_generator.rb +2 -5
- data/lib/suspenders/generators/production/manifest_generator.rb +24 -0
- data/lib/suspenders/generators/production/timeout_generator.rb +2 -2
- data/lib/suspenders/generators/security_generator.rb +1 -6
- data/lib/suspenders/generators/staging/pull_requests_generator.rb +33 -0
- data/lib/suspenders/generators/static_generator.rb +2 -2
- data/lib/suspenders/generators/stylesheet_base_generator.rb +2 -6
- data/lib/suspenders/generators/testing_generator.rb +2 -7
- data/lib/suspenders/generators/views_generator.rb +2 -7
- data/lib/suspenders/version.rb +2 -2
- data/spec/adapters/heroku_spec.rb +2 -2
- data/spec/features/heroku_spec.rb +22 -6
- data/spec/features/json_spec.rb +15 -0
- data/spec/features/new_project_spec.rb +13 -8
- data/spec/features/production/deployment_spec.rb +22 -0
- data/spec/features/production/email_spec.rb +1 -1
- data/spec/features/production/manifest_spec.rb +35 -0
- data/spec/features/staging/pull_requests_spec.rb +22 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/be_executable_matcher.rb +7 -0
- data/spec/support/generators.rb +5 -0
- data/spec/support/project_files.rb +13 -0
- data/suspenders.gemspec +2 -0
- data/templates/Gemfile.erb +3 -5
- data/templates/_flashes.html.slim +1 -1
- data/templates/factory_bot_rspec.rb +2 -0
- data/templates/gitlab-ci.yml.erb +13 -16
- data/templates/overcommit.yml +1 -1
- data/templates/suspenders_gitignore +3 -0
- data/templates/suspenders_layout.html.slim +2 -3
- metadata +53 -9
- data/templates/app.json.erb +0 -27
- data/templates/browserslist +0 -3
@@ -1,16 +1,8 @@
|
|
1
|
-
|
2
|
-
require_relative "../../actions"
|
1
|
+
require_relative "../base"
|
3
2
|
|
4
3
|
module Suspenders
|
5
4
|
module Production
|
6
|
-
class EmailGenerator <
|
7
|
-
include Suspenders::Actions
|
8
|
-
|
9
|
-
source_root File.expand_path(
|
10
|
-
File.join("..", "..", "..", "..", "templates"),
|
11
|
-
File.dirname(__FILE__),
|
12
|
-
)
|
13
|
-
|
5
|
+
class EmailGenerator < Generators::Base
|
14
6
|
def smtp_configuration
|
15
7
|
copy_file "smtp.rb", "config/smtp.rb"
|
16
8
|
|
@@ -26,7 +18,7 @@ module Suspenders
|
|
26
18
|
RUBY
|
27
19
|
|
28
20
|
inject_into_file "config/environments/production.rb", config,
|
29
|
-
after: "config.action_mailer.
|
21
|
+
after: "config.action_mailer.perform_caching = false"
|
30
22
|
end
|
31
23
|
|
32
24
|
def env_vars
|
@@ -3,14 +3,7 @@ require_relative "../../actions"
|
|
3
3
|
|
4
4
|
module Suspenders
|
5
5
|
module Production
|
6
|
-
class ErrorReportingGenerator <
|
7
|
-
include Suspenders::Actions
|
8
|
-
|
9
|
-
source_root File.expand_path(
|
10
|
-
File.join("..", "..", "..", "..", "templates"),
|
11
|
-
File.dirname(__FILE__),
|
12
|
-
)
|
13
|
-
|
6
|
+
class ErrorReportingGenerator < Generators::Base
|
14
7
|
def add_sentry
|
15
8
|
gem "sentry-raven"
|
16
9
|
Bundler.with_clean_env { run "bundle install" }
|
@@ -1,11 +1,8 @@
|
|
1
|
-
|
2
|
-
require_relative "../../actions"
|
1
|
+
require_relative "../base"
|
3
2
|
|
4
3
|
module Suspenders
|
5
4
|
module Production
|
6
|
-
class ForceTlsGenerator <
|
7
|
-
include Suspenders::Actions
|
8
|
-
|
5
|
+
class ForceTlsGenerator < Generators::Base
|
9
6
|
def config_enforce_ssl
|
10
7
|
configure_environment "production", "config.force_ssl = true"
|
11
8
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Suspenders
|
4
|
+
module Production
|
5
|
+
class ManifestGenerator < Generators::Base
|
6
|
+
def render_manifest
|
7
|
+
expand_json(
|
8
|
+
"app.json",
|
9
|
+
name: app_name.dasherize,
|
10
|
+
scripts: {},
|
11
|
+
env: {
|
12
|
+
APPLICATION_HOST: { required: true },
|
13
|
+
EMAIL_RECIPIENTS: { required: true },
|
14
|
+
HEROKU_APP_NAME: { required: true },
|
15
|
+
HEROKU_PARENT_APP_NAME: { required: true },
|
16
|
+
RACK_ENV: { required: true },
|
17
|
+
SECRET_KEY_BASE: { generator: "secret" },
|
18
|
+
},
|
19
|
+
addons: ["heroku-postgresql"],
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,12 +1,7 @@
|
|
1
1
|
require "rails/generators"
|
2
2
|
|
3
3
|
module Suspenders
|
4
|
-
class SecurityGenerator <
|
5
|
-
source_root File.expand_path(
|
6
|
-
File.join("..", "..", "..", "templates"),
|
7
|
-
File.dirname(__FILE__),
|
8
|
-
)
|
9
|
-
|
4
|
+
class SecurityGenerator < Generators::Base
|
10
5
|
def add_checkers_gems
|
11
6
|
gem 'brakeman', require: false, group: :development
|
12
7
|
gem 'bundler-audit', '>= 0.5.0', require: false, group: :development
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Suspenders
|
4
|
+
module Staging
|
5
|
+
class PullRequestsGenerator < Generators::Base
|
6
|
+
def configure_heroku_staging_pr_pipeline_host
|
7
|
+
config = <<-RUBY
|
8
|
+
|
9
|
+
if ENV.fetch("HEROKU_APP_NAME", "").include?("staging-pr-")
|
10
|
+
ENV["APPLICATION_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com"
|
11
|
+
ENV["ASSET_HOST"] = ENV["HEROKU_APP_NAME"] + ".herokuapp.com"
|
12
|
+
end
|
13
|
+
RUBY
|
14
|
+
|
15
|
+
inject_into_file(
|
16
|
+
"config/environments/production.rb",
|
17
|
+
config,
|
18
|
+
after: "Rails.application.configure do\n",
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_review_apps_setup_script
|
23
|
+
template(
|
24
|
+
"bin_setup_review_app.erb",
|
25
|
+
"bin/setup_review_app",
|
26
|
+
force: true,
|
27
|
+
)
|
28
|
+
|
29
|
+
run "chmod a+x bin/setup_review_app"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,11 +1,7 @@
|
|
1
|
-
|
1
|
+
require_relative "base"
|
2
2
|
|
3
3
|
module Suspenders
|
4
|
-
class StylesheetBaseGenerator <
|
5
|
-
source_root File.expand_path(
|
6
|
-
File.join("..", "..", "..", "templates"),
|
7
|
-
File.dirname(__FILE__))
|
8
|
-
|
4
|
+
class StylesheetBaseGenerator < Generators::Base
|
9
5
|
def add_css_config
|
10
6
|
copy_file(
|
11
7
|
"application.sass",
|
@@ -1,12 +1,7 @@
|
|
1
|
-
|
1
|
+
require_relative "base"
|
2
2
|
|
3
3
|
module Suspenders
|
4
|
-
class TestingGenerator <
|
5
|
-
source_root File.expand_path(
|
6
|
-
File.join("..", "..", "..", "templates"),
|
7
|
-
File.dirname(__FILE__),
|
8
|
-
)
|
9
|
-
|
4
|
+
class TestingGenerator < Generators::Base
|
10
5
|
def add_testing_gems
|
11
6
|
gem "rspec-rails", "~> 3.8", group: %i(development test)
|
12
7
|
gem "shoulda-matchers", group: :test
|
@@ -1,12 +1,7 @@
|
|
1
|
-
|
1
|
+
require_relative "base"
|
2
2
|
|
3
3
|
module Suspenders
|
4
|
-
class ViewsGenerator <
|
5
|
-
source_root File.expand_path(
|
6
|
-
File.join("..", "..", "..", "templates"),
|
7
|
-
File.dirname(__FILE__),
|
8
|
-
)
|
9
|
-
|
4
|
+
class ViewsGenerator < Generators::Base
|
10
5
|
def add_slim_gem
|
11
6
|
gem "slim-rails"
|
12
7
|
Bundler.with_clean_env { run "bundle install" }
|
data/lib/suspenders/version.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Suspenders
|
2
|
-
RAILS_VERSION = "~> 5.2.
|
2
|
+
RAILS_VERSION = "~> 5.2.2".freeze
|
3
3
|
POSTGRES_VERSION = "10.4".freeze # Used in CI
|
4
4
|
RUBY_VERSION = IO.
|
5
5
|
read("#{File.dirname(__FILE__)}/../../.ruby-version").
|
6
6
|
strip.
|
7
7
|
freeze
|
8
|
-
VERSION = "2.
|
8
|
+
VERSION = "2.30.0".freeze
|
9
9
|
end
|
@@ -11,9 +11,9 @@ module Suspenders
|
|
11
11
|
Heroku.new(app_builder).set_heroku_remotes
|
12
12
|
|
13
13
|
expect(app_builder).to have_received(:append_file).
|
14
|
-
with(setup_file, /git remote add -f production
|
14
|
+
with(setup_file, /git remote add -f production git@heroku\.com:#{app_name.dasherize}-production\.git/)
|
15
15
|
expect(app_builder).to have_received(:append_file).
|
16
|
-
with(setup_file, /git remote add -f staging
|
16
|
+
with(setup_file, /git remote add -f staging git@heroku\.com:#{app_name.dasherize}-staging\.git/)
|
17
17
|
end
|
18
18
|
|
19
19
|
it "sets the heroku rails secrets" do
|
@@ -7,26 +7,29 @@ RSpec.describe "Heroku" do
|
|
7
7
|
run_suspenders("--heroku=true")
|
8
8
|
setup_app_dependencies
|
9
9
|
end
|
10
|
+
let(:app_name) { SuspendersTestHelpers::APP_NAME.dasherize }
|
10
11
|
|
11
12
|
it "suspends a project for Heroku" do
|
12
|
-
app_name = SuspendersTestHelpers::APP_NAME.dasherize
|
13
|
-
|
14
13
|
expect(FakeHeroku).to have_created_app_for("staging", "--region eu")
|
15
14
|
expect(FakeHeroku).to have_created_app_for("production", "--region eu")
|
16
15
|
%w(staging production).each do |env|
|
17
16
|
expect(FakeHeroku).to have_configured_vars(env, "APPLICATION_HOST")
|
18
17
|
expect(FakeHeroku).to have_configured_vars(env, "SENTRY_DSN")
|
19
|
-
expect(FakeHeroku).to have_configured_vars(env, "
|
18
|
+
expect(FakeHeroku).to have_configured_vars(env, "SENTRY_ENV")
|
19
|
+
expect(FakeHeroku).to have_configured_vars(env, "SMTP_ADDRESS")
|
20
|
+
expect(FakeHeroku).to have_configured_vars(env, "SMTP_DOMAIN")
|
21
|
+
expect(FakeHeroku).to have_configured_vars(env, "SMTP_PASSWORD")
|
22
|
+
expect(FakeHeroku).to have_configured_vars(env, "SMTP_USERNAME")
|
20
23
|
end
|
21
24
|
expect(FakeHeroku).to have_setup_pipeline_for(app_name)
|
22
25
|
|
23
26
|
bin_setup_path = "#{project_path}/bin/setup"
|
24
27
|
bin_setup = IO.read(bin_setup_path)
|
25
28
|
|
26
|
-
expect(bin_setup).to match(/^if heroku
|
27
|
-
expect(bin_setup).to match(/^if heroku
|
29
|
+
expect(bin_setup).to match(/^if heroku apps | grep #{app_name}-production/)
|
30
|
+
expect(bin_setup).to match(/^if heroku apps | grep #{app_name}-staging/)
|
28
31
|
expect(bin_setup).to match(/^git config heroku.remote staging/)
|
29
|
-
expect(
|
32
|
+
expect("bin/setup").to be_executable
|
30
33
|
|
31
34
|
readme = IO.read("#{project_path}/README.md")
|
32
35
|
|
@@ -35,6 +38,19 @@ RSpec.describe "Heroku" do
|
|
35
38
|
end
|
36
39
|
end
|
37
40
|
|
41
|
+
context "--heroku with region flag" do
|
42
|
+
before(:all) do
|
43
|
+
clean_up
|
44
|
+
run_suspenders(%{--heroku=true --heroku-flags="--region eu"})
|
45
|
+
setup_app_dependencies
|
46
|
+
end
|
47
|
+
|
48
|
+
it "suspends a project with extra Heroku flags" do
|
49
|
+
expect(FakeHeroku).to have_created_app_for("staging", "--region eu")
|
50
|
+
expect(FakeHeroku).to have_created_app_for("production", "--region eu")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
38
54
|
def clean_up
|
39
55
|
drop_dummy_database
|
40
56
|
remove_project_directory
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:json", type: :generator do
|
4
|
+
it "generates the Gemfile for JSON parsing" do
|
5
|
+
with_app { generate("suspenders:json") }
|
6
|
+
|
7
|
+
expect("Gemfile").to match_contents(%r{gem .oj.})
|
8
|
+
end
|
9
|
+
|
10
|
+
it "cleans up the Gemfile from JSON parsing" do
|
11
|
+
with_app { destroy("suspenders:json") }
|
12
|
+
|
13
|
+
expect("Gemfile").not_to match_contents(%r{gem .oj.})
|
14
|
+
end
|
15
|
+
end
|
@@ -14,7 +14,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
14
14
|
/^ruby '#{Suspenders::RUBY_VERSION}'$/,
|
15
15
|
)
|
16
16
|
expect(gemfile_file).to match(
|
17
|
-
/^gem '
|
17
|
+
/^gem 'active_interaction'/,
|
18
18
|
)
|
19
19
|
expect(gemfile_file).to match(
|
20
20
|
/^gem 'rails', '#{Suspenders::RAILS_VERSION}'$/,
|
@@ -57,9 +57,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
57
57
|
end
|
58
58
|
|
59
59
|
it "makes bin/setup executable" do
|
60
|
-
|
61
|
-
|
62
|
-
expect(File.stat(bin_setup_path)).to be_executable
|
60
|
+
expect("bin/setup").to be_executable
|
63
61
|
end
|
64
62
|
|
65
63
|
it "adds support file for action mailer" do
|
@@ -213,8 +211,9 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
213
211
|
]
|
214
212
|
|
215
213
|
config_files.each do |file|
|
216
|
-
expect(file).not_to match(
|
217
|
-
expect(file).not_to
|
214
|
+
expect(file).not_to match(%r{.*#.*})
|
215
|
+
expect(file).not_to eq(file.strip)
|
216
|
+
expect(file).not_to match(%r{^$\n\n})
|
218
217
|
end
|
219
218
|
end
|
220
219
|
|
@@ -229,7 +228,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
229
228
|
expect(bin_setup).to include("heroku ps:scale worker=1 --app $APP_NAME")
|
230
229
|
expect(bin_setup).to include("heroku restart --app $APP_NAME")
|
231
230
|
|
232
|
-
expect(
|
231
|
+
expect("bin/setup_review_app").to be_executable
|
233
232
|
end
|
234
233
|
|
235
234
|
it "creates deploy script" do
|
@@ -237,7 +236,7 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
237
236
|
bin_deploy = IO.read(bin_deploy_path)
|
238
237
|
|
239
238
|
expect(bin_deploy).to include("heroku run rails db:migrate --exit-code")
|
240
|
-
expect(
|
239
|
+
expect("bin/deploy").to be_executable
|
241
240
|
end
|
242
241
|
|
243
242
|
it "creates heroku application manifest file with application name in it" do
|
@@ -255,6 +254,12 @@ RSpec.describe "Suspend a new project with default configuration" do
|
|
255
254
|
expect(gemfile).to match(/high_voltage/)
|
256
255
|
end
|
257
256
|
|
257
|
+
it "adds sassc-rails" do
|
258
|
+
gemfile = read_project_file("Gemfile")
|
259
|
+
|
260
|
+
expect(gemfile).to match(/sassc-rails/)
|
261
|
+
end
|
262
|
+
|
258
263
|
it "doesn't use turbolinks" do
|
259
264
|
app_js = read_project_file(%w(app assets javascripts application.js))
|
260
265
|
expect(app_js).not_to match(/turbolinks/)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:production:deployment", type: :generator do
|
4
|
+
it "generates the configuration for a production deployment" do
|
5
|
+
rm "bin/deploy"
|
6
|
+
|
7
|
+
with_app { generate("suspenders:production:deployment") }
|
8
|
+
|
9
|
+
expect("bin/deploy").to exist_as_a_file
|
10
|
+
expect("bin/deploy").to be_executable
|
11
|
+
expect("README.md").to match_contents(%r{bin/deploy})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "destroys the configuration for a production deployment" do
|
15
|
+
touch "bin/deploy"
|
16
|
+
|
17
|
+
with_app { destroy("suspenders:production:deployment") }
|
18
|
+
|
19
|
+
expect("bin/deploy").not_to exist_as_a_file
|
20
|
+
expect("README.md").not_to match_contents(%r{bin/deploy})
|
21
|
+
end
|
22
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
RSpec.describe "suspenders:production:email" do
|
3
|
+
RSpec.describe "suspenders:production:email", type: :generator do
|
4
4
|
it "generates the configuration for a production email deployment" do
|
5
5
|
with_app { generate("suspenders:production:email") }
|
6
6
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:production:manifest", type: :generator do
|
4
|
+
it "generates the manifest for a production build" do
|
5
|
+
with_app { generate("suspenders:production:manifest") }
|
6
|
+
|
7
|
+
expect("app.json").to contain_json(
|
8
|
+
name: SuspendersTestHelpers::APP_NAME.dasherize,
|
9
|
+
env: {
|
10
|
+
APPLICATION_HOST: { required: true },
|
11
|
+
EMAIL_RECIPIENTS: { required: true },
|
12
|
+
HEROKU_APP_NAME: { required: true },
|
13
|
+
HEROKU_PARENT_APP_NAME: { required: true },
|
14
|
+
RACK_ENV: { required: true },
|
15
|
+
SECRET_KEY_BASE: { generator: "secret" },
|
16
|
+
},
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "destroys the manifest for a production build" do
|
21
|
+
with_app { destroy("suspenders:production:manifest") }
|
22
|
+
|
23
|
+
expect("app.json").not_to contain_json(
|
24
|
+
name: SuspendersTestHelpers::APP_NAME.dasherize,
|
25
|
+
env: {
|
26
|
+
APPLICATION_HOST: { required: true },
|
27
|
+
EMAIL_RECIPIENTS: { required: true },
|
28
|
+
HEROKU_APP_NAME: { required: true },
|
29
|
+
HEROKU_PARENT_APP_NAME: { required: true },
|
30
|
+
RACK_ENV: { required: true },
|
31
|
+
SECRET_KEY_BASE: { generator: "secret" },
|
32
|
+
},
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "suspenders:staging:pull_requests", type: :generators do
|
4
|
+
it "generates the configuration for Heroku pipeline review apps" do
|
5
|
+
with_app { generate("suspenders:staging:pull_requests") }
|
6
|
+
|
7
|
+
expect("config/environments/production.rb").to \
|
8
|
+
match_contents(%r{HEROKU_APP_NAME})
|
9
|
+
|
10
|
+
expect("bin/setup_review_app").to \
|
11
|
+
match_contents(%r{APP_NAME=dummy-app-staging-pr-\$1})
|
12
|
+
end
|
13
|
+
|
14
|
+
it "destroys the configuration for Heroku pipeline review apps" do
|
15
|
+
with_app { destroy("suspenders:staging:pull_requests") }
|
16
|
+
|
17
|
+
expect("config/environments/production.rb").not_to \
|
18
|
+
match_contents(%r{APP_NAME=dummy-app-staging-pr-\$1})
|
19
|
+
|
20
|
+
expect("bin/setup_review_app").not_to exist_as_a_file
|
21
|
+
end
|
22
|
+
end
|