rsg 0.0.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.
- 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
|