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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +2 -2
  3. data/.github/workflows/codeql-analysis.yml +70 -0
  4. data/.gitignore +3 -0
  5. data/CHANGELOG.md +18 -1
  6. data/CONTRIBUTING.md +17 -0
  7. data/Gemfile.lock +9 -11
  8. data/README.md +15 -1
  9. data/lib/boring_generators/version.rb +1 -1
  10. data/lib/generators/boring/bootstrap/install/install_generator.rb +15 -1
  11. data/lib/generators/boring/factory_bot/install/install_generator.rb +46 -0
  12. data/lib/generators/boring/factory_bot/install/templates/users.rb +8 -0
  13. data/lib/generators/boring/faker/install/install_generator.rb +17 -0
  14. data/lib/generators/boring/flipper/install/install_generator.rb +37 -0
  15. data/lib/generators/boring/flipper/install/templates/initializer.rb.tt +19 -0
  16. data/lib/generators/boring/letter_opener/install/install_generator.rb +39 -0
  17. data/lib/generators/boring/overcommit/base_generator.rb +45 -0
  18. data/lib/generators/boring/overcommit/pre_commit/rubocop/install/install_generator.rb +62 -0
  19. data/lib/generators/boring/rspec/install/install_generator.rb +50 -0
  20. data/lib/generators/boring/rswag/install/install_generator.rb +166 -0
  21. data/lib/generators/boring/rswag/install/templates/README +10 -0
  22. data/lib/generators/boring/rubocop/install/install_generator.rb +32 -6
  23. data/lib/generators/boring/rubocop/install/templates/.rubocop.yml.tt +6 -3
  24. data/lib/generators/boring/webmock/install/install_generator.rb +86 -0
  25. data/lib/generators/boring/whenever/install/install_generator.rb +25 -0
  26. data/tmp/templates/app_template/.ruby-version +1 -1
  27. data/tmp/templates/app_template/Gemfile +1 -1
  28. data/tmp/templates/app_template/config/boot.rb +1 -1
  29. data/tmp/templates/app_template/yarn.lock +61 -91
  30. metadata +17 -4
  31. 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
- 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}"
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
- bullet_gem_content = <<~RUBY
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", bullet_gem_content, after: /group :development do/
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] ? options[:ruby_version] : DEFAULT_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.0
1
+ 2.7.3
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
  git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
 
4
- ruby '2.7.0'
4
+ ruby '2.7.3'
5
5
 
6
6
  # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
7
7
  gem 'rails', '~> 6.0.3', '>= 6.0.3.2'
@@ -1 +1 @@
1
- require "rails/all"
1
+ require "bundler/setup" # Set up gems listed in the Gemfile.