boring_generators 0.11.0 → 0.13.0
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 +4 -4
- data/.github/workflows/ci.yml +2 -2
- data/.github/workflows/codeql-analysis.yml +70 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +18 -1
- data/CONTRIBUTING.md +17 -0
- data/Gemfile.lock +9 -11
- data/README.md +15 -1
- data/lib/boring_generators/version.rb +1 -1
- data/lib/generators/boring/bootstrap/install/install_generator.rb +15 -1
- data/lib/generators/boring/factory_bot/install/install_generator.rb +46 -0
- data/lib/generators/boring/factory_bot/install/templates/users.rb +8 -0
- data/lib/generators/boring/faker/install/install_generator.rb +17 -0
- data/lib/generators/boring/flipper/install/install_generator.rb +37 -0
- data/lib/generators/boring/flipper/install/templates/initializer.rb.tt +19 -0
- data/lib/generators/boring/letter_opener/install/install_generator.rb +39 -0
- data/lib/generators/boring/overcommit/base_generator.rb +45 -0
- data/lib/generators/boring/overcommit/pre_commit/rubocop/install/install_generator.rb +62 -0
- data/lib/generators/boring/rspec/install/install_generator.rb +50 -0
- data/lib/generators/boring/rswag/install/install_generator.rb +166 -0
- data/lib/generators/boring/rswag/install/templates/README +10 -0
- data/lib/generators/boring/rubocop/install/install_generator.rb +32 -6
- data/lib/generators/boring/rubocop/install/templates/.rubocop.yml.tt +6 -3
- data/lib/generators/boring/webmock/install/install_generator.rb +86 -0
- data/lib/generators/boring/whenever/install/install_generator.rb +25 -0
- data/tmp/templates/app_template/.ruby-version +1 -1
- data/tmp/templates/app_template/Gemfile +1 -1
- data/tmp/templates/app_template/config/boot.rb +1 -1
- data/tmp/templates/app_template/yarn.lock +61 -91
- metadata +17 -4
- data/tmp/templates/app_template/log/development.log +0 -72
@@ -0,0 +1,166 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Boring
|
4
|
+
module Rswag
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
desc "Adds rswag gem to the application"
|
7
|
+
source_root File.expand_path("templates", __dir__)
|
8
|
+
|
9
|
+
class_option :rails_port,
|
10
|
+
type: :string,
|
11
|
+
desc: "Tell us the port number where you normally run your rails app. Defaults to PORT 3000",
|
12
|
+
default: "3000"
|
13
|
+
class_option :authentication_type,
|
14
|
+
type: :string,
|
15
|
+
desc: "Tell us the authentication type you use in your rails app. Options: ['basic', 'bearer', 'api_key']. Defaults to 'basic'",
|
16
|
+
default: 'basic'
|
17
|
+
class_option :skip_api_authentication,
|
18
|
+
type: :boolean,
|
19
|
+
desc: "Use this option with value 'true' if you don't want to add Authentication when making API calls via swagger docs.",
|
20
|
+
default: false
|
21
|
+
class_option :api_authentication_options,
|
22
|
+
type: :hash,
|
23
|
+
desc: 'Use together with authentication_type. Required for "api_key" authentication which has dynamic set of options. See: https://swagger.io/docs/specification/authentication. Example: "--api_authentication_options=name:api_key in:header"'
|
24
|
+
class_option :enable_swagger_ui_authentication,
|
25
|
+
type: :boolean,
|
26
|
+
desc: "Use this option with value 'true' for securing your API docs behind a basic authentication to block unauthorized access",
|
27
|
+
default: false
|
28
|
+
|
29
|
+
def verify_presence_of_rspec_gem
|
30
|
+
gem_file_content_array = File.readlines("Gemfile")
|
31
|
+
|
32
|
+
rspec_is_installed = gem_file_content_array.any? { |line| line.include?("rspec-rails") }
|
33
|
+
|
34
|
+
return if rspec_is_installed
|
35
|
+
|
36
|
+
say "We couldn't find rspec-rails gem which is a dependency for the rswag gem. Please configure rspec and run the generator again!"
|
37
|
+
|
38
|
+
abort
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_rswag_gems
|
42
|
+
say "Adding rswag gems to Gemfile", :green
|
43
|
+
|
44
|
+
gem 'rswag-api'
|
45
|
+
gem 'rswag-ui'
|
46
|
+
gem 'rswag-specs', group: [:development, :test]
|
47
|
+
end
|
48
|
+
|
49
|
+
def install_rswag
|
50
|
+
say "\nRunning rswag install generator to add required files", :green
|
51
|
+
|
52
|
+
Bundler.with_unbundled_env do
|
53
|
+
run 'bundle install'
|
54
|
+
|
55
|
+
generate 'rswag:api:install'
|
56
|
+
generate 'rswag:ui:install'
|
57
|
+
generate 'rswag:specs:install', [env: 'test']
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_api_host
|
62
|
+
say "\nUpdating API Host URL", :green
|
63
|
+
|
64
|
+
rails_port = options[:rails_port]
|
65
|
+
|
66
|
+
gsub_file "spec/swagger_helper.rb",
|
67
|
+
"url: 'https://{defaultHost}'",
|
68
|
+
"url: 'http://{defaultHost}'"
|
69
|
+
gsub_file "spec/swagger_helper.rb",
|
70
|
+
"default: 'www.example.com'",
|
71
|
+
"default: 'localhost:#{rails_port}'"
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_authentication_scheme
|
75
|
+
if options[:skip_api_authentication]
|
76
|
+
return
|
77
|
+
end
|
78
|
+
|
79
|
+
say "\nAdding Authentication for APIs", :green
|
80
|
+
|
81
|
+
authentication_type = options[:authentication_type]
|
82
|
+
|
83
|
+
if authentication_type == 'api_key'
|
84
|
+
validate_api_authentication_options
|
85
|
+
|
86
|
+
authentication_options = options[:api_authentication_options]
|
87
|
+
end
|
88
|
+
|
89
|
+
authentication_content = case authentication_type
|
90
|
+
when 'bearer'
|
91
|
+
<<~RUBY.chomp.indent(0)
|
92
|
+
type: :http,
|
93
|
+
scheme: :bearer
|
94
|
+
RUBY
|
95
|
+
when 'api_key'
|
96
|
+
<<~RUBY
|
97
|
+
type: :apiKey,
|
98
|
+
name: "#{authentication_options['name']}",
|
99
|
+
in: "#{authentication_options['in']}",
|
100
|
+
RUBY
|
101
|
+
else
|
102
|
+
<<~RUBY
|
103
|
+
type: :http,
|
104
|
+
scheme: :basic
|
105
|
+
RUBY
|
106
|
+
end
|
107
|
+
|
108
|
+
gsub_file "spec/swagger_helper.rb",
|
109
|
+
/servers: \[.*\]/m do |match|
|
110
|
+
configuration_content = <<~RUBY.indent(6)
|
111
|
+
components: {
|
112
|
+
securitySchemes: {
|
113
|
+
authorization: {\n#{authentication_content.chomp.indent(6)}
|
114
|
+
}
|
115
|
+
}
|
116
|
+
},
|
117
|
+
security: [
|
118
|
+
authorization: []
|
119
|
+
]
|
120
|
+
RUBY
|
121
|
+
|
122
|
+
match << ",\n#{configuration_content.chomp}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def enable_swagger_ui_authentication
|
127
|
+
return unless options[:enable_swagger_ui_authentication]
|
128
|
+
|
129
|
+
say "\nAdding Basic Authentication to secure the UI", :green
|
130
|
+
|
131
|
+
uncomment_lines 'config/initializers/rswag_ui.rb', /c.basic_auth_enabled/
|
132
|
+
uncomment_lines 'config/initializers/rswag_ui.rb', /c.basic_auth_credentials/
|
133
|
+
gsub_file "config/initializers/rswag_ui.rb",
|
134
|
+
"c.basic_auth_credentials 'username', 'password'",
|
135
|
+
'c.basic_auth_credentials Rails.application.credentials.dig(:swagger_ui, :username), Rails.application.credentials.dig(:swagger_ui, :password)'
|
136
|
+
|
137
|
+
say "❗️❗️\nusername will be used from `Rails.application.credentials.dig(:swagger_ui, :username)` and password from `Rails.application.credentials.dig(:swagger_ui, :password)`. You can change these values if they don't match with your app.\n", :yellow
|
138
|
+
end
|
139
|
+
|
140
|
+
def show_readme
|
141
|
+
readme "README"
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def validate_api_authentication_options
|
147
|
+
api_authentication_options = options[:api_authentication_options]
|
148
|
+
|
149
|
+
if api_authentication_options.blank?
|
150
|
+
say "api_authentication_options args should be provided for api_key authentication", :red
|
151
|
+
|
152
|
+
abort
|
153
|
+
end
|
154
|
+
|
155
|
+
missing_options = %w[name in] - api_authentication_options.keys
|
156
|
+
|
157
|
+
if missing_options.length.positive?
|
158
|
+
say "Option/s '#{missing_options.join(', ')}' should be present for api_key authentication!", :red
|
159
|
+
say 'Example of valid options: "--api_authentication_options=name:api_key in:query"', :yellow
|
160
|
+
|
161
|
+
abort
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
===============================================================================
|
2
|
+
|
3
|
+
To get up and running with rswag you can do the following next:
|
4
|
+
|
5
|
+
1. Write a rswag spec by following instructions from Getting Started guide at https://github.com/rswag/rswag#getting-started
|
6
|
+
2. Once the spec is ready, generate the swagger file with `rails rswag`
|
7
|
+
3. Run the rails server with `rails s`
|
8
|
+
4. Assuming your app is at "localhost:3000", you will find your API docs at `http://localhost:3000/api-docs/index.html`
|
9
|
+
|
10
|
+
===============================================================================
|
@@ -9,20 +9,24 @@ module Boring
|
|
9
9
|
DEFAULT_RUBY_VERSION = "2.7.1"
|
10
10
|
|
11
11
|
class_option :skip_adding_rubocop_rules, type: :boolean, aliases: "-s",
|
12
|
-
|
13
|
-
class_option :ruby_version,
|
14
|
-
|
12
|
+
desc: "Skip adding rubocop rules and add empty file."
|
13
|
+
class_option :ruby_version, type: :string, aliases: "-v",
|
14
|
+
desc: "Tell us the ruby version which you use for the application. Default to Ruby #{DEFAULT_RUBY_VERSION}", default: DEFAULT_RUBY_VERSION
|
15
|
+
class_option :test_gem, type: :string,
|
16
|
+
desc: "Tell us the framework you use for writing tests in your application. Supported options are ['rspec', 'minitest']"
|
15
17
|
|
16
18
|
def add_rubocop_gems
|
17
19
|
say "Adding rubocop gems", :green
|
18
|
-
|
20
|
+
rubocop_gem_content = <<~RUBY
|
19
21
|
\n
|
20
22
|
\t# A Ruby static code analyzer, based on the community Ruby style guide
|
21
23
|
\tgem "rubocop", require: false
|
22
24
|
\tgem "rubocop-rails", require: false
|
23
25
|
\tgem "rubocop-performance", require: false
|
26
|
+
\tgem "rubocop-rake", require: false
|
27
|
+
#{rubocop_test_gem_content}
|
24
28
|
RUBY
|
25
|
-
insert_into_file "Gemfile",
|
29
|
+
insert_into_file "Gemfile", rubocop_gem_content, after: /group :development do/
|
26
30
|
Bundler.with_unbundled_env do
|
27
31
|
run "bundle install"
|
28
32
|
end
|
@@ -31,9 +35,31 @@ module Boring
|
|
31
35
|
def add_rails_prefered_rubocop_rules
|
32
36
|
say "Adding rubocop style guides", :green
|
33
37
|
@skip_adding_rules = options[:skip_adding_rubocop_rules]
|
34
|
-
@target_ruby_version = options[:ruby_version]
|
38
|
+
@target_ruby_version = options[:ruby_version]
|
35
39
|
template(".rubocop.yml", ".rubocop.yml")
|
36
40
|
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def rubocop_test_gem_content
|
45
|
+
test_gem = options[:test_gem]
|
46
|
+
|
47
|
+
return if test_gem.blank?
|
48
|
+
|
49
|
+
if %w[rspec minitest].exclude?(test_gem)
|
50
|
+
raise(NotImplementedError, "#{test_gem} is not supported as a test_gem option! Supported options are ['rspec', 'minitest']")
|
51
|
+
end
|
52
|
+
|
53
|
+
if test_gem.eql?('rspec')
|
54
|
+
@test_gem_extension = 'rubocop-rspec'
|
55
|
+
|
56
|
+
"\tgem \"rubocop-rspec\", require: false"
|
57
|
+
else
|
58
|
+
@test_gem_extension = 'rubocop-minitest'
|
59
|
+
|
60
|
+
"\tgem \"rubocop-minitest\", require: false"
|
61
|
+
end
|
62
|
+
end
|
37
63
|
end
|
38
64
|
end
|
39
65
|
end
|
@@ -1,8 +1,12 @@
|
|
1
1
|
require:
|
2
2
|
- rubocop-performance
|
3
3
|
- rubocop-rails
|
4
|
+
- rubocop-rake
|
5
|
+
<%- if @test_gem_extension -%>
|
6
|
+
- <%= @test_gem_extension %>
|
7
|
+
<%- end -%>
|
4
8
|
|
5
|
-
<%- unless @skip_adding_rules
|
9
|
+
<%- unless @skip_adding_rules -%>
|
6
10
|
AllCops:
|
7
11
|
TargetRubyVersion: <%= @target_ruby_version %>
|
8
12
|
# RuboCop has a bunch of cops enabled by default. This setting tells RuboCop
|
@@ -258,5 +262,4 @@ Performance/DeletePrefix:
|
|
258
262
|
|
259
263
|
Performance/DeleteSuffix:
|
260
264
|
Enabled: true
|
261
|
-
|
262
|
-
<% end %>
|
265
|
+
<%- end -%>
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Boring
|
3
|
+
module Webmock
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
desc "Adds webmock gem to the application"
|
6
|
+
|
7
|
+
SUPPORTED_TEST_FRAMEWORKS = %w[rspec minitest]
|
8
|
+
|
9
|
+
# can't use "test_framework" option which would be a good naming for this because it's being used by Rails::Generator::Base. It's better not to have any conflict with the base class so prefixing with "app_" here
|
10
|
+
class_option :app_test_framework,
|
11
|
+
type: :string,
|
12
|
+
desc: "Tell us the framework you use for writing tests in your application. Supported options are #{SUPPORTED_TEST_FRAMEWORKS}",
|
13
|
+
default: "minitest"
|
14
|
+
|
15
|
+
def verify_test_framework_configurations
|
16
|
+
app_test_framework = options[:app_test_framework]
|
17
|
+
|
18
|
+
if app_test_framework.blank?
|
19
|
+
say <<~WARNING, :red
|
20
|
+
ERROR: Unsupported test framework: #{app_test_framework}
|
21
|
+
WARNING
|
22
|
+
|
23
|
+
abort
|
24
|
+
else
|
25
|
+
verify_presence_of_test_framework
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_webmock_gem
|
30
|
+
say "Adding webmock gem", :green
|
31
|
+
|
32
|
+
gem "webmock"
|
33
|
+
|
34
|
+
Bundler.with_unbundled_env do
|
35
|
+
run "bundle install"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def configure_webmock
|
40
|
+
app_test_framework = options[:app_test_framework]
|
41
|
+
|
42
|
+
say "Configuring webmock", :green
|
43
|
+
|
44
|
+
if app_test_framework == "minitest"
|
45
|
+
configure_minitest
|
46
|
+
else
|
47
|
+
configure_rspec
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def verify_presence_of_test_framework
|
54
|
+
app_test_framework = options[:app_test_framework]
|
55
|
+
test_framework_folder = { minitest: "test", rspec: "spec" }.dig(app_test_framework.to_sym) || ''
|
56
|
+
|
57
|
+
test_folder_is_present = Dir.exist?(test_framework_folder) && Dir.entries(test_framework_folder).length.positive?
|
58
|
+
|
59
|
+
return if test_folder_is_present
|
60
|
+
|
61
|
+
say "We couldn't find #{test_framework_folder} in your project. Please make sure #{app_test_framework} is configured correctly and run the generator again!", :red
|
62
|
+
|
63
|
+
abort
|
64
|
+
end
|
65
|
+
|
66
|
+
def configure_minitest
|
67
|
+
inject_into_file 'test/test_helper.rb',
|
68
|
+
before: /\n(class|module) ActiveSupport/ do
|
69
|
+
<<~RUBY
|
70
|
+
\nrequire 'webmock/minitest'
|
71
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
72
|
+
RUBY
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def configure_rspec
|
77
|
+
inject_into_file "spec/spec_helper.rb",
|
78
|
+
"require 'webmock/rspec'\n\n",
|
79
|
+
before: /\A/
|
80
|
+
inject_into_file "spec/spec_helper.rb",
|
81
|
+
"\tWebMock.disable_net_connect!(allow_localhost: true)\n\n",
|
82
|
+
after: "RSpec.configure do |config|\n"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Boring
|
4
|
+
module Whenever
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
desc "Adds whenever gem to the application for managing cron jobs"
|
7
|
+
|
8
|
+
def add_whenever_gem
|
9
|
+
say "Adding whenever gem", :green
|
10
|
+
|
11
|
+
Bundler.with_unbundled_env do
|
12
|
+
run "bundle add whenever"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_schedule_file
|
17
|
+
say "Create schedule.rb file", :green
|
18
|
+
|
19
|
+
Bundler.with_unbundled_env do
|
20
|
+
run "bundle exec wheneverize ."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
2.7.
|
1
|
+
2.7.3
|
@@ -1 +1 @@
|
|
1
|
-
require "
|
1
|
+
require "bundler/setup" # Set up gems listed in the Gemfile.
|