capistrano-sidekiq 2.3.1 → 3.0.0.alpha.1

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: 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