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,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_job/logging'
4
+
5
+ ActiveSupport::Notifications.unsubscribe('enqueue.active_job')
6
+
7
+ module ActiveJob
8
+ module Logging
9
+ class EnqueueLogSubscriber < LogSubscriber
10
+ define_method :enqueue, instance_method(:enqueue)
11
+ end
12
+ end
13
+ end
14
+
15
+ ActiveJob::Logging::EnqueueLogSubscriber.attach_to(:active_job)
@@ -0,0 +1,45 @@
1
+ {
2
+ "name":"<%= app_name.dasherize %>",
3
+ "scripts":{},
4
+ "env":{
5
+ "APPLICATION_HOST":{
6
+ "required":true
7
+ },
8
+ "CAPYBARA_ASSET_HOST":{
9
+ "required":true
10
+ },
11
+ "EMAIL_RECIPIENTS":{
12
+ "required":true
13
+ },
14
+ "GOOGLE_TAG_ID":{
15
+ "required":true
16
+ },
17
+ "HEROKU_APP_NAME": {
18
+ "required":true
19
+ },
20
+ "HEROKU_PARENT_APP_NAME": {
21
+ "required":true
22
+ },
23
+ "RACK_ENV":{
24
+ "required":true
25
+ },
26
+ "SECRET_KEY_BASE":{
27
+ "generator":"secret"
28
+ },
29
+ "SMTP_ADDRESS":{
30
+ "required":true
31
+ },
32
+ "SMTP_DOMAIN":{
33
+ "required":true
34
+ },
35
+ "SMTP_PASSWORD":{
36
+ "required":true
37
+ },
38
+ "SMTP_USERNAME":{
39
+ "required":true
40
+ }
41
+ },
42
+ "addons":[
43
+ "heroku-postgresql"
44
+ ]
45
+ }
@@ -0,0 +1,19 @@
1
+ default: &default
2
+ ASSET_HOST: 'localhost:3000'
3
+ APPLICATION_HOST: 'localhost:3000'
4
+ PORT: '3000'
5
+ RACK_ENV: 'development'
6
+ RACK_MINI_PROFILER: '0'
7
+ SECRET_KEY_BASE: 'development_secret'
8
+ EXECJS_RUNTIME: 'Node'
9
+ SMTP_ADDRESS: ''
10
+ SMTP_DOMAIN: ''
11
+ SMTP_PASSWORD: ''
12
+ SMTP_USERNAME: ''
13
+ WEB_CONCURRENCY: 1
14
+
15
+ development:
16
+ <<: *default
17
+
18
+ test:
19
+ <<: *default
@@ -0,0 +1,5 @@
1
+ @charset "utf-8";
2
+
3
+ @import "normalize.css/normalize.css";
4
+
5
+ @import "partials/_flashes.scss";
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+
3
+ # Run this script to deploy the app to Heroku.
4
+
5
+ set -e
6
+
7
+ branch="$(git symbolic-ref HEAD --short)"
8
+ target="${1:-staging}"
9
+
10
+ git push "$target" "$branch:master"
11
+ heroku run rails db:migrate --exit-code --remote "$target"
12
+ heroku restart --remote "$target"
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ load File.expand_path('spring', __dir__)
4
+ rescue LoadError => e
5
+ raise unless e.message.include?('spring')
6
+ end
7
+ require_relative '../config/boot'
8
+ require 'rake'
9
+
10
+ task spec: %i[rubocop]
11
+
12
+ Rake.application.run
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ include FileUtils
3
+
4
+ require 'pathname'
5
+ require 'fileutils'
6
+
7
+ APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8
+
9
+ def system!(*args)
10
+ system(*args) || abort("\n== Command #{args} failed ==")
11
+ end
12
+
13
+ chdir APP_ROOT do
14
+ puts '== Installing dependencies =='
15
+ system! 'gem install bundler --conservative'
16
+ system('bundle check') || system!('bundle install')
17
+
18
+ puts "\n== Copying sample files =="
19
+ unless File.exist?('config/application.yml')
20
+ system 'cp config/application.example.yml config/application.yml'
21
+ end
22
+
23
+ puts "\n== Preparing database =="
24
+ system! 'bin/rails db:setup'
25
+
26
+ puts "\n== Removing old logs and tempfiles =="
27
+ system! 'bin/rails log:clear tmp:clear'
28
+
29
+ puts "\n== Restarting application server =="
30
+ system! 'bin/rails restart'
31
+ end
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+
3
+ # Run this script to set up a review app's database and worker dyno
4
+
5
+ set -e
6
+
7
+ if [ -z "$1" ]; then
8
+ printf "You must provide a review app (same as the pull request) id.\n"
9
+ exit 64
10
+ fi
11
+
12
+ PARENT_APP_NAME=<%= app_name.dasherize %>-staging
13
+ APP_NAME=<%= app_name.dasherize %>-staging-pr-$1
14
+
15
+ heroku pg:backups:capture --app $PARENT_APP_NAME
16
+
17
+ URL=`heroku pg:backups public-url --app $PARENT_APP_NAME`
18
+
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
+ heroku ps:scale worker=1 --app $APP_NAME
22
+ heroku restart --app $APP_NAME
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+ include FileUtils
3
+
4
+ require 'pathname'
5
+ require 'fileutils'
6
+
7
+ APP_ROOT = Pathname.new File.expand_path('..', __dir__)
8
+
9
+ def system!(*args)
10
+ system(*args) || abort("\n== Command #{args} failed ==")
11
+ end
12
+
13
+ chdir APP_ROOT do
14
+ puts '== Installing dependencies =='
15
+ system! 'gem install bundler --conservative'
16
+ system('bundle check') || system!('bundle install')
17
+
18
+ puts "\n== Updating database =="
19
+ system! 'bin/rails db:migrate'
20
+
21
+ puts "\n== Removing old logs and tempfiles =="
22
+ system! 'bin/rails log:clear tmp:clear'
23
+
24
+ puts "\n== Restarting application server =="
25
+ system! 'bin/rails restart'
26
+ end
@@ -0,0 +1,3 @@
1
+ Last 2 versions
2
+ Explorer >= 11
3
+ Android >= 4.4
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ if Rails.env.development? || Rails.env.test?
4
+ require 'bundler/audit/task'
5
+ Bundler::Audit::Task.new
6
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'capybara/poltergeist'
4
+
5
+ Capybara.asset_host = ENV['ASSET_HOST']
6
+ Capybara.always_include_port = true
7
+ Capybara.register_driver :poltergeist do |app|
8
+ options = {
9
+ timeout: 60,
10
+ js_errors: false,
11
+ phantomjs: Phantomjs.path,
12
+ phantomjs_logger: File.open(File::NULL, 'w'),
13
+ logger: nil,
14
+ phantomjs_options:
15
+ [
16
+ '--load-images=no',
17
+ '--ignore-ssl-errors=yes'
18
+ ]
19
+ }
20
+ Capybara::Poltergeist::Driver.new(app, options)
21
+ end
22
+ Capybara.javascript_driver = :poltergeist
@@ -0,0 +1,38 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ working_directory: ~/<%= app_name.dasherize %>
5
+ docker:
6
+ - image: circleci/ruby:2.5.1
7
+ environment:
8
+ PGHOST: localhost
9
+ PGUSER: <%= app_name.dasherize %>
10
+ RAILS_ENV: test
11
+ - image: postgres:9.5
12
+ environment:
13
+ POSTGRES_USER: <%= app_name.dasherize %>
14
+ POSTGRES_DB: <%= app_name.dasherize %>_test
15
+ POSTGRES_PASSWORD: ""
16
+ steps:
17
+ - checkout
18
+
19
+ - type: cache-restore
20
+ name: Restore bundle cache
21
+ key: <%= app_name.dasherize %>-{{ checksum "Gemfile.lock" }}
22
+
23
+ - run: bundle install --path vendor/bundle
24
+
25
+ - type: cache-save
26
+ name: Store bundle cache
27
+ key: <%= app_name.dasherize %>-{{ checksum "Gemfile.lock" }}
28
+ paths:
29
+ - vendor/bundle
30
+
31
+ - run: dockerize -wait tcp://localhost:5432 -timeout 1m
32
+
33
+ - run: cp config/application.example.yml config/application.yml
34
+
35
+ - run: bundle exec rake db:setup
36
+
37
+ - run: bundle exec brakeman --exit-on-warn --quiet -f plain
38
+ - run: bundle exec rake
@@ -0,0 +1,19 @@
1
+ en:
2
+ date:
3
+ formats:
4
+ default:
5
+ "%m/%d/%Y"
6
+ with_weekday:
7
+ "%a %m/%d/%y"
8
+
9
+ time:
10
+ formats:
11
+ default:
12
+ "%a, %b %-d, %Y at %r"
13
+ date:
14
+ "%b %-d, %Y"
15
+ short:
16
+ "%B %d"
17
+
18
+ titles:
19
+ application: <%= app_name.humanize %>
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.before(:suite) do
5
+ DatabaseCleaner.clean_with(:deletion)
6
+ end
7
+
8
+ config.before(:each) do
9
+ DatabaseCleaner.strategy = :transaction
10
+ end
11
+
12
+ config.before(:each, js: true) do
13
+ DatabaseCleaner.strategy = :deletion
14
+ end
15
+
16
+ config.before(:each) do
17
+ DatabaseCleaner.start
18
+ end
19
+
20
+ config.after(:each) do
21
+ DatabaseCleaner.clean
22
+ end
23
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ if Rails.env.development? || Rails.env.test?
4
+ require 'factory_bot'
5
+
6
+ namespace :dev do
7
+ desc 'Sample data for local development environment'
8
+ task prime: 'db:setup' do
9
+ include FactoryBot::Syntax::Methods
10
+
11
+ # create(:user, email: "user@example.com", password: "password")
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,18 @@
1
+ !.keep
2
+ *.DS_Store
3
+ *.swo
4
+ *.swp
5
+ .byebug_history
6
+ /.bundle
7
+ /coverage/*
8
+ /config/application.yml
9
+ /db/*.sqlite3
10
+ /db/*.sqlite3-journal
11
+ /log/*
12
+ /node_modules
13
+ /public/assets
14
+ /public/packs
15
+ /public/system
16
+ /tags
17
+ /tmp/*
18
+ /yarn-error.log
@@ -0,0 +1,17 @@
1
+ doctype html
2
+ html lang="#{I18n.locale}"
3
+ head
4
+ meta content=("text/html; charset=UTF-8") http-equiv="Content-Type" /
5
+ meta charset="utf-8" /
6
+ meta content="NOODP" name="ROBOTS" /
7
+ meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport" /
8
+ title= title
9
+
10
+ = stylesheet_link_tag :application, media: "all"
11
+ = csrf_meta_tags
12
+
13
+ body class=body_class
14
+ = render "flashes"
15
+ = yield
16
+ = render "javascript"
17
+ = render "css_overrides"
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'net/smtp'
5
+
6
+ # Example:
7
+ # begin
8
+ # some http call
9
+ # rescue *HTTP_ERRORS => error
10
+ # notify_hoptoad error
11
+ # end
12
+
13
+ HTTP_ERRORS = [
14
+ EOFError,
15
+ Errno::ECONNRESET,
16
+ Errno::EINVAL,
17
+ Net::HTTPBadResponse,
18
+ Net::HTTPHeaderSyntaxError,
19
+ Net::ProtocolError,
20
+ Timeout::Error
21
+ ].freeze
22
+
23
+ SMTP_SERVER_ERRORS = [
24
+ IOError,
25
+ Net::SMTPAuthenticationError,
26
+ Net::SMTPServerBusy,
27
+ Net::SMTPUnknownError,
28
+ Timeout::Error
29
+ ].freeze
30
+
31
+ SMTP_CLIENT_ERRORS = [
32
+ Net::SMTPFatalError,
33
+ Net::SMTPSyntaxError
34
+ ].freeze
35
+
36
+ SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ FactoryBot.define do
4
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.include FactoryBot::Syntax::Methods
5
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FlashesHelper
4
+ def user_facing_flashes
5
+ flash.to_hash.slice('alert', 'error', 'notice', 'success')
6
+ end
7
+ end
data/templates/i18n.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.configure do |config|
4
+ config.include ActionView::Helpers::TranslationHelper
5
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ ActiveSupport::JSON::Encoding.time_precision = 0
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ Rails.application.configure do
4
+ config.lograge.enabled = Rails.env.production?
5
+ config.lograge.custom_options = lambda do |event|
6
+ exceptions = %w[controller action format]
7
+ {
8
+ params: event.payload[:params].except(*exceptions)
9
+ }
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ development: &default
2
+ adapter: postgresql
3
+ database: <%= app_name %>_development
4
+ encoding: utf8
5
+ min_messages: warning
6
+ pool: <%%= Integer(ENV.fetch("DB_POOL", 5)) %>
7
+ reaping_frequency: <%%= Integer(ENV.fetch("DB_REAPING_FREQUENCY", 10)) %>
8
+ timeout: 5000
9
+
10
+ test:
11
+ <<: *default
12
+ database: <%= app_name %>_test
13
+
14
+ production: &deploy
15
+ encoding: utf8
16
+ min_messages: warning
17
+ pool: <%%= [Integer(ENV.fetch("MAX_THREADS", 5)), Integer(ENV.fetch("DB_POOL", 5))].max %>
18
+ timeout: 5000
19
+ url: <%%= ENV.fetch("DATABASE_URL", "") %>
data/templates/puma.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ workers Integer(ENV.fetch('WEB_CONCURRENCY', 2))
4
+ threads_count = Integer(ENV.fetch('MAX_THREADS', 2))
5
+ threads(threads_count, threads_count)
6
+
7
+ preload_app!
8
+
9
+ rackup DefaultRackup
10
+ environment ENV.fetch('RACK_ENV', 'development')
11
+
12
+ on_worker_boot do
13
+ ActiveRecord::Base.establish_connection
14
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ if ENV['RACK_MINI_PROFILER'].to_i.positive?
4
+ require 'rack-mini-profiler'
5
+
6
+ Rack::MiniProfilerRails.initialize!(Rails.application)
7
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ ENV['RACK_ENV'] = 'test'
4
+
5
+ require 'spec_helper'
6
+
7
+ require File.expand_path('../config/environment', __dir__)
8
+ abort('DATABASE_URL environment variable is set') if ENV['DATABASE_URL']
9
+
10
+ require 'rspec/rails'
11
+
12
+ Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each do |file|
13
+ require file
14
+ end
15
+
16
+ module Features
17
+ include Formulaic::Dsl
18
+ end
19
+
20
+ RSpec.configure do |config|
21
+ config.include Features, type: :feature
22
+ config.infer_base_class_for_anonymous_controllers = false
23
+ config.infer_spec_type_from_file_location!
24
+ config.use_transactional_fixtures = false
25
+ end
26
+
27
+ ActiveRecord::Migration.maintain_test_schema!
@@ -0,0 +1,85 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bin/*'
4
+
5
+ Metrics/LineLength:
6
+ Max: 80
7
+ Exclude:
8
+ - 'db/schema.rb'
9
+
10
+ Metrics/MethodLength:
11
+ Enabled: false
12
+
13
+ Rails:
14
+ Enabled: true
15
+
16
+ Style/AlignParameters:
17
+ EnforcedStyle: with_fixed_indentation
18
+
19
+ Style/BlockComments:
20
+ Exclude:
21
+ - 'spec/spec_helper.rb'
22
+
23
+ Metrics/BlockLength:
24
+ Exclude:
25
+ - 'app/admin/*'
26
+ - 'config/environments/*'
27
+ - 'spec/**/*'
28
+
29
+ Style/Documentation:
30
+ Enabled: false
31
+
32
+ Style/EmptyLinesAroundBlockBody:
33
+ Exclude:
34
+ - 'db/schema.rb'
35
+
36
+ Style/ExtraSpacing:
37
+ Exclude:
38
+ - 'bin/*'
39
+ - 'db/schema.rb'
40
+
41
+ Style/FirstParameterIndentation:
42
+ EnforcedStyle: consistent
43
+
44
+ Style/FrozenStringLiteralComment:
45
+ Exclude:
46
+ - 'bin/*'
47
+ - 'db/schema.rb'
48
+
49
+ Style/GuardClause:
50
+ Enabled: false
51
+
52
+ Style/HashSyntax:
53
+ Exclude:
54
+ - 'Rakefile'
55
+ - 'lib/tasks/*.rake'
56
+
57
+ Style/IfUnlessModifier:
58
+ Enabled: false
59
+
60
+ Style/IndentArray:
61
+ EnforcedStyle: consistent
62
+
63
+ Style/MultilineMethodCallIndentation:
64
+ EnforcedStyle: indented
65
+
66
+ Style/NumericLiterals:
67
+ Exclude:
68
+ - 'db/schema.rb'
69
+
70
+ Style/PercentLiteralDelimiters:
71
+ PreferredDelimiters:
72
+ '%': ()
73
+ '%i': '[]'
74
+ '%q': ()
75
+ '%Q': ()
76
+ '%r': '{}'
77
+ '%s': ()
78
+ '%w': '[]'
79
+ '%W': '[]'
80
+ '%x': ()
81
+
82
+ Style/StringLiterals:
83
+ Exclude:
84
+ - 'bin/*'
85
+ - 'db/schema.rb'