modulorails 1.2.1 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 47ac5a151c8230d9ff0e9b775d32bd2a27eddbea284cf30aacf0bc863eb65a47
4
- data.tar.gz: 180b663722790df15a3e180fbfe32a13f8743a57e28f6d74005d93ee08bf98b0
3
+ metadata.gz: 38bfc28b69038bd12e6db5b86c5a81fc29aab339896ee1b2b47429ed6d12c4fe
4
+ data.tar.gz: 0b0a203652556def30c6e3471acd7e35fecf834310d94d21f58766acafaf9f5b
5
5
  SHA512:
6
- metadata.gz: a90d84b0c21e644e07d097e6c00b77af37dbfe1d43b1e1b4f75fd614fc7bc87bf86a93343e1362ab78a4321f1f1081bad4e3605a7c10dee082ab31cc346d102d
7
- data.tar.gz: 9bcdf33285526a1ecca9dee4b05ab6d5f343280f8e9ec34427e428ab52786a11ab3235cf5ed77c5a1eb59163ff1dfb54d905c280068cf0f10032e47379c3c0e6
6
+ metadata.gz: d68c37e214e7e996b586775a4f74c805d78c6d6a9f1745e1abfe38ca323b7ce82265f94c89219f2bfa811c92b02b4c160daa8751097019cc1be919844b184009
7
+ data.tar.gz: 346739b57ded95ac5c96684c4e9d91af1867b4713741d7e71d6484b3ddc68ec651feef1c863c318ab6684f2fa9a93df8ddfb20956880a37e9a87962f21f9414e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  This file is used to list changes made in each version of the gem.
4
4
 
5
+ # 1.3.0
6
+
7
+ - Update redis configuration in generators.
8
+ - Update mailcatcher docker image for better compatibility with ARM64.
9
+ - Remove possible suffix `Service` in service generator.
10
+ - Update rubocop configuration in template.
11
+ - Add a generator to add Sidekiq to a project.
12
+ - Update docker generator to use valid names for environment variables.
13
+
5
14
  # 1.2.1
6
15
 
7
16
  - Update rubocop configuration.
@@ -15,6 +15,7 @@ class Modulorails::DockerGenerator < Rails::Generators::Base
15
15
  template 'entrypoints/docker-entrypoint.sh'
16
16
  chmod 'entrypoints/docker-entrypoint.sh', 0755
17
17
  template 'config/database.yml'
18
+ template 'config/cable.yml'
18
19
 
19
20
  # Useless unless project is using Webpacker
20
21
  if Modulorails.data.webpacker_version.present?
@@ -0,0 +1,15 @@
1
+ redis_local: &redis_local
2
+ adapter: redis
3
+ url: <%= ENV.fetch('REDIS_URL', 'redis://redis:6379') %>
4
+
5
+ development:
6
+ <<: *redis_local
7
+
8
+ test:
9
+ <<: *redis_local
10
+
11
+ staging:
12
+ <<: *redis_local
13
+
14
+ production:
15
+ <<: *redis_local
@@ -1,29 +1,29 @@
1
1
  <%- image_name = Modulorails.data.name.parameterize -%>
2
- <%- upper_image_name = image_name.upcase -%>
2
+ <%- environment_name = Modulorails.data.environment_name -%>
3
3
  <%- adapter = Modulorails.data.adapter -%>
4
4
  <%- if adapter =~ /mysql/ -%>
5
5
  development: &default
6
6
  adapter: mysql2
7
7
  encoding: utf8mb4
8
8
  collation: utf8mb4_unicode_ci
9
- database: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_NAME', '<%= image_name %>') %>
10
- username: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_USERNAME', 'root') %>
11
- password: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_PASSWORD', '') %>
12
- host: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_HOST', 'database') %>
13
- port: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_PORT', 3306) %>
9
+ database: <%%= ENV.fetch('<%= environment_name %>_DATABASE_NAME', '<%= image_name %>') %>
10
+ username: <%%= ENV.fetch('<%= environment_name %>_DATABASE_USERNAME', 'root') %>
11
+ password: <%%= ENV.fetch('<%= environment_name %>_DATABASE_PASSWORD', '') %>
12
+ host: <%%= ENV.fetch('<%= environment_name %>_DATABASE_HOST', 'database') %>
13
+ port: <%%= ENV.fetch('<%= environment_name %>_DATABASE_PORT', 3306) %>
14
14
  <%- else -%>
15
15
  development: &default
