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.
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'