modulorails 1.2.1 → 1.3.0

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