16
16
  adapter: postgresql
17
- database: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_NAME', '<%= image_name %>') %>
18
- username: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_USERNAME', 'postgres') %>
19
- password: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_PASSWORD', 'postgres') %>
20
- host: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_HOST', 'database') %>
21
- port: <%%= ENV.fetch('<%= upper_image_name %>_DATABASE_PORT', 5432) %>
17
+ database: <%%= ENV.fetch('<%= environment_name %>_DATABASE_NAME', '<%= image_name %>') %>
18
+ username: <%%= ENV.fetch('<%= environment_name %>_DATABASE_USERNAME', 'postgres') %>
19
+ password: <%%= ENV.fetch('<%= environment_name %>_DATABASE_PASSWORD', 'postgres') %>
20
+ host: <%%= ENV.fetch('<%= environment_name %>_DATABASE_HOST', 'database') %>
21
+ port: <%%= ENV.fetch('<%= environment_name %>_DATABASE_PORT', 5432) %>
22
22
  <%- end -%>
23
23
 
24
24
  test:
25
25
  <<: *default
26
- database: <%%= ENV.fetch('<%= upper_image_name %>_TEST_DATABASE_NAME', '<%= image_name %>_test') %>
26
+ database: <%%= ENV.fetch('<%= environment_name %>_TEST_DATABASE_NAME', '<%= image_name %>_test') %>
27
27
 
28
28
  staging:
29
29
  <<: *default
@@ -1,6 +1,7 @@
1
1
  version: '3.7'
2
2
 
3
3
  <%- image_name = Modulorails.data.name.parameterize -%>
4
+ <%- environment_name = Modulorails.data.environment_name -%>
4
5
  services:
5
6
  app:
6
7
  image: modulotechgroup/<%= image_name %>
@@ -15,9 +16,10 @@ services:
15
16
  environment:
16
17
  RAILS_ENV: production
17
18
  URL: http://localhost:3000
18
- <%= image_name.upcase %>_DATABASE_HOST: database
19
- <%= image_name.upcase %>_DATABASE_NAME: <%= image_name %>
19
+ <%= environment_name %>_DATABASE_HOST: database
20
+ <%= environment_name %>_DATABASE_NAME: <%= image_name %>
20
21
  RAILS_SERVE_STATIC_FILES: 'true'
22
+ REDIS_URL: redis://redis:6379/1
21
23
 
22
24
  <%- adapter = Modulorails.data.adapter -%>
23
25
  <%- if adapter =~ /mysql/ -%>
@@ -1,6 +1,7 @@
1
1
  version: '3.7'
2
2
 
3
3
  <%- image_name = Modulorails.data.name.parameterize -%>
4
+ <%- environment_name = Modulorails.data.environment_name -%>
4
5
  services:
5
6
  app:
6
7
  image: modulotechgroup/<%= image_name %>:dev
@@ -17,8 +18,9 @@ services:
17
18
  environment:
18
19
  RAILS_ENV: development
19
20
  URL: http://localhost:3000
20
- <%= image_name.upcase %>_DATABASE_HOST: database
21
- <%= image_name.upcase %>_DATABASE_NAME: <%= image_name %>
21
+ <%= environment_name %>_DATABASE_HOST: database
22
+ <%= environment_name %>_DATABASE_NAME: <%= image_name %>
23
+ REDIS_URL: redis://redis:6379/1
22
24
  entrypoint: ./entrypoints/docker-entrypoint.sh
23
25
  stdin_open: true
24
26
  tty: true
@@ -50,9 +52,9 @@ services:
50
52
  image: redis:6.2-alpine
51
53
 
52
54
  mailcatcher:
53
- image: tophfr/mailcatcher
55
+ image: dockage/mailcatcher
54
56
  ports:
55
- - 1080:80
57
+ - 1080:1080
56
58
 
57
59
  <%- webpack_container_needed = Modulorails.data.webpacker_version.present? -%>
58
60
  <%- if webpack_container_needed -%>
@@ -1,4 +1,5 @@
1
1
  <%- image_name = Modulorails.data.name.parameterize -%>
2
+ <%- environment_name = Modulorails.data.environment_name -%>
2
3
  include:
3
4
  - project: 'modulosource/modulotech/devops/gitlab-ci-templates'
4
5
  file:
@@ -20,12 +21,12 @@ variables:
20
21
  <%- if adapter =~ /mysql/ -%>
21
22
  MYSQL_DATABASE: <%= image_name %>_test
