boring_generators 0.11.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
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.