capistrano-sidekiq 2.3.1 → 3.0.0.alpha.1

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: 69c753e231935baa29ba10cec37dba7dda56f3b4bc143313ea0704f3be234823
4
- data.tar.gz: e95c44603f7696cd95b985f9fcb22918d16653eaf1b2acce45ddaaef48b8425f
3
+ metadata.gz: 1d2fab3d52e0ca2c2fdb94e71d21d87e543a3f605f4f822b4c8bf2794c5f8144
4
+ data.tar.gz: 2ede4bc9269188112bef354fc06e2fa7ddb6f1f8de1db57a3dc2cf24da10095f
5
5
  SHA512:
6
- metadata.gz: 62ec5153286616b7843061a9e447fd43c9c155125152d29695ef894570d6049905c4a65d676aed50b62384bd1c6b440f596c2b2ff2b5e3b3c87d230986e51d7c
7
- data.tar.gz: bc0dd086283e7eaaef125571e36fb4124f022bcae0700642705d2f45699f71883351c68d4405be068450af046d3717fb82545fd5aa0c276e36f6dff8ee56d9c1
6
+ metadata.gz: c6651700dda4403c8b3e23d2da8f2d7c685c8ae36311cfdea998a1e731de7b87279ad0a354ba9d9da537f10c6735a2e8277f24f04e4a6748d9f70ce63617232c
7
+ data.tar.gz: adacca94a04e2a3ae569e4e94152b1b0a75c345a182aa7595776d75f3c7df789942539ea280a1545361b4610e4ba8e8cb23d72962ab1482a8a2ae26f2a3568e0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased](https://github.com/seuros/capistrano-sidekiq/compare/v2.3.0...master)
4
+ - Rewrite to match capistrano3-puma api
5
+ - Add support for multiple sidekiq configs (processes and queues can be configured with erb)
6
+ - Add support to multiple EnvironmentFile
7
+ - Add support to multiple EnvironmentVariables
8
+ - Default role for sidekiq is now :worker instead of :app
9
+
3
10
  ## [2.3.0](https://github.com/seuros/capistrano-sidekiq/tree/2.3.0) (2022-05-17)
4
11
 
5
12
  [Full Changelog](https://github.com/seuros/capistrano-sidekiq/compare/v2.2.0...2.3.0)
data/README.md CHANGED
@@ -16,78 +16,27 @@ And then execute:
16
16
  ## Usage
17
17
  ```ruby
18
18
  # Capfile
19
-
20
19
  require 'capistrano/sidekiq'
21
20
  install_plugin Capistrano::Sidekiq # Default sidekiq tasks
22
21
  # Then select your service manager
23
22
  install_plugin Capistrano::Sidekiq::Systemd
24
- # or
25
- install_plugin Capistrano::Sidekiq::Monit # tests needed
26
23
  ```
27
24
 
28
-
29
25
  Configurable options - Please ensure you check your version's branch for the available settings - shown here with defaults:
30
26
 
31
27
  ```ruby
32
- :sidekiq_roles => :app
28
+ :sidekiq_roles => :worker
33
29
  :sidekiq_default_hooks => true
34
- :sidekiq_pid => File.join(shared_path, 'tmp', 'pids', 'sidekiq.pid') # ensure this path exists in production before deploying.
35
30
  :sidekiq_env => fetch(:rack_env, fetch(:rails_env, fetch(:stage)))
36
- :sidekiq_log => File.join(shared_path, 'log', 'sidekiq.log')
37
31
  # single config
38
- :sidekiq_config => 'config/sidekiq.yml'
39
- # per process config - process 1, process 2,... etc.
40
- :sidekiq_config => [
41
- 'config/sidekiq_config1.yml',
42
- 'config/sidekiq_config2.yml'
43
- ]
44
- :sidekiq_concurrency => 25
45
- :sidekiq_queue => %w(default high low)
46
- :sidekiq_processes => 1 # number of systemd processes you want to start
47
-
48
- # sidekiq systemd options
49
- :sidekiq_service_templates_path => 'config/deploy/templates' # to be used if a custom template is needed (filaname should be #{fetch(:sidekiq_service_unit_name)}.service.capistrano.erb or sidekiq.service.capistrano.erb
50
- :sidekiq_service_unit_name => 'sidekiq'
51
- :sidekiq_service_unit_user => :user # :system
52
- :sidekiq_enable_lingering => true
53
- :sidekiq_lingering_user => nil
54
-
55
- # sidekiq monit
56
- :sidekiq_monit_templates_path => 'config/deploy/templates'
57
- :sidekiq_monit_conf_dir => '/etc/monit/conf.d'
58
- :sidekiq_monit_use_sudo => true
59
- :monit_bin => '/usr/bin/monit'
60
- :sidekiq_monit_default_hooks => true
61
- :sidekiq_monit_group => nil
62
- :sidekiq_service_name => "sidekiq_#{fetch(:application)}"
63
-
64
- :sidekiq_user => nil #user to run sidekiq as
65
- ```
66
- See `capistrano/sidekiq/helpers.rb` for other undocumented configuration settings.
67
-
68
- ## Bundler
69
-
70
- If you'd like to prepend `bundle exec` to your sidekiq and sidekiqctl calls, modify the SSHKit command maps
71
- in your deploy.rb file:
72
- ```ruby
73
- SSHKit.config.command_map[:sidekiq] = "bundle exec sidekiq"
74
- SSHKit.config.command_map[:sidekiqctl] = "bundle exec sidekiqctl"
75
- ```
76
-
77
-
78
- ## Customizing the monit sidekiq templates
79
-
80
- If you need change some config in redactor, you can
81
-
82
- ```
83
- bundle exec rails generate capistrano:sidekiq:monit:template
32
+ :sidekiq_config_files, ['sidekiq.yml']
33
+ # multiple configs
34
+ :sidekiq_config_files, ['sidekiq.yml', 'sidekiq-2.yml'] # you can also set it per server
84
35
  ```
85
36
 
86
- If your deploy user has no need in `sudo` for using monit, you can disable it as follows:
37
+ ## Example
87
38
 
88
- ```ruby
89
- set :sidekiq_monit_use_sudo, false
90
- ```
39
+ A sample application is provided to show how to use this gem at https://github.com/seuros/capistrano-example-app
91
40
 
92
41
  ## Configuring the log files on systems with less recent Systemd versions
93
42
 
@@ -2,18 +2,45 @@
2
2
 
3
3
  module Capistrano
4
4
  class Sidekiq::Systemd < Capistrano::Plugin
5
- include Sidekiq::Helpers
6
-
5
+ include SidekiqCommon
6
+ def define_tasks
7
+ eval_rakefile File.expand_path('../tasks/systemd.rake', __dir__)
8
+ end
7
9
  def set_defaults
8
- set_if_empty :sidekiq_service_unit_name, 'sidekiq' # This will change in version 3.0.0 to {application}_sidekiq_{stage}
9
- set_if_empty :sidekiq_service_unit_user, :user # :system
10
- set_if_empty :sidekiq_enable_lingering, true
11
- set_if_empty :sidekiq_lingering_user, nil
12
- set_if_empty :sidekiq_service_templates_path, 'config/deploy/templates'
10
+ set_if_empty :systemctl_bin, '/bin/systemctl'
11
+ set_if_empty :service_unit_user, :user
12
+ set_if_empty :systemctl_user, fetch(:service_unit_user, :user) == :user
13
+
14
+ set_if_empty :sidekiq_service_unit_name, -> { "#{fetch(:application)}_sidekiq_#{fetch(:stage)}" }
15
+ set_if_empty :sidekiq_lingering_user, -> { fetch(:lingering_user, fetch(:user)) }
16
+
17
+ ## Sidekiq could have a stripped down or more complex version of the environment variables
18
+ set_if_empty :sidekiq_service_unit_env_files, -> { fetch(:service_unit_env_files, []) }
19
+ set_if_empty :sidekiq_service_unit_env_vars, -> { fetch(:service_unit_env_vars, []) }
20
+
21
+ set_if_empty :sidekiq_service_templates_path, fetch(:service_templates_path, 'config/deploy/templates')
13
22
  end
14
23
 
15
- def define_tasks
16
- eval_rakefile File.expand_path('../tasks/systemd.rake', __dir__)
24
+ def systemd_command(*args)
25
+ command = [fetch(:systemctl_bin)]
26
+
27
+ unless fetch(:service_unit_user) == :system
28
+ command << "--user"
29
+ end
30
+
31
+ command + args
32
+ end
33
+
34
+ def sudo_if_needed(*command)
35
+ if fetch(:service_unit_user) == :system
36
+ backend.sudo command.map(&:to_s).join(" ")
37
+ else
38
+ backend.execute(*command)
39
+ end
40
+ end
41
+
42
+ def execute_systemd(*args)
43
+ sudo_if_needed(*systemd_command(*args))
17
44
  end
18
45
  end
19
46
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capistrano
4
- SidekiqVERSION = '2.3.1'
4
+ SidekiqVERSION = '3.0.0.alpha.1'
5
5
  end
@@ -4,6 +4,51 @@ require 'capistrano/bundler'
4
4
  require 'capistrano/plugin'
5
5
 
6
6
  module Capistrano
7
+ module SidekiqCommon
8
+ def compiled_template(config_file = "sidekiq.yml")
9
+ @config_file = config_file
10
+ local_template_directory = fetch(:sidekiq_service_templates_path)
11
+ search_paths = [
12
+ File.join(local_template_directory, 'sidekiq.service.capistrano.erb'),
13
+ File.expand_path(
14
+ File.join(*%w[.. templates sidekiq.service.capistrano.erb]),
15
+ __FILE__
16
+ )
17
+ ]
18
+ template_path = search_paths.detect { |path| File.file?(path) }
19
+ template = File.read(template_path)
20
+ ERB.new(template, trim_mode: '-').result(binding)
21
+ end
22
+
23
+ def expanded_bundle_path
24
+ backend.capture(:echo, SSHKit.config.command_map[:bundle]).strip
25
+ end
26
+
27
+ def sidekiq_config
28
+ "--config config/#{@config_file}" if @config_file != "sidekiq.yml"
29
+ end
30
+
31
+ def switch_user(role, &block)
32
+ su_user = sidekiq_user(role)
33
+ if su_user == role.user
34
+ yield
35
+ else
36
+ as su_user, &block
37
+ end
38
+ end
39
+
40
+ def sidekiq_user(role = nil)
41
+ if role.nil?
42
+ fetch(:sidekiq_user)
43
+ else
44
+ properties = role.properties
45
+ properties.fetch(:sidekiq_user) || # local property for sidekiq only
46
+ fetch(:sidekiq_user) ||
47
+ properties.fetch(:run_as) || # global property across multiple capistrano gems
48
+ role.user
49
+ end
50
+ end
51
+ end
7
52
  class Sidekiq < Capistrano::Plugin
8
53
  def define_tasks
9
54
  eval_rakefile File.expand_path('tasks/sidekiq.rake', __dir__)
@@ -13,9 +58,14 @@ module Capistrano
13
58
  set_if_empty :sidekiq_default_hooks, true
14
59
 
15
60
  set_if_empty :sidekiq_env, -> { fetch(:rack_env, fetch(:rails_env, fetch(:rake_env, fetch(:stage)))) }
16
- set_if_empty :sidekiq_roles, fetch(:sidekiq_role, :app)
61
+ set_if_empty :sidekiq_roles, fetch(:sidekiq_role, :worker)
62
+ set_if_empty :sidekiq_configs, %w[sidekiq] # sidekiq.yml
63
+
17
64
  set_if_empty :sidekiq_log, -> { File.join(shared_path, 'log', 'sidekiq.log') }
18
- set_if_empty :sidekiq_error_log, -> { File.join(shared_path, 'log', 'sidekiq.error.log') }
65
+ set_if_empty :sidekiq_error_log, -> { File.join(shared_path, 'log', 'sidekiq.log') }
66
+
67
+ set_if_empty :sidekiq_config_files, ['sidekiq.yml']
68
+
19
69
  # Rbenv, Chruby, and RVM integration
20
70
  append :rbenv_map_bins, 'sidekiq', 'sidekiqctl'
21
71
  append :rvm_map_bins, 'sidekiq', 'sidekiqctl'
@@ -26,6 +76,4 @@ module Capistrano
26
76
  end
27
77
  end
28
78
 
29
- require_relative 'sidekiq/helpers'
30
79
  require_relative 'sidekiq/systemd'
31
- require_relative 'sidekiq/monit'
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  git_plugin = self
@@ -7,59 +6,17 @@ namespace :sidekiq do
7
6
  standard_actions = {
8
7
  start: 'Start Sidekiq',
9
8
  stop: 'Stop Sidekiq (graceful shutdown within timeout, put unfinished tasks back to Redis)',
10
- status: 'Get Sidekiq Status'
9
+ status: 'Get Sidekiq Status',
10
+ restart: 'Restart Sidekiq'
11
11
  }
12
12
  standard_actions.each do |command, description|
13
13
  desc description
14
14
  task command do
15
15
  on roles fetch(:sidekiq_roles) do |role|
16
16
  git_plugin.switch_user(role) do
17
- git_plugin.systemctl_command(command)
18
- end
19
- end
20
- end
21
- end
22
-
23
- desc 'Restart Sidekiq (Quiet, Wait till workers finish or 30 seconds, Stop, Start)'
24
- task :restart do
25
- on roles fetch(:sidekiq_roles) do |role|
26
- git_plugin.switch_user(role) do
27
- git_plugin.quiet_sidekiq
28
- git_plugin.process_block do |process|
29
- start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
30
- running = nil
31
-
32
- # get running workers
33
- while (running.nil? || running > 0) && git_plugin.duration(start_time) < 30 do
34
- command_args =
35
- if fetch(:sidekiq_service_unit_user) == :system
36
- [:sudo, 'systemd-cgls']
37
- else
38
- ['systemd-cgls', '--user']
39
- end
40
- # need to pipe through tr -cd... to strip out systemd colors or you
41
- # get log error messages for non UTF-8 characters.
42
- command_args.push(
43
- '-u', "#{git_plugin.sidekiq_service_unit_name(process: process)}.service",
44
- '|', 'tr -cd \'\11\12\15\40-\176\''
45
- )
46
- status = capture(*command_args, raise_on_non_zero_exit: false)
47
- status_match = status.match(/\[(?<running>\d+) of (?<total>\d+) busy\]/)
48
- break unless status_match
49
-
50
- running = status_match[:running]&.to_i
51
-
52
- colors = SSHKit::Color.new($stdout)
53
- if running.zero?
54
- info colors.colorize("✔ Process ##{process}: No running workers. Shutting down for restart!", :green)
55
- else
56
- info colors.colorize("⧗ Process ##{process}: Waiting for #{running} workers.", :yellow)
57
- sleep(1)
58
- end
17
+ git_plugin.config_files(role).each do |config_file|
18
+ git_plugin.execute_systemd(command, git_plugin.sidekiq_service_file_name(config_file))
59
19
  end
60
-
61
- git_plugin.systemctl_command(:stop, process: process)
62
- git_plugin.systemctl_command(:start, process: process)
63
20
  end
64
21
  end
65
22
  end
@@ -69,229 +26,121 @@ namespace :sidekiq do
69
26
  task :quiet do
70
27
  on roles fetch(:sidekiq_roles) do |role|
71
28
  git_plugin.switch_user(role) do
72
- git_plugin.quiet_sidekiq
29
+ git_plugin.quiet_sidekiq(role)
73
30
  end
74
31
  end
75
32
  end
76
33
 
77
- desc 'Install systemd sidekiq service'
34
+ desc 'Install Sidekiq systemd service'
78
35
  task :install do
79
36
  on roles fetch(:sidekiq_roles) do |role|
80
37
  git_plugin.switch_user(role) do
81
- git_plugin.create_systemd_template
82
- if git_plugin.config_per_process?
83
- git_plugin.process_block do |process|
84
- git_plugin.create_systemd_config_symlink(process)
85
- end
86
- end
87
- git_plugin.systemctl_command(:enable)
88
-
89
- if fetch(:sidekiq_service_unit_user) != :system && fetch(:sidekiq_enable_lingering)
90
- execute :loginctl, 'enable-linger', fetch(:sidekiq_lingering_user)
91
- end
38
+ git_plugin.create_systemd_template(role)
92
39
  end
93
40
  end
41
+ invoke 'sidekiq:enable'
94
42
  end
95
43
 
96
- desc 'Uninstall systemd sidekiq service'
44
+ desc 'Uninstall Sidekiq systemd service'
97
45
  task :uninstall do
46
+ invoke 'sidekiq:disable'
98
47
  on roles fetch(:sidekiq_roles) do |role|
99
48
  git_plugin.switch_user(role) do
100
- git_plugin.systemctl_command(:stop)
101
- git_plugin.systemctl_command(:disable)
102
- if git_plugin.config_per_process?
103
- git_plugin.process_block do |process|
104
- git_plugin.delete_systemd_config_symlink(process)
105
- end
106
- end
107
- execute :sudo, :rm, '-f', File.join(
108
- fetch(:service_unit_path, git_plugin.fetch_systemd_unit_path),
109
- git_plugin.sidekiq_service_file_name
110
- )
49
+ git_plugin.rm_systemd_service(role)
111
50
  end
112
51
  end
113
52
  end
114
53
 
115
- desc 'Generate service_locally'
116
- task :generate_service_locally do
117
- run_locally do
118
- File.write('sidekiq', git_plugin.compiled_template)
119
- end
120
- end
54
+ desc 'Enable Sidekiq systemd service'
55
+ task :enable do
56
+ on roles(fetch(:sidekiq_roles)) do |role|
57
+ git_plugin.config_files(role).each do |config_file|
58
+ git_plugin.execute_systemd("enable", git_plugin.sidekiq_service_file_name(config_file))
59
+ end
121
60
 
122
- def fetch_systemd_unit_path
123
- if fetch(:sidekiq_service_unit_user) == :system
124
- # if the path is not standard `set :service_unit_path`
125
- '/etc/systemd/system/'
126
- else
127
- home_dir = backend.capture :pwd
128
- File.join(home_dir, '.config', 'systemd', 'user')
61
+ if fetch(:systemctl_user) && fetch(:sidekiq_lingering_user)
62
+ execute :loginctl, "enable-linger", fetch(:puma_lingering_user)
63
+ end
129
64
  end
130
65
  end
131
66
 
132
- def compiled_template
133
- local_template_directory = fetch(:sidekiq_service_templates_path)
134
- search_paths = [
135
- File.join(local_template_directory, "#{fetch(:sidekiq_service_unit_name)}.service.capistrano.erb"),
136
- File.join(local_template_directory, 'sidekiq.service.capistrano.erb'),
137
- File.expand_path(
138
- File.join(*%w[.. .. .. generators capistrano sidekiq systemd templates sidekiq.service.capistrano.erb]),
139
- __FILE__
140
- )
141
- ]
142
- template_path = search_paths.detect { |path| File.file?(path) }
143
- template = File.read(template_path)
144
- ERB.new(template).result(binding)
67
+ desc 'Disable Sidekiq systemd service'
68
+ task :disable do
69
+ on roles(fetch(:sidekiq_roles)) do |role|
70
+ git_plugin.config_files(role).each do |config_file|
71
+ git_plugin.execute_systemd("disable", git_plugin.sidekiq_service_file_name(config_file))
72
+ end
73
+ end
145
74
  end
146
75
 
147
- def create_systemd_template
148
- ctemplate = compiled_template
149
- systemd_path = fetch(:service_unit_path, fetch_systemd_unit_path)
150
- backend.execute :mkdir, '-p', systemd_path if fetch(:sidekiq_service_unit_user) == :user
151
-
152
- if sidekiq_processes > 1
153
- range = 1..sidekiq_processes
76
+ def fetch_systemd_unit_path
77
+ if fetch(:puma_systemctl_user) == :system
78
+ "/etc/systemd/system/"
154
79
  else
155
- range = 0..0
156
- end
157
- range.each do |index|
158
- temp_file_name = File.join('/tmp', sidekiq_service_file_name(index))
159
- systemd_file_name = File.join(systemd_path, sidekiq_service_file_name(index))
160
- backend.upload!(StringIO.new(ctemplate), temp_file_name)
161
-
162
- if fetch(:sidekiq_service_unit_user) == :system
163
- backend.execute :sudo, :mv, temp_file_name, systemd_file_name
164
- backend.execute :sudo, :systemctl, 'daemon-reload'
165
- else
166
- backend.execute :mv, temp_file_name, systemd_file_name
167
- backend.execute :systemctl, '--user', 'daemon-reload'
168
- end
80
+ home_dir = backend.capture :pwd
81
+ File.join(home_dir, ".config", "systemd", "user")
169
82
  end
170
83
  end
171
84
 
172
- def create_systemd_config_symlink(process)
173
- config = fetch(:sidekiq_config)
174
- return unless config
175
-
176
- process_config = config[process - 1]
177
- if process_config.nil?
178
- backend.error(
179
- "No configuration for Process ##{process} found. "\
180
- 'Please make sure you have 1 item in :sidekiq_config for each process.'
181
- )
182
- exit 1
85
+ def create_systemd_template(role)
86
+ systemd_path = fetch(:service_unit_path, fetch_systemd_unit_path)
87
+ backend.execute :mkdir, '-p', systemd_path if fetch(:systemctl_user)
88
+
89
+ config_files(role).each do |config_file|
90
+ ctemplate = compiled_template(config_file)
91
+ temp_file_name = File.join('/tmp', "sidekiq.#{config_file}.service")
92
+ systemd_file_name = File.join(systemd_path, sidekiq_service_file_name(config_file))
93
+ backend.upload!(StringIO.new(ctemplate), temp_file_name)
94
+ if fetch(:systemctl_user)
95
+ warn "Moving #{temp_file_name} to #{systemd_file_name}"
96
+ backend.execute :mv, temp_file_name, systemd_file_name
97
+ else
98
+ warn "Installing #{systemd_file_name} as root"
99
+ backend.execute :sudo, :mv, temp_file_name, systemd_file_name
100
+ end
183
101
  end
184
-
185
- base_path = fetch(:deploy_to)
186
- config_link_base_path = File.join(base_path, 'shared', 'sidekiq_systemd')
187
- config_link_path = File.join(
188
- config_link_base_path, sidekiq_systemd_config_name(process)
189
- )
190
- process_config_path = File.join(base_path, 'current', process_config)
191
-
192
- backend.execute :mkdir, '-p', config_link_base_path
193
- backend.execute :ln, '-sf', process_config_path, config_link_path
194
102
  end
195
103
 
196
- def delete_systemd_config_symlink(process)
197
- config_link_path = File.join(
198
- fetch(:deploy_to), 'shared', 'sidekiq_systemd',
199
- sidekiq_systemd_config_name(process)
200
- )
201
- backend.execute :rm, config_link_path, raise_on_non_zero_exit: false
202
- end
104
+ def rm_systemd_service(role)
105
+ systemd_path = fetch(:service_unit_path, fetch_systemd_unit_path)
203
106
 
204
- def systemctl_command(*args, process: nil)
205
- execute_array =
206
- if fetch(:sidekiq_service_unit_user) == :system
207
- %i[sudo systemctl]
107
+ config_files(role).each do |config_file|
108
+ systemd_file_name = File.join(systemd_path, sidekiq_service_file_name(config_file))
109
+ if fetch(:systemctl_user)
110
+ warn "Deleting #{systemd_file_name}"
111
+ backend.execute :rm, "-f", systemd_file_name
208
112
  else
209
- [:systemctl, '--user']
113
+ warn "Deleting #{systemd_file_name} as root"
114
+ backend.execute :sudo, :rm, "-f", systemd_file_name
210
115
  end
211
- if process && sidekiq_processes > 1
212
- execute_array.push(
213
- *args, sidekiq_service_unit_name(process: process)
214
- ).flatten
215
- else
216
- execute_array.push(*args, sidekiq_service_unit_name).flatten
217
116
  end
218
- backend.execute(*execute_array, raise_on_non_zero_exit: false)
219
- end
220
-
221
- def quiet_sidekiq
222
- systemctl_command(:kill, '-s', :TSTP)
223
117
  end
224
118
 
225
- def switch_user(role, &block)
226
- su_user = sidekiq_user
227
- if su_user != role.user
228
- yield
229
- else
230
- backend.as su_user, &block
119
+ def quiet_sidekiq(role)
120
+ config_files(role).each do |config_file|
121
+ sidekiq_service = sidekiq_service_unit_name(config_file)
122
+ warn "Quieting #{sidekiq_service}"
123
+ execute_systemd("kill -s TSTP", sidekiq_service)
231
124
  end
232
125
  end
233
126
 
234
- def sidekiq_user
235
- fetch(:sidekiq_user, fetch(:run_as))
236
- end
237
-
238
- def sidekiq_config
239
- config = fetch(:sidekiq_config)
240
- return unless config
241
-
242
- if config_per_process?
243
- config = File.join(
244
- fetch(:deploy_to), 'shared', 'sidekiq_systemd',
245
- sidekiq_systemd_config_name
246
- )
247
- end
248
- "--config #{config}"
249
- end
250
-
251
- def sidekiq_concurrency
252
- "--concurrency #{fetch(:sidekiq_concurrency)}" if fetch(:sidekiq_concurrency)
253
- end
254
-
255
- def sidekiq_processes
256
- fetch(:sidekiq_processes, 1)
257
- end
258
-
259
- def sidekiq_queues
260
- Array(fetch(:sidekiq_queue)).map do |queue|
261
- "--queue #{queue}"
262
- end.join(' ')
263
- end
264
-
265
- def sidekiq_service_file_name(index = nil)
266
- return "#{fetch(:sidekiq_service_unit_name)}.service" if index.to_i.zero?
267
- "#{fetch(:sidekiq_service_unit_name)}@#{index}.service"
268
- end
269
-
270
- def sidekiq_service_unit_name(process: nil)
271
- if process && sidekiq_processes > 1
272
- "#{fetch(:sidekiq_service_unit_name)}@#{process}"
127
+ def sidekiq_service_unit_name(config_file)
128
+ if config_file != "sidekiq.yml"
129
+ fetch(:sidekiq_service_unit_name) + "." + config_file.split(".")[0..-2].join(".")
273
130
  else
274
131
  fetch(:sidekiq_service_unit_name)
275
132
  end
276
133
  end
277
134
 
278
- # process = 1 | sidekiq_systemd_1.yaml
279
- # process = nil | sidekiq_systemd_%i.yaml
280
- def sidekiq_systemd_config_name(process = nil)
281
- "sidekiq_systemd_#{(process&.to_s || '%i')}.yaml"
282
- end
135
+ def sidekiq_service_file_name(config_file)
136
+ ## Remove the extension
137
+ config_file = config_file.split('.')[0..-1].join('.')
283
138
 
284
- def config_per_process?
285
- fetch(:sidekiq_config).is_a?(Array)
286
- end
287
-
288
- def process_block
289
- (1..sidekiq_processes).each do |process|
290
- yield(process)
291
- end
139
+ "#{sidekiq_service_unit_name(config_file)}.service"
292
140
  end
293
141
 
294
- def duration(start_time)
295
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
142
+ def config_files(role)
143
+ role.properties.fetch(:sidekiq_config_files) ||
144
+ fetch(:sidekiq_config_files)
296
145
  end
297
146
  end
@@ -0,0 +1,45 @@
1
+ # Source: https://github.com/mperham/sidekiq/blob/master/examples/systemd/sidekiq.service
2
+ #
3
+ # This file tells systemd how to run Sidekiq as a 24/7 long-running daemon.
4
+
5
+ # Then run:
6
+ # - systemctl enable <%= sidekiq_service_unit_name(@config_file) %>
7
+ # - systemctl {start,stop,restart} <%= sidekiq_service_unit_name(@config_file) %>
8
+ #
9
+ # Use `journalctl -u <%= sidekiq_service_unit_name(@config_file) %> -rn 100` to view the last 100 lines of log output.
10
+ #
11
+ [Unit]
12
+ Description=Sidekiq for <%= "#{fetch(:application)} (#{fetch(:stage)})" %>
13
+ # start us only once the network and logging subsystems are available,
14
+ # consider adding redis-server.service if Redis is local and systemd-managed.
15
+ After=syslog.target network.target
16
+
17
+ [Service]
18
+ Type=notify
19
+ # If your Sidekiq process locks up, systemd's watchdog will restart it within seconds.
20
+ WatchdogSec=10
21
+ <%="User=#{sidekiq_user}" if fetch(:sidekiq_systemctl_user) == :system %>
22
+ WorkingDirectory=<%= current_path %>
23
+ ExecStart=<%= expanded_bundle_path %> exec sidekiq -e <%= fetch(:sidekiq_env) %> <%= sidekiq_config %>
24
+
25
+ # Use `systemctl kill -s TSTP <% sidekiq_service_unit_name(@config_file) %>` to quiet the Sidekiq process
26
+ UMask=0002
27
+
28
+ <%- Array(fetch(:sidekiq_service_unit_env_files)).each do |file| %>
29
+ <%="EnvironmentFile=#{file}" %>
30
+ <% end -%>
31
+ <% Array(fetch(:sidekiq_service_unit_env_vars)).each do |environment_variable| %>
32
+ <%="Environment=\"#{environment_variable}\"" %>
33
+ <% end -%>
34
+
35
+ # if we crash, restart
36
+ RestartSec=1
37
+ Restart=on-failure
38
+
39
+ <%="StandardOutput=append:#{fetch(:sidekiq_log)}" if fetch(:sidekiq_log) -%>
40
+
41
+ <%="StandardError=append:#{fetch(:sidekiq_error_log)}" if fetch(:sidekiq_error_log) -%>
42
+
43
+ SyslogIdentifier=<%= sidekiq_service_unit_name(@config_file) %>
44
+ [Install]
45
+ WantedBy=<%=(fetch(:sidekiq_systemctl_user) == :system) ? "multi-user.target" : "default.target"%>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-sidekiq
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 3.0.0.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Abdelkader Boudih
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-11 00:00:00.000000000 Z
11
+ date: 2022-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '6.0'
47
+ version: 6.0.6
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '6.0'
54
+ version: 6.0.6
55
55
  description: Sidekiq integration for Capistrano
56
56
  email:
57
57
  - terminale@gmail.com
@@ -59,31 +59,24 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - ".gitignore"
63
- - ".tool-versions"
64
62
  - CHANGELOG.md
65
- - Gemfile
66
63
  - LICENSE.txt
67
64
  - README.md
68
- - Rakefile
69
- - capistrano-sidekiq.gemspec
70
65
  - lib/capistrano-sidekiq.rb
71
66
  - lib/capistrano/sidekiq.rb
72
- - lib/capistrano/sidekiq/helpers.rb
73
- - lib/capistrano/sidekiq/monit.rb
74
67
  - lib/capistrano/sidekiq/systemd.rb
75
68
  - lib/capistrano/sidekiq/version.rb
76
- - lib/capistrano/tasks/monit.rake
77
69
  - lib/capistrano/tasks/sidekiq.rake
78
70
  - lib/capistrano/tasks/systemd.rake
71
+ - lib/capistrano/templates/sidekiq.service.capistrano.erb
79
72
  - lib/generators/capistrano/sidekiq/monit/template_generator.rb
80
73
  - lib/generators/capistrano/sidekiq/monit/templates/sidekiq_monit.conf.erb
81
- - lib/generators/capistrano/sidekiq/systemd/templates/sidekiq.service.capistrano.erb
82
74
  homepage: https://github.com/seuros/capistrano-sidekiq
83
75
  licenses:
84
76
  - LGPL-3.0
85
77
  metadata: {}
86
- post_install_message:
78
+ post_install_message: "\n Version 3.0.0 is a major release. Please see README.md,
79
+ breaking changes are listed in CHANGELOG.md\n "
87
80
  rdoc_options: []
88
81
  require_paths:
89
82
  - lib
@@ -91,14 +84,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
91
84
  requirements:
92
85
  - - ">="
93
86
  - !ruby/object:Gem::Version
94
- version: 2.0.0
87
+ version: 2.5.0
95
88
  required_rubygems_version: !ruby/object:Gem::Requirement
96
89
  requirements:
97
- - - ">="
90
+ - - ">"
98
91
  - !ruby/object:Gem::Version
99
- version: '0'
92
+ version: 1.3.1
100
93
  requirements: []
101
- rubygems_version: 3.4.10
94
+ rubygems_version: 3.1.6
102
95
  signing_key:
103
96
  specification_version: 4
104
97
  summary: Sidekiq integration for Capistrano
data/.gitignore DELETED
@@ -1,19 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- .idea
19
- *.iml
data/.tool-versions DELETED
@@ -1 +0,0 @@
1
- ruby 2.7.6
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in capistrano-sidekiq.gemspec
4
- gemspec
5
-
6
- gem "bump", "~> 0.10.0"
7
-
8
- gem "github_changelog_generator", "~> 1.16"
data/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require 'github_changelog_generator/task'
3
-
4
- GitHubChangelogGenerator::RakeTask.new :changelog do |config|
5
- config.user = 'seuros'
6
- config.project = 'capistrano-sidekiq'
7
- config.issues = false
8
- config.future_release = '2.3.0'
9
- end
@@ -1,22 +0,0 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'capistrano/sidekiq/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'capistrano-sidekiq'
7
- spec.version = Capistrano::SidekiqVERSION
8
- spec.authors = ['Abdelkader Boudih']
9
- spec.email = ['terminale@gmail.com']
10
- spec.summary = %q{Sidekiq integration for Capistrano}
11
- spec.description = %q{Sidekiq integration for Capistrano}
12
- spec.homepage = 'https://github.com/seuros/capistrano-sidekiq'
13
- spec.license = 'LGPL-3.0'
14
-
15
- spec.required_ruby_version = '>= 2.0.0'
16
- spec.files = `git ls-files`.split($/)
17
- spec.require_paths = ['lib']
18
-
19
- spec.add_dependency 'capistrano', '>= 3.9.0'
20
- spec.add_dependency 'capistrano-bundler'
21
- spec.add_dependency 'sidekiq', '>= 6.0'
22
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Capistrano
4
- module Sidekiq::Helpers
5
-
6
- def sidekiq_require
7
- "--require #{fetch(:sidekiq_require)}" if fetch(:sidekiq_require)
8
- end
9
-
10
- def sidekiq_config
11
- "--config #{fetch(:sidekiq_config)}" if fetch(:sidekiq_config)
12
- end
13
-
14
- def sidekiq_concurrency
15
- "--concurrency #{fetch(:sidekiq_concurrency)}" if fetch(:sidekiq_concurrency)
16
- end
17
-
18
- def sidekiq_queues
19
- Array(fetch(:sidekiq_queue)).map do |queue|
20
- "--queue #{queue}"
21
- end.join(' ')
22
- end
23
-
24
- def sidekiq_logfile
25
- fetch(:sidekiq_log)
26
- end
27
-
28
- def switch_user(role, &block)
29
- su_user = sidekiq_user(role)
30
- if su_user == role.user
31
- yield
32
- else
33
- as su_user, &block
34
- end
35
- end
36
-
37
- def sidekiq_user(role = nil)
38
- if role.nil?
39
- fetch(:sidekiq_user)
40
- else
41
- properties = role.properties
42
- properties.fetch(:sidekiq_user) || # local property for sidekiq only
43
- fetch(:sidekiq_user) ||
44
- properties.fetch(:run_as) || # global property across multiple capistrano gems
45
- role.user
46
- end
47
- end
48
-
49
- def expanded_bundle_path
50
- backend.capture(:echo, SSHKit.config.command_map[:bundle]).strip
51
- end
52
- end
53
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Capistrano
4
- class Sidekiq::Monit < Capistrano::Plugin
5
- include Sidekiq::Helpers
6
-
7
- def set_defaults
8
- set_if_empty :monit_bin, '/usr/bin/monit'
9
- set_if_empty :sidekiq_monit_conf_dir, '/etc/monit/conf.d'
10
- set_if_empty :sidekiq_monit_conf_file, -> { "#{sidekiq_service_name}.conf" }
11
- set_if_empty :sidekiq_monit_use_sudo, true
12
- set_if_empty :sidekiq_monit_default_hooks, true
13
- set_if_empty :sidekiq_monit_templates_path, 'config/deploy/templates'
14
- set_if_empty :sidekiq_monit_group, nil
15
- end
16
-
17
- def define_tasks
18
- eval_rakefile File.expand_path('../tasks/monit.rake', __dir__)
19
- end
20
- end
21
- end
@@ -1,127 +0,0 @@
1
- git_plugin = self
2
-
3
- namespace :deploy do
4
- before :starting, :check_sidekiq_monit_hooks do
5
- if fetch(:sidekiq_default_hooks) && fetch(:sidekiq_monit_default_hooks)
6
- invoke 'sidekiq:monit:add_default_hooks'
7
- end
8
- end
9
- end
10
-
11
- namespace :sidekiq do
12
- namespace :monit do
13
- task :add_default_hooks do
14
- before 'deploy:updating', 'sidekiq:monit:unmonitor'
15
- after 'deploy:published', 'sidekiq:monit:monitor'
16
- end
17
-
18
- desc 'Config Sidekiq monit-service'
19
- task :config do
20
- on roles(fetch(:sidekiq_roles)) do |role|
21
- @role = role
22
- git_plugin.upload_sidekiq_template 'sidekiq_monit', "#{fetch(:tmp_dir)}/monit.conf", @role
23
-
24
- git_plugin.switch_user(role) do
25
- mv_command = "mv #{fetch(:tmp_dir)}/monit.conf #{fetch(:sidekiq_monit_conf_dir)}/#{fetch(:sidekiq_monit_conf_file)}"
26
-
27
- git_plugin.sudo_if_needed mv_command
28
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} reload"
29
- end
30
- end
31
- end
32
-
33
- desc 'Monitor Sidekiq monit-service'
34
- task :monitor do
35
- on roles(fetch(:sidekiq_roles)) do |role|
36
- git_plugin.switch_user(role) do
37
- begin
38
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} monitor #{git_plugin.sidekiq_service_name}"
39
- rescue
40
- invoke 'sidekiq:monit:config'
41
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} monitor #{git_plugin.sidekiq_service_name}"
42
- end
43
- end
44
- end
45
- end
46
-
47
- desc 'Unmonitor Sidekiq monit-service'
48
- task :unmonitor do
49
- on roles(fetch(:sidekiq_roles)) do |role|
50
- git_plugin.switch_user(role) do
51
- begin
52
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} unmonitor #{git_plugin.sidekiq_service_name}"
53
- rescue
54
- # no worries here
55
- end
56
- end
57
- end
58
- end
59
- end
60
-
61
- desc 'Start Sidekiq monit-service'
62
- task :start do
63
- on roles(fetch(:sidekiq_roles)) do |role|
64
- git_plugin.switch_user(role) do
65
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} start #{git_plugin.sidekiq_service_name}"
66
- end
67
- end
68
- end
69
-
70
- desc 'Stop Sidekiq monit-service'
71
- task :stop do
72
- on roles(fetch(:sidekiq_roles)) do |role|
73
- git_plugin.switch_user(role) do
74
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} stop #{git_plugin.sidekiq_service_name}"
75
- end
76
- end
77
- end
78
-
79
- desc 'Restart Sidekiq monit-service'
80
- task :restart do
81
- on roles(fetch(:sidekiq_roles)) do |role|
82
- git_plugin.sudo_if_needed "#{fetch(:monit_bin)} restart #{git_plugin.sidekiq_service_name}"
83
- end
84
- end
85
-
86
- def sidekiq_service_name
87
- fetch(:sidekiq_service_name, "sidekiq_#{fetch(:application)}_#{fetch(:sidekiq_env)}")
88
- end
89
-
90
- def sudo_if_needed(command)
91
- if use_sudo?
92
- backend.execute :sudo, command
93
- else
94
- backend.execute command
95
- end
96
- end
97
-
98
- def use_sudo?
99
- fetch(:sidekiq_monit_use_sudo)
100
- end
101
-
102
- def upload_sidekiq_template(from, to, role)
103
- template = sidekiq_template(from, role)
104
- backend.upload!(StringIO.new(ERB.new(template).result(binding)), to)
105
- end
106
-
107
- def sidekiq_template(name, role)
108
- local_template_directory = fetch(:sidekiq_monit_templates_path)
109
-
110
- search_paths = [
111
- "#{name}-#{role.hostname}-#{fetch(:stage)}.erb",
112
- "#{name}-#{role.hostname}.erb",
113
- "#{name}-#{fetch(:stage)}.erb",
114
- "#{name}.erb"
115
- ].map { |filename| File.join(local_template_directory, filename) }
116
-
117
- global_search_path = File.expand_path(
118
- File.join(*%w[.. .. .. generators capistrano sidekiq monit templates], "#{name}.conf.erb"),
119
- __FILE__
120
- )
121
-
122
- search_paths << global_search_path
123
-
124
- template_path = search_paths.detect { |path| File.file?(path) }
125
- File.read(template_path)
126
- end
127
- end
@@ -1,68 +0,0 @@
1
- # Source: https://github.com/mperham/sidekiq/blob/master/examples/systemd/sidekiq.service
2
- #
3
- # This file tells systemd how to run Sidekiq as a 24/7 long-running daemon.
4
- #
5
- # Customize this file based on your bundler location, app directory, etc.
6
- # Customize and copy this into /usr/lib/systemd/system (CentOS) or /lib/systemd/system (Ubuntu).
7
- # Then run:
8
- # - systemctl enable <%= sidekiq_service_unit_name %>
9
- # - systemctl {start,stop,restart} <%= sidekiq_service_unit_name %>
10
- #
11
- # This file corresponds to a single Sidekiq process. Add multiple copies
12
- # to run multiple processes (sidekiq-1, sidekiq-2, etc).
13
- #
14
- # Use `journalctl -u <%= sidekiq_service_unit_name %> -rn 100` to view the last 100 lines of log output.
15
- #
16
- [Unit]
17
- Description=sidekiq for <%= "#{fetch(:application)} (#{fetch(:stage)})" %>
18
- # start us only once the network and logging subsystems are available,
19
- # consider adding redis-server.service if Redis is local and systemd-managed.
20
- After=syslog.target network.target
21
-
22
- # See these pages for lots of options:
23
- #
24
- # https://www.freedesktop.org/software/systemd/man/systemd.service.html
25
- # https://www.freedesktop.org/software/systemd/man/systemd.exec.html
26
- #
27
- # THOSE PAGES ARE CRITICAL FOR ANY LINUX DEVOPS WORK; read them multiple
28
- # times! systemd is a critical tool for all developers to know and understand.
29
- #
30
- [Service]
31
- #
32
- # !!!! !!!! !!!!
33
- #
34
- # As of v6.0.6, Sidekiq automatically supports systemd's `Type=notify` and watchdog service
35
- # monitoring. If you are using an earlier version of Sidekiq, change this to `Type=simple`
36
- # and remove the `WatchdogSec` line.
37
- #
38
- # !!!! !!!! !!!!
39
- #
40
- Type=notify
41
- # If your Sidekiq process locks up, systemd's watchdog will restart it within seconds.
42
- WatchdogSec=10
43
-
44
- WorkingDirectory=<%= File.join(fetch(:deploy_to), 'current') %>
45
- ExecStart=<%= expanded_bundle_path %> exec sidekiq -e <%= fetch(:sidekiq_env) %> <%= sidekiq_config %> <%= sidekiq_concurrency %> <%= sidekiq_queues %>
46
-
47
- # Use `systemctl kill -s TSTP <%= sidekiq_service_unit_name %>` to quiet the Sidekiq process
48
- <%="User=#{sidekiq_user}" if sidekiq_user %>
49
- UMask=0002
50
-
51
- <%="EnvironmentFile=#{File.join(fetch(:deploy_to), 'current')}/#{fetch(:sidekiq_service_unit_env_file)}" if fetch(:sidekiq_service_unit_env_file) %>
52
-
53
- <% fetch(:sidekiq_service_unit_env_vars, []).each do |environment_variable| %>
54
- <%="Environment=#{environment_variable}" %>
55
- <% end %>
56
-
57
- # if we crash, restart
58
- RestartSec=1
59
- Restart=on-failure
60
-
61
- # output goes to /var/log/syslog (Ubuntu) or /var/log/messages (CentOS)
62
- <%="StandardOutput=append:#{fetch(:sidekiq_log)}" if fetch(:sidekiq_log) %>
63
- <%="StandardError=append:#{fetch(:sidekiq_error_log)}" if fetch(:sidekiq_error_log) %>
64
-
65
- SyslogIdentifier=<%= sidekiq_service_unit_name %>
66
-
67
- [Install]
68
- WantedBy=default.target