22
23
  MYSQL_ALLOW_EMPTY_PASSWORD: 'true'
23
- <%= image_name.upcase %>_DATABASE_HOST: mysql
24
+ <%= environment_name %>_DATABASE_HOST: mysql
24
25
  <%- else -%>
25
26
  POSTGRES_DB: <%= image_name %>_test
26
27
  POSTGRES_USER: postgres
27
28
  POSTGRES_PASSWORD: postgres
28
- <%= image_name.upcase %>_DATABASE_HOST: postgres
29
+ <%= environment_name %>_DATABASE_HOST: postgres
29
30
  <%- end -%>
30
31
 
31
32
  stages:
@@ -13,11 +13,7 @@ class Modulorails::HealthCheckGenerator < Rails::Generators::Base
13
13
 
14
14
  # Add the route
15
15
  unless File.read(Rails.root.join('config/routes.rb')).match?('health_check_routes')
16
- inject_into_file 'config/routes.rb', after: "Rails.application.routes.draw do\n" do
17
- <<~'RUBY'
18
- health_check_routes
19
- RUBY
20
- end
16
+ inject_into_file 'config/routes.rb', " health_check_routes\n\n", after: "Rails.application.routes.draw do\n"
21
17
  end
22
18
 
23
19
  # Update the gem and the Gemfile.lock
@@ -83,7 +83,7 @@ HealthCheck.setup do |config|
83
83
  # config.rabbitmq_config = {}
84
84
 
85
85
  # When redis url/password is non-standard
86
- config.redis_url = ENV['REDIS_URL']
86
+ config.redis_url = ENV.fetch('REDIS_URL', 'redis://redis:6379')
87
87
  # Only included if set, as url can optionally include passwords as well
88
88
  # config.redis_password = 'redis_password' # default ENV['REDIS_PASSWORD']
89
89
 
@@ -101,12 +101,12 @@ Metrics/CyclomaticComplexity:
101
101
 
102
102
  # Commonly used screens these days easily fit more than 80 characters.
103
103
  Layout/LineLength:
104
- Max: 100
104
+ Max: 120
105
105
 
106
106
  # Too short methods lead to extraction of single-use methods, which can make
107
107
  # the code easier to read (by naming things), but can also clutter the class
108
108
  Metrics/MethodLength:
109
- Max: 20
109
+ Max: 25
110
110
 
111
111
  # The guiding principle of classes is SRP, SRP can't be accurately measured by LoC
112
112
  Metrics/ClassLength:
@@ -265,3 +265,7 @@ Style/ParallelAssignment:
265
265
  # Checks the style of children definitions at classes and modules.
266
266
  Style/ClassAndModuleChildren:
267
267
  Enabled: false
268
+
269
+ # Useful to display but it really is a bother to change it: hence the `info` severity.
270
+ Rails/I18nLocaleTexts:
271
+ Severity: info
@@ -0,0 +1,14 @@
1
+ Description:
2
+ Generates a new Modulorails service. Pass the service name, either
3
+ CamelCased or under_scored, and a list of parameters as arguments.
4
+
5
+ To create a service within a module, specify the service name as a
6
+ path like 'parent_module/service_name'.
7
+
8
+ This generates a service class in app/services.
9
+
10
+ Example:
11
+ `bin/rails generate modulorails:service Missions::Search word page per`
12
+
13
+ Mission::Search service with positional parameters word, page and per.
14
+ Service: app/services/missions/search_service.rb
@@ -8,8 +8,20 @@ class Modulorails::ServiceGenerator < Rails::Generators::NamedBase
8
8
  desc 'This generator creates a service inheriting Modulorails::BaseService'
9
9
  argument :arguments, type: :array, default: [], banner: 'argument argument'
10
10
 
11
+ check_class_collision suffix: "Service"
12
+
11
13
  def create_service_files
12
14
  template 'service.rb', File.join('app/services', class_path, "#{file_name}_service.rb")
13
15
  end
14
16
 
17
+ private
18
+
19
+ def file_name
20
+ @_file_name ||= remove_possible_suffix(super)
21
+ end
22
+
23
+ def remove_possible_suffix(name)
24
+ name.sub(/_?service$/i, '')
25
+ end
26
+
15
27
  end
