rsg 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +13 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +14 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +190 -0
- data/LICENSE +201 -0
- data/README.md +192 -0
- data/Rakefile +10 -0
- data/bin/console +12 -0
- data/bin/setup +8 -0
- data/exe/rsg +22 -0
- data/lib/rsg/generators/actions.rb +108 -0
- data/lib/rsg/generators/app/USAGE +14 -0
- data/lib/rsg/generators/app/app_builder.rb +42 -0
- data/lib/rsg/generators/app/app_generator.rb +80 -0
- data/lib/rsg/generators/app/templates/README.md.erb +22 -0
- data/lib/rsg/generators/base.rb +27 -0
- data/lib/rsg/generators/dotenv/install_generator.rb +24 -0
- data/lib/rsg/generators/dotenv/templates/env.development +2 -0
- data/lib/rsg/generators/dotenv/templates/env.test +2 -0
- data/lib/rsg/generators/gemfile/cleanup_generator.rb +28 -0
- data/lib/rsg/generators/install/install_generator.rb +13 -0
- data/lib/rsg/generators/logging/common_generator.rb +40 -0
- data/lib/rsg/generators/logging/lograge_generator.rb +31 -0
- data/lib/rsg/generators/logging/templates/initializer_lograge.rb +9 -0
- data/lib/rsg/generators/misc/misc_generator.rb +61 -0
- data/lib/rsg/generators/misc/templates/puma.rb +44 -0
- data/lib/rsg/generators/options.rb +15 -0
- data/lib/rsg/generators/orm/active_record_generator.rb +44 -0
- data/lib/rsg/generators/orm/templates/active_record/mysql.yml +59 -0
- data/lib/rsg/generators/orm/templates/active_record/postgresql.yml +86 -0
- data/lib/rsg/generators/orm/templates/active_record/sqlite3.yml +25 -0
- data/lib/rsg/generators/orm/templates/db.rake +7 -0
- data/lib/rsg/generators/orm/templates/samples.rb +10 -0
- data/lib/rsg/generators/orm/templates/seeds.rb +9 -0
- data/lib/rsg/generators/testing/rspec_generator.rb +33 -0
- data/lib/rsg/generators/webpacker/install_generator.rb +51 -0
- data/lib/rsg/generators/webpacker/templates/application.js +18 -0
- data/lib/rsg/generators/webpacker/templates/application.sass +19 -0
- data/lib/rsg/generators/webpacker/templates/landing_controller.rb.erb +6 -0
- data/lib/rsg/generators/webpacker/templates/landing_show.html.erb +8 -0
- data/lib/rsg/version.rb +4 -0
- data/lib/rsg.rb +36 -0
- data/rsg.gemspec +28 -0
- data/templates/README.md +4 -0
- data/templates/rsg-default.rb +17 -0
- metadata +109 -0
data/exe/rsg
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "pathname"
|
5
|
+
|
6
|
+
source_path = Pathname.new(__FILE__).dirname.join("../lib").expand_path
|
7
|
+
$LOAD_PATH << source_path
|
8
|
+
|
9
|
+
require "rsg"
|
10
|
+
|
11
|
+
if ARGV.empty?
|
12
|
+
puts "Please provide a path for the new application"
|
13
|
+
puts
|
14
|
+
puts "See --help for more info"
|
15
|
+
exit 0
|
16
|
+
elsif ["-v", "--version"].include? ARGV[0]
|
17
|
+
puts "RSG: #{RSG::VERSION}"
|
18
|
+
puts "Rails: #{Rails::VERSION}"
|
19
|
+
exit 0
|
20
|
+
end
|
21
|
+
|
22
|
+
Rsg::AppGenerator.start
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "json"
|
2
|
+
require "shellwords"
|
3
|
+
|
4
|
+
module Rsg
|
5
|
+
module Generators
|
6
|
+
module Actions
|
7
|
+
def rsg_install
|
8
|
+
append_gem "rsg",
|
9
|
+
within_group: %i(development test),
|
10
|
+
install: false,
|
11
|
+
path: options[:path]
|
12
|
+
end
|
13
|
+
|
14
|
+
def rsg_generate(name, quiet: false)
|
15
|
+
cmd = "generate #{name}"
|
16
|
+
cmd << " -q" if quiet
|
17
|
+
|
18
|
+
rails_command cmd
|
19
|
+
git_add_commit "RSG Generator executed: #{name}"
|
20
|
+
end
|
21
|
+
|
22
|
+
def rsg_apply_default!
|
23
|
+
rsg_apply "rsg-default"
|
24
|
+
end
|
25
|
+
|
26
|
+
def rsg_apply(template)
|
27
|
+
apply Rsg.lookup_app_template(template)
|
28
|
+
end
|
29
|
+
|
30
|
+
def api_mode?
|
31
|
+
return @api_mode if defined?(@api_mode)
|
32
|
+
@api_mode = !!(File.read("config/application.rb") =~ /^[^#]*config\.api_only = true[^\n]*$/)
|
33
|
+
end
|
34
|
+
|
35
|
+
def confirm?(prompt)
|
36
|
+
opts = { limited_to: %w(y n) }
|
37
|
+
ask(prompt, opts).downcase == 'y'
|
38
|
+
end
|
39
|
+
|
40
|
+
def git_add_commit(commit_msg)
|
41
|
+
truncated_msg = commit_msg.strip.gsub("\n", ' ')[0..59].strip
|
42
|
+
truncated_msg.gsub!(/.{3}$/, '...') if commit_msg.length > 60
|
43
|
+
say_status :run, "git add . && git commit -m \"#{truncated_msg}\""
|
44
|
+
|
45
|
+
run "git add .", verbose: false, capture: true
|
46
|
+
run "git commit -m #{Shellwords.escape(commit_msg)}", verbose: false, capture: true
|
47
|
+
end
|
48
|
+
|
49
|
+
def enable_railtie(name)
|
50
|
+
uncomment_lines "config/application.rb", /require ['"]#{name}\/railtie['"]/
|
51
|
+
end
|
52
|
+
|
53
|
+
def append_gem(gem_name, install: true, within_group: [], after: ["bootsnap", "rails"], **gem_line_params)
|
54
|
+
within_group = Array(within_group)
|
55
|
+
if within_group.any?
|
56
|
+
group_part = within_group.map { |g| "[:'\"]#{g}['\"]?" }.join(", ")
|
57
|
+
regex = /^ *group #{group_part} do\n(\s*(gem|#)[^\n]+\n)+ *end\n/
|
58
|
+
else
|
59
|
+
regex = /.+/m
|
60
|
+
end
|
61
|
+
|
62
|
+
gsub_file "Gemfile", regex do |match|
|
63
|
+
gem_line = build_gem_line(gem_name, gem_line_params)
|
64
|
+
append_gem_line(match, gem_line, after)
|
65
|
+
end
|
66
|
+
|
67
|
+
run("bundle install", capture: true) if install
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def append_gem_line(code, gem_line, after)
|
73
|
+
code_lines = code.split("\n")
|
74
|
+
index = code_lines.length
|
75
|
+
indentation = ""
|
76
|
+
|
77
|
+
# Goes to the line above the `end` line by default
|
78
|
+
if code_lines[0] =~ /^([^#]*)group/
|
79
|
+
index -= 1
|
80
|
+
indentation = "#{$1} "
|
81
|
+
end
|
82
|
+
|
83
|
+
Array(after).each do |candidate|
|
84
|
+
idx = code_lines.index { |l| l =~ /^([^#]*)gem ['"]#{candidate}['"].*$/ }
|
85
|
+
next unless idx
|
86
|
+
|
87
|
+
indentation = $1
|
88
|
+
index = idx + 1
|
89
|
+
break
|
90
|
+
end
|
91
|
+
|
92
|
+
code_lines.insert(index, "#{indentation}#{gem_line}").join("\n") << "\n"
|
93
|
+
end
|
94
|
+
|
95
|
+
def build_gem_line(gem_name, params = {})
|
96
|
+
line = "gem '#{gem_name}'"
|
97
|
+
if params.key?(:version)
|
98
|
+
version_args = Array(params[:version]).map { |v| "'#{v}'" }.join(", ")
|
99
|
+
line << ", #{version_args}"
|
100
|
+
end
|
101
|
+
line << ", require: '#{params[:require]}'" if params.key?(:require)
|
102
|
+
line << ", group: #{params[:group]}" if params.key?(:group)
|
103
|
+
line << ", path: '#{params[:path]}'" if params[:path].present?
|
104
|
+
line
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
RSG is a Rails app generator with Doximity's basic defaults configured.
|
3
|
+
|
4
|
+
For full details on the changes we've made compared to a vanilla Rails app, check
|
5
|
+
our GitHub project:
|
6
|
+
https://github.com/doximity/rsg
|
7
|
+
|
8
|
+
Example:
|
9
|
+
rsg ~/Code/weblog [options]
|
10
|
+
|
11
|
+
Is the equivalent of running `rails new ~/Code/weblog [options]` with most Rails
|
12
|
+
components disabled by default. This will generate a minimal Rails app in
|
13
|
+
~/Code/weblog configured with our preferred defaults. Some questions might be
|
14
|
+
asked along the way to fine tune the generated app.
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
# The application builder allows you to override elements of the application
|
5
|
+
# generator without being forced to reverse the operations of the default
|
6
|
+
# generator.
|
7
|
+
#
|
8
|
+
# This allows you to override entire operations, like the creation of the
|
9
|
+
# Gemfile, README, or JavaScript files, without needing to know exactly
|
10
|
+
# what those operations do so you can create another template action.
|
11
|
+
#
|
12
|
+
# For Rails 6.1, you can check out https://github.com/rails/rails/blob/6-1-stable/railties/lib/rails/generators/rails/app/app_generator.rb#L44
|
13
|
+
class AppBuilder < ::Rails::AppBuilder
|
14
|
+
def master_key
|
15
|
+
gsub_file "config/application.rb",
|
16
|
+
/^(\s*)(config\.load_defaults[^\n]+)\n$/,
|
17
|
+
"\\1\\2\n\n\\1# We don't use Rails encrypted secrets\n"\
|
18
|
+
"\\1config.require_master_key = false\n" \
|
19
|
+
"\\1config.active_support.use_authenticated_message_encryption = false\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
###########################################################################
|
23
|
+
# Simple template overwrites
|
24
|
+
###########################################################################
|
25
|
+
|
26
|
+
def readme
|
27
|
+
template "README.md.erb", "README.md"
|
28
|
+
end
|
29
|
+
|
30
|
+
###########################################################################
|
31
|
+
# Things to skip since we don't care about them
|
32
|
+
###########################################################################
|
33
|
+
|
34
|
+
def ruby_version
|
35
|
+
# NOOP since we have the ruby version in Gemfile
|
36
|
+
end
|
37
|
+
|
38
|
+
def credentials
|
39
|
+
# NOOP since we store env vars / secrets elsewhere
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# require "rails/generators"
|
2
|
+
require "rails/generators/rails/app/app_generator"
|
3
|
+
|
4
|
+
require_relative "app_builder"
|
5
|
+
|
6
|
+
module Rsg
|
7
|
+
# AppGenerator is the entrypoint for generation of new apps which builds on
|
8
|
+
# top of the core `rails new` command
|
9
|
+
class AppGenerator < Rails::Generators::AppGenerator
|
10
|
+
include Generators::Actions
|
11
|
+
|
12
|
+
hide!
|
13
|
+
|
14
|
+
class_option :version, type: :boolean, aliases: "-v", group: :rsg, desc: "Show RSG version number and quit"
|
15
|
+
class_option :help, type: :boolean, aliases: "-h", group: :rsg, desc: "Show this help message and quit"
|
16
|
+
class_option :path, type: :string, default: nil, desc: "Path to the RSG gem"
|
17
|
+
class_option :template, aliases: "-m", type: :string, default: "rsg-default", desc: "Path to some application template (can be a filesystem path or URL)"
|
18
|
+
|
19
|
+
# --minimal might take care of some of these, but not all, we change all defaults here regardless since
|
20
|
+
# --minimal is subject to change with new releases. We also hide them all, and re-add things as necessary
|
21
|
+
# based on user input as generators kick in
|
22
|
+
class_option :skip_action_cable, type: :boolean, default: true, desc: "Skip Action Cable files", hide: true
|
23
|
+
class_option :skip_action_mailbox, type: :boolean, default: true, desc: "Skip Action Mailbox files", hide: true
|
24
|
+
class_option :skip_action_mailer, type: :boolean, default: true, desc: "Skip Action Mailer files", hide: true
|
25
|
+
class_option :skip_action_text, type: :boolean, default: true, desc: "Skip Action Text files", hide: true
|
26
|
+
class_option :skip_active_job, type: :boolean, default: true, desc: "Skip Active Job files", hide: true
|
27
|
+
class_option :skip_active_record, type: :boolean, default: true, desc: "Skip Active Record files", hide: true
|
28
|
+
class_option :skip_active_storage, type: :boolean, default: true, desc: "Skip Active Storage files", hide: true
|
29
|
+
class_option :skip_bundle, type: :boolean, default: true, desc: "Don't run bundle install", hide: true
|
30
|
+
class_option :skip_javascript, type: :boolean, default: true, desc: "Skip JavaScript files", hide: true
|
31
|
+
class_option :skip_jbuilder, type: :boolean, default: true, desc: "Skip jbuilder gem", hide: true
|
32
|
+
class_option :skip_keeps, type: :boolean, default: true, desc: "Skip Puma", hide: true
|
33
|
+
class_option :skip_spring, type: :boolean, default: true, desc: "Don't install Spring application preloader", hide: true
|
34
|
+
class_option :skip_sprockets, type: :boolean, default: true, desc: "Skip Sprockets files", hide: true
|
35
|
+
class_option :skip_system_test, type: :boolean, default: true, desc: "Skip system test files", hide: true
|
36
|
+
class_option :skip_test, type: :boolean, default: true, desc: "Skip Test Unit", hide: true
|
37
|
+
class_option :skip_turbolinks, type: :boolean, default: true, desc: "Skip turbolinks gem", hide: true
|
38
|
+
class_option :skip_webpack_install, type: :boolean, default: true, desc: "Don't run webpack install", hide: true
|
39
|
+
|
40
|
+
# Hide other flags, but leave their defaults untouched
|
41
|
+
class_option :database, type: :string, default: "sqlite3", desc: "Configure for selected database (options: #{DATABASES.join("/")})", hide: true
|
42
|
+
class_option :dev, type: :boolean, default: false, desc: "Set up the application with Gemfile pointing to your Rails checkout", hide: true
|
43
|
+
class_option :edge, type: :boolean, default: false, desc: "Set up the application with Gemfile pointing to Rails repository", hide: true
|
44
|
+
class_option :master, type: :boolean, default: false, desc: "Preconfigure a minimal rails app", hide: true
|
45
|
+
class_option :minimal, type: :boolean, default: false, desc: "Preconfigure a minimal rails app", hide: true
|
46
|
+
class_option :skip_bootsnap, type: :boolean, default: false, desc: "Skip bootsnap gem", hide: true
|
47
|
+
class_option :skip_collision_check, type: :boolean, default: false, desc: "Skip collision check", hide: true
|
48
|
+
class_option :skip_gemfile, type: :boolean, default: false, desc: "Don't create a Gemfile", hide: true
|
49
|
+
class_option :skip_git, type: :boolean, default: false, desc: "Skip .gitignore file", hide: true
|
50
|
+
class_option :skip_listen, type: :boolean, default: false, desc: "Don't generate configuration that depends on the listen gem", hide: true
|
51
|
+
class_option :skip_namespace, type: :boolean, default: false, desc: "Skip namespace (affects only isolated engines)", hide: true
|
52
|
+
class_option :skip_puma, type: :boolean, default: false, desc: "Skip Puma related files", hide: true
|
53
|
+
class_option :webpack, type: :string, desc: "Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus)", hide: true
|
54
|
+
|
55
|
+
def self.banner
|
56
|
+
"rsg #{arguments.map(&:usage).join(" ")} [options]"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.source_paths
|
60
|
+
@__source_paths ||= [
|
61
|
+
Rails::Generators::AppGenerator.source_root,
|
62
|
+
Pathname.new(__FILE__).dirname.join("templates").expand_path
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
def set_default_accessors!
|
67
|
+
bundled_template = Rsg.lookup_app_template(options[:template])
|
68
|
+
super
|
69
|
+
self.rails_template = bundled_template if bundled_template
|
70
|
+
end
|
71
|
+
|
72
|
+
protected
|
73
|
+
|
74
|
+
# rubocop:disable Naming/AccessorMethodName
|
75
|
+
def get_builder_class
|
76
|
+
Rsg::AppBuilder
|
77
|
+
end
|
78
|
+
# rubocop:enable Naming/AccessorMethodName
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# <%= app_name.humanize %>
|
2
|
+
|
3
|
+
```
|
4
|
+
TODO: Write a few words about what the app does
|
5
|
+
```
|
6
|
+
|
7
|
+
## Generated with RSG v<%= Rsg::VERSION %>
|
8
|
+
|
9
|
+
This is an application generated with [rsg](https://github.com/doximity/rsg). If you've skipped any of its
|
10
|
+
generators (like ActiveRecord's) or if you'd like to know what else is available for you to configure you
|
11
|
+
can run `rails generate --help | grep rsg`.
|
12
|
+
|
13
|
+
## Getting Started
|
14
|
+
|
15
|
+
After you have cloned this repo, run this setup script to set up your machine
|
16
|
+
with the necessary dependencies to run and test this app:
|
17
|
+
|
18
|
+
% ./bin/setup
|
19
|
+
|
20
|
+
Then start the web server with:
|
21
|
+
|
22
|
+
% ./bin/rails server
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "rails/generators"
|
3
|
+
|
4
|
+
module Rsg
|
5
|
+
module Generators
|
6
|
+
class Base < Rails::Generators::Base
|
7
|
+
include Actions
|
8
|
+
include Options
|
9
|
+
|
10
|
+
def self.inherited(base)
|
11
|
+
super
|
12
|
+
|
13
|
+
parts = base.namespace.split(":")
|
14
|
+
return unless parts[0] == "rsg"
|
15
|
+
|
16
|
+
parts = parts[1..-2] + ["templates"]
|
17
|
+
templates_path = Pathname.new(__FILE__).dirname.join(*parts).expand_path
|
18
|
+
|
19
|
+
base.source_paths << templates_path if templates_path.exist?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.exit_on_failure?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Dotenv
|
5
|
+
class InstallGenerator < Rsg::Generators::Base
|
6
|
+
def banner
|
7
|
+
say "Configuring dotent-rails in development and test environments"
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_dotenv
|
11
|
+
append_gem "dotenv-rails",
|
12
|
+
version: "< 3",
|
13
|
+
after: "rails",
|
14
|
+
group: [:development, :test],
|
15
|
+
require: "dotenv/rails-now"
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure_dotenv
|
19
|
+
copy_file "env.development", ".env.development"
|
20
|
+
copy_file "env.test", ".env.test"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Gemfile
|
5
|
+
class CleanupGenerator < Rsg::Generators::Base
|
6
|
+
def banner
|
7
|
+
say "Cleaning up Gemfile"
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove_comments
|
11
|
+
gsub_file "Gemfile", /^ *#\s*[^#\n]+\n/, ""
|
12
|
+
end
|
13
|
+
|
14
|
+
def remove_tzinfo
|
15
|
+
# Remove tzinfo-data since we don't have a need for it in dev / prod env
|
16
|
+
gsub_file "Gemfile", /\ngem 'tzinfo-data'[^\n]+\n/, ""
|
17
|
+
end
|
18
|
+
|
19
|
+
def remove_extra_whitespace
|
20
|
+
gsub_file "Gemfile", /^( *gem[^\n]+)\n\n\n/, "\\1\n\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
def isolate_rails_gem
|
24
|
+
gsub_file "Gemfile", /^( *)(gem ["']rails["'][^\n]+)\n(?: *)(gem ['"]puma['"][^\n]+)\n$/, "\\1\\2\n\n\\3"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Logging
|
5
|
+
class CommonGenerator < Rsg::Generators::Base
|
6
|
+
def banner
|
7
|
+
say "Improving basic logging configs"
|
8
|
+
end
|
9
|
+
|
10
|
+
def log_level_env_var
|
11
|
+
inject_into_file "config/application.rb", <<-CODE, before: /^ end$/
|
12
|
+
\n # Sane default log levels per env, but able to tweak with env var
|
13
|
+
# NOTE: Settings on config/environments/*.rb take precedence over this
|
14
|
+
config.log_level = ENV.fetch('LOG_LEVEL') { Rails.env.development? ? 'debug' : 'info' }.to_sym
|
15
|
+
|
16
|
+
# Log to stdout most of the time and allow use of JSON logs in dev by using an env var
|
17
|
+
config.x.log_to_stdout = %w[1 true yes].include?(ENV.fetch('RAILS_LOG_TO_STDOUT', '1'))
|
18
|
+
CODE
|
19
|
+
end
|
20
|
+
|
21
|
+
def stdout_logging_in_dev
|
22
|
+
inject_into_file "config/environments/development.rb", <<-CODE, before: /^end$/
|
23
|
+
\n # Configure stdout logging in dev as well
|
24
|
+
if config.x.log_to_stdout
|
25
|
+
logger = ActiveSupport::Logger.new(STDOUT)
|
26
|
+
logger.formatter = config.log_formatter
|
27
|
+
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
28
|
+
end
|
29
|
+
CODE
|
30
|
+
end
|
31
|
+
|
32
|
+
def adjust_prod
|
33
|
+
comment_lines "config/environments/production.rb", /^(\s*)(config\.log_level .+)$/
|
34
|
+
gsub_file "config/environments/production.rb",
|
35
|
+
'ENV["RAILS_LOG_TO_STDOUT"].present?',
|
36
|
+
"config.x.log_to_stdout"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Logging
|
5
|
+
class LogrageGenerator < Rsg::Generators::Base
|
6
|
+
def self.source_root
|
7
|
+
Pathname.new(__FILE__).dirname.join("templates").expand_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def banner
|
11
|
+
say "Configuring lograge with JSON logging"
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_lograge
|
15
|
+
append_gem "lograge", install: false
|
16
|
+
append_gem "logstash-event", after: "lograge"
|
17
|
+
end
|
18
|
+
|
19
|
+
def initializer
|
20
|
+
copy_file "initializer_lograge.rb", "config/initializers/logging.rb"
|
21
|
+
end
|
22
|
+
|
23
|
+
def json_logs_env_var
|
24
|
+
inject_into_file "config/application.rb", <<-CODE, before: /^ end$/
|
25
|
+
\n # Enable JSON logs with lograge
|
26
|
+
config.x.json_logs = Rails.env.production? || %w[1 true yes].include?(ENV.fetch('JSON_LOGS', '0'))
|
27
|
+
CODE
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Rails.application.configure do
|
2
|
+
return unless config.x.json_logs
|
3
|
+
|
4
|
+
# See https://github.com/roidrage/lograge for more information on how to configure the gem
|
5
|
+
# This only configures logs to be formatted as JSON when lograge is enabled but you can do much more with it,
|
6
|
+
# like annotating logs with user IDs
|
7
|
+
config.lograge.enabled = true
|
8
|
+
config.lograge.formatter = Lograge::Formatters::Logstash.new
|
9
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Misc
|
5
|
+
class MiscGenerator < Generators::Base
|
6
|
+
def self.source_root
|
7
|
+
Pathname.new(__FILE__).dirname.join("templates").expand_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def banner
|
11
|
+
say "Making some extra tweaks"
|
12
|
+
end
|
13
|
+
|
14
|
+
def disable_assets_generators
|
15
|
+
return if api_mode?
|
16
|
+
|
17
|
+
inject_into_file "config/application.rb", <<-CODE, before: /^\s*# Don't generate system test files./
|
18
|
+
|
19
|
+
# Don't generate CSS files when using scaffolding commands, since we compile assets through webpacker
|
20
|
+
config.generators.assets = false
|
21
|
+
config.generators.scaffold_stylesheet = false
|
22
|
+
config.generators.stylesheets = false
|
23
|
+
|
24
|
+
# Most of time we can get away with a handful of methods in the default application_helper. Other ones
|
25
|
+
# can be introduced as needed
|
26
|
+
config.generators.helper = false
|
27
|
+
CODE
|
28
|
+
end
|
29
|
+
|
30
|
+
def configure_pry
|
31
|
+
append_gem "pry-rails", within_group: :development
|
32
|
+
end
|
33
|
+
|
34
|
+
def remove_assets
|
35
|
+
run "rm -rf app/assets"
|
36
|
+
end
|
37
|
+
|
38
|
+
# TODO: Skip puma on app generator, introduce a new Puma::InstallGenerator
|
39
|
+
def puma_configs
|
40
|
+
copy_file "puma.rb", "config/puma.rb", force: true
|
41
|
+
end
|
42
|
+
|
43
|
+
# TODO: Move to an i18n generator that does this and more
|
44
|
+
def configure_environments
|
45
|
+
# If by any chance we make use of translations, let them fail and get
|
46
|
+
# caught early on the dev process
|
47
|
+
uncomment_lines "config/environments/development.rb", /raise_on_missing_translations/
|
48
|
+
uncomment_lines "config/environments/test.rb", /raise_on_missing_translations/
|
49
|
+
end
|
50
|
+
|
51
|
+
def healthcheck
|
52
|
+
inject_into_file "config/routes.rb", <<-CODE, before: "end"
|
53
|
+
|
54
|
+
# Defines a static healthcheck for probes. Please note that this won't
|
55
|
+
# output any logs in production
|
56
|
+
get :healthcheck, to: proc { [200, {}, ['OK']] }
|
57
|
+
CODE
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Puma can serve each request in a thread from an internal thread pool.
|
4
|
+
# The `threads` method setting takes two numbers: a minimum and maximum.
|
5
|
+
# Any libraries that use thread pools should be configured to match
|
6
|
+
# the maximum value specified for Puma. Default is set to 5 threads for minimum
|
7
|
+
# and maximum; this matches the default thread size of Active Record.
|
8
|
+
max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5)
|
9
|
+
min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count }
|
10
|
+
threads min_threads_count, max_threads_count
|
11
|
+
|
12
|
+
# Specifies the `worker_timeout` threshold that Puma will use to wait before
|
13
|
+
# terminating a worker in development environments.
|
14
|
+
# worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
|
15
|
+
|
16
|
+
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
|
17
|
+
port ENV.fetch('PORT', 3000)
|
18
|
+
|
19
|
+
# Specifies the `environment` that Puma will run in.
|
20
|
+
# environment ENV.fetch("RAILS_ENV") { "development" }
|
21
|
+
|
22
|
+
# Specifies the `pidfile` that Puma will use.
|
23
|
+
# pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
|
24
|
+
|
25
|
+
# Specifies the number of `workers` to boot in clustered mode. Workers are
|
26
|
+
# forked web server processes. If using threads and workers together the
|
27
|
+
# concurrency of the application would be max `threads` * `workers`. Workers do
|
28
|
+
# not work on JRuby or Windows (both of which do not support processes).
|
29
|
+
#
|
30
|
+
# Here we disable workers by default since we tipically run our apps in
|
31
|
+
# containers, so we can scale the amount of processes by spinning up new
|
32
|
+
# containers to handle the load instead of having multiple processes running in
|
33
|
+
# the same container.
|
34
|
+
workers ENV.fetch('WEB_CONCURRENCY', 0)
|
35
|
+
|
36
|
+
# Use the `preload_app!` method when specifying a `workers` number.
|
37
|
+
# This directive tells Puma to first boot the application and load code
|
38
|
+
# before forking the application. This takes advantage of Copy On Write
|
39
|
+
# process behavior so workers use less memory.
|
40
|
+
#
|
41
|
+
# preload_app!
|
42
|
+
|
43
|
+
# Allow puma to be restarted by `rails restart` command.
|
44
|
+
plugin :tmp_restart
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rsg
|
2
|
+
module Generators
|
3
|
+
module Options
|
4
|
+
def self.included(base)
|
5
|
+
configure_basic_options(base)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configure_basic_options(base)
|
9
|
+
base.instance_eval do
|
10
|
+
class_option :quiet, type: :boolean, aliases: "-q", default: false, desc: "Suppress status output"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require_relative "../base"
|
2
|
+
|
3
|
+
module Rsg
|
4
|
+
module Orm
|
5
|
+
class ActiveRecordGenerator < Generators::Base
|
6
|
+
include Rails::Generators::Database
|
7
|
+
|
8
|
+
SUPPORTED_DBS = %w(sqlite3 mysql postgres)
|
9
|
+
class_option :database, type: :string, default: nil, desc: "Configure for selected database (options: #{SUPPORTED_DBS.join("/")})"
|
10
|
+
|
11
|
+
def self.source_root
|
12
|
+
Pathname.new(__FILE__).dirname.join("templates").expand_path
|
13
|
+
end
|
14
|
+
|
15
|
+
def banner
|
16
|
+
say "Configuring active record"
|
17
|
+
end
|
18
|
+
|
19
|
+
def enable_active_record
|
20
|
+
enable_railtie "active_record"
|
21
|
+
end
|
22
|
+
|
23
|
+
def configure_driver
|
24
|
+
database = options.fetch(:database) { ask("Which database you'd like to use?", limited_to: SUPPORTED_DBS, default: "sqlite3") }
|
25
|
+
template "active_record/#{database}.yml", "config/database.yml"
|
26
|
+
|
27
|
+
name, version = gem_for_database(database)
|
28
|
+
append_gem name, version: version
|
29
|
+
end
|
30
|
+
|
31
|
+
def write_db_sample
|
32
|
+
copy_file "db.rake", "lib/tasks/db.rake"
|
33
|
+
copy_file "seeds.rb", "db/seeds.rb"
|
34
|
+
copy_file "samples.rb", "db/samples.rb"
|
35
|
+
end
|
36
|
+
|
37
|
+
def migrate
|
38
|
+
return if no?("Would you like to create the database schema?")
|
39
|
+
|
40
|
+
rake "db:create db:migrate"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|