@@ -0,0 +1,146 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
4
+
5
+ class Modulorails::SidekiqGenerator < Rails::Generators::Base
6
+
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+ desc 'This generator adds Sidekiq to the project'
10
+
11
+ def add_to_docker_compose
12
+ add_to_docker_compose_yml_file(Rails.root.join('docker-compose.yml'))
13
+ end
14
+
15
+ def add_to_docker_compose_prod
16
+ add_to_docker_compose_yml_file(Rails.root.join('docker-compose.prod.yml'))
17
+ end
18
+
19
+ def add_to_gemfile
20
+ gemfile_path = Rails.root.join('Gemfile')
21
+
22
+ # Add gem redis unless already present
23
+ unless File.read(gemfile_path).match?(/^\s*gem ['"]redis['"]/)
24
+ append_to_file(gemfile_path, "gem 'redis'\n")
25
+ end
26
+
27
+ # Add gem sidekiq unless already present
28
+ unless File.read(gemfile_path).match?(/^\s*gem ['"]sidekiq['"]/)
29
+ append_to_file(gemfile_path, "gem 'sidekiq'\n")
30
+ end
31
+ end
32
+
33
+ def add_to_config
34
+ Dir.glob(Rails.root.join('config/environments/*.rb')) do |file|
35
+ add_to_config_file(file)
36
+ end
37
+ end
38
+
39
+ def add_initializer
40
+ template 'config/initializers/sidekiq.rb'
41
+ end
42
+
43
+ def add_routes
44
+ routes_path = Rails.root.join('config/routes.rb')
45
+
46
+ unless File.read(routes_path).match?(%r{require ['"]sidekiq/web["']})
47
+ inject_into_file routes_path, after: "Rails.application.routes.draw do\n" do
48
+ <<-RUBY
49
+ require 'sidekiq/web'
50
+ mount Sidekiq::Web => '/sidekiq'
51
+
52
+ RUBY
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_health_check
58
+ file_path = Rails.root.join('config/initializers/health_check.rb')
59
+
60
+ unless File.read(file_path).match?(%r{add_custom_check\s*\(?\s*['"]sidekiq-queues['"]\s*\)?})
61
+ inject_into_file file_path, after: /^HealthCheck.setup do \|config\|\n$/ do
62
+ <<-RUBY
63
+
64
+ # Add one or more custom checks that return a blank string if ok, or an error message if there is an error
65
+ config.add_custom_check('sidekiq-queues') do
66
+ queues = Sidekiq::Queue.all
67
+
68
+ # No queues, means no jobs, ok!
69
+ next '' if queues.empty?
70
+
71
+ enqueued_jobs_count = queues.each.map { |queue| queue.count }.sum
72
+
73
+ # Less than 200 enqueued jobs, ok!
74
+ enqueued_jobs_count < 200 ? '' : "\#{enqueued_jobs_count} are currently enqueued."
75
+ end
76
+
77
+ # Add one or more custom checks that return a blank string if ok, or an error message if there is an error
78
+ config.add_custom_check('sidekiq-retries') do
79
+ retry_jobs_count = Sidekiq::RetrySet.new.count
80
+
81
+ # Less than 200 jobs to retry, ok!
82
+ retry_jobs_count < 200 ? '' : "\#{retry_jobs_count} are waiting for retry."
83
+ end
84
+ RUBY
85
+ end
86
+ end
87
+ end
88
+
89
+ def add_entrypoint
90
+ template 'entrypoints/sidekiq-entrypoint.sh'
91
+ chmod 'entrypoints/sidekiq-entrypoint.sh', 0755
92
+ end
93
+
94
+ private
95
+
96
+ def add_to_docker_compose_yml_file(file_path)
97
+ @image_name ||= Modulorails.data.name.parameterize
98
+
99
+ # Create docker-compose.yml unless present
100
+ unless File.exist?(file_path)
101
+ # Modulorails::GitlabciGenerator.new([], {}, {}).invoke_all
102
+ invoke(Modulorails::DockerGenerator, [])
103
+ end
104
+
105
+ return if File.read(file_path).match?(/^ {2}sidekiq:$/)
106
+
107
+ insert_into_file file_path, after: /^services:/ do
108
+ <<-YAML
109
+
110
+ sidekiq:
111
+ image: modulotechgroup/#{@image_name}:dev
112
+ build:
113
+ context: .
114
+ dockerfile: Dockerfile
115
+ depends_on:
116
+ - database
117
+ - redis
118
+ volumes:
119
+ - .:/app
120
+ environment:
121
+ RAILS_ENV: development
122
+ URL: http://app:3000
123
+ #{@image_name.upcase}_DATABASE_HOST: database
124
+ #{@image_name.upcase}_DATABASE_NAME: #{@image_name}
125
+ REDIS_URL: redis://redis:6379/1
126
+ entrypoint: ./entrypoints/sidekiq-entrypoint.sh
127
+ stdin_open: true
128
+ tty: true
129
+ YAML
130
+ end
131
+ end
132
+
133
+ def add_to_config_file(file_path)
134
+ pattern = /^(?>\s*)(?>#\s*)?(\w+)\.active_job\.queue_adapter = .+$/
135
+
136
+ if File.read(file_path).match?(pattern)
137
+ gsub_file file_path, pattern, ' \1.active_job.queue_adapter = :sidekiq'
138
+ else
139
+ append_file file_path, after: "configure do\n" do
140
+ <<-RUBY
141
+ config.active_job.queue_adapter = :sidekiq
142
+ RUBY
143
+ end
144
+ end
145
+ end
146
+ end
@@ -0,0 +1,9 @@
1
+ redis_url = Rails.application.config_for('cable')['url']
2
+
3
+ Sidekiq.configure_server do |config|
4
+ config.redis = { url: redis_url }
5
+ end
6
+
7
+ Sidekiq.configure_client do |config|
8
+ config.redis = { url: redis_url }
9
+ end
@@ -0,0 +1,7 @@
1
+ #!/bin/sh
2
+
3
+ # Exit immediately if a command exits with a non-zero status
4
+ set -e
5
+
6
+ # Launch Sidekiq
7
+ exec ./bin/bundle exec sidekiq
@@ -15,6 +15,7 @@ module Modulorails
15
15
  bundler_version modulorails_version adapter db_version adapter_version webpacker_version
16
16
  importmap_version jsbundling_version
17
17
  production_url staging_url review_base_url
18
+ environment_name
18
19
  ].freeze
19
20
 
20
21
  # Useful if the gem's user need to read one of the data
@@ -73,6 +74,9 @@ module Modulorails
73
74
  # The name is the usual name of the project, the one used in conversations at Modulotech
74
75
  @name = configuration.name
75
76
 
77
+ # A version of the name suitable to name environment variables
78
+ @environment_name = @name.parameterize.gsub('-', '_').gsub(/\b(\d)/, 'MT_\1').upcase
79
+
76
80
  # The main developer, the lead developer, in short the developer to call when something's
77
81
  # wrong with the application ;)
78
82
  @main_developer = configuration.main_developer
@@ -1,6 +1,6 @@
1
1
  module Modulorails
2
2
 
3
- VERSION = '1.2.1'.freeze
3
+ VERSION = '1.3.0'.freeze
4
4
 
5
5
  # Useful to compare the current Ruby version
6
6
  COMPARABLE_RUBY_VERSION = Gem::Version.new(RUBY_VERSION)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modulorails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu Ciappara
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-09 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: git
@@ -202,6 +202,7 @@ files:
202
202
  - lib/generators/modulorails/docker/docker_generator.rb
203
203
  - lib/generators/modulorails/docker/templates/Dockerfile.prod.tt
204
204
  - lib/generators/modulorails/docker/templates/Dockerfile.tt
205
+ - lib/generators/modulorails/docker/templates/config/cable.yml.tt
205
206
  - lib/generators/modulorails/docker/templates/config/database.yml.tt
206
207
  - lib/generators/modulorails/docker/templates/docker-compose.prod.yml.tt
207
208
  - lib/generators/modulorails/docker/templates/docker-compose.yml.tt
@@ -216,8 +217,12 @@ files:
216
217
  - lib/generators/modulorails/rubocop/rubocop_generator.rb
217
218
  - lib/generators/modulorails/rubocop/templates/rubocop.yml.tt
218
219
  - lib/generators/modulorails/self_update/self_update_generator.rb
220
+ - lib/generators/modulorails/service/USAGE
219
221
  - lib/generators/modulorails/service/service_generator.rb
220
222
  - lib/generators/modulorails/service/templates/service.rb.tt
223
+ - lib/generators/modulorails/sidekiq/sidekiq_generator.rb
224
+ - lib/generators/modulorails/sidekiq/templates/config/initializers/sidekiq.rb.tt
225
+ - lib/generators/modulorails/sidekiq/templates/entrypoints/sidekiq-entrypoint.sh.tt
221
226
  - lib/modulorails.rb
222
227
  - lib/modulorails/configuration.rb
223
228
  - lib/modulorails/data.rb