process_bot 0.1.26 → 0.1.28
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 +4 -4
- data/AGENTS.md +1 -1
- data/CHANGELOG.md +1 -1
- data/Gemfile.lock +2 -2
- data/Rakefile +1 -35
- data/lib/process_bot/process/handlers/custom.rb +8 -1
- data/lib/process_bot/process/runner.rb +48 -12
- data/lib/process_bot/process.rb +68 -2
- data/lib/process_bot/version.rb +1 -1
- data/lib/tasks/release.rake +177 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e123dbde56775d5539bb91d48be68c1f83a09a2b001c6a61a1334aa3dba2b1ab
|
|
4
|
+
data.tar.gz: 34f9ff90352cad06e742ba69f7d4402d095678359caded93b20204f89b804a44
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8cbc29f75c5ffa3358f8614c11698fc4ac6548efa5a00a4d63a1004300707c80b395eb9229b877b06cc93c1d3b7e10987fa99d02f1942c67a133db277d9af49b
|
|
7
|
+
data.tar.gz: 8042fcbf747ba1162120b87e54d64bd1ac972615eaca4288865864ea76747e27d94b697b8de97d0a38ede453abbc9c30e5a54fdc3af32052f9ff466c82b9d311
|
data/AGENTS.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- Made graceful shutdown waiting optional and defaulted Capistrano to not wait.
|
|
10
10
|
- Kept graceful handling synchronous and verified `bundle exec rspec`.
|
|
11
11
|
- Enabled ProcessBot logging by default for Capistrano hooks (configurable via `process_bot_log`).
|
|
12
|
-
- Always run RuboCop against changed or created Ruby files.
|
|
12
|
+
- Always run RuboCop against changed or created Ruby files before pushing or opening a PR.
|
|
13
13
|
- Added `graceful_no_wait` command and Capistrano task for non-blocking graceful shutdowns.
|
|
14
14
|
- Always add or update tests for new/changed functionality, and run them.
|
|
15
15
|
- Added coverage for graceful_no_wait and Capistrano wait defaults.
|
data/CHANGELOG.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
- Add optional Sidekiq restart overlap and a new ProcessBot restart command.
|
|
9
9
|
- Guard stop-related process scanning when subprocess PID/PGID is unavailable and fail stop loudly.
|
|
10
10
|
- Wait briefly for subprocess PID assignment during stop; raise if PID is still missing so stop cannot silently succeed.
|
|
11
|
-
|
|
12
11
|
- Require an active runner for custom stop commands to avoid constructing a fresh runner with no PID.
|
|
12
|
+
- Buffer subprocess output by line before broadcasting it to control clients so Capistrano does not receive one-character log chunks.
|
|
13
13
|
|
|
14
14
|
## [0.1.0] - 2022-04-03
|
|
15
15
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
process_bot (0.1.
|
|
4
|
+
process_bot (0.1.28)
|
|
5
5
|
knjrbfw (>= 0.0.116)
|
|
6
6
|
pry
|
|
7
7
|
rake
|
|
@@ -58,7 +58,7 @@ GEM
|
|
|
58
58
|
rspec-expectations (3.13.5)
|
|
59
59
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
60
60
|
rspec-support (~> 3.13.0)
|
|
61
|
-
rspec-mocks (3.13.
|
|
61
|
+
rspec-mocks (3.13.8)
|
|
62
62
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
63
63
|
rspec-support (~> 3.13.0)
|
|
64
64
|
rspec-support (3.13.7)
|
data/Rakefile
CHANGED
|
@@ -7,40 +7,6 @@ require "rubocop/rake_task"
|
|
|
7
7
|
RSpec::Core::RakeTask.new(:spec)
|
|
8
8
|
RuboCop::RakeTask.new
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
version_content = File.read(version_path)
|
|
12
|
-
version_match = version_content.match(/VERSION = "(\d+)\.(\d+)\.(\d+)"\.freeze/)
|
|
13
|
-
raise "Could not find current version in #{version_path}" unless version_match
|
|
14
|
-
|
|
15
|
-
major = version_match[1].to_i
|
|
16
|
-
minor = version_match[2].to_i
|
|
17
|
-
patch = version_match[3].to_i + 1
|
|
18
|
-
|
|
19
|
-
new_version = "#{major}.#{minor}.#{patch}"
|
|
20
|
-
new_content = version_content.sub(version_match[0], "VERSION = \"#{new_version}\".freeze")
|
|
21
|
-
File.write(version_path, new_content)
|
|
22
|
-
|
|
23
|
-
new_version
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
namespace :release do
|
|
27
|
-
desc "Bump patch version, run bundle, commit version bump, build gem, and push gem"
|
|
28
|
-
task :patch do
|
|
29
|
-
version_path = "lib/process_bot/version.rb"
|
|
30
|
-
new_version = bump_patch_version(version_path)
|
|
31
|
-
|
|
32
|
-
puts "Bumped version to #{new_version}"
|
|
33
|
-
|
|
34
|
-
sh "bundle install"
|
|
35
|
-
sh "git add #{version_path}"
|
|
36
|
-
sh "git commit -m \"Bump version to #{new_version}\""
|
|
37
|
-
sh "bundle exec rake build"
|
|
38
|
-
|
|
39
|
-
gem_path = "pkg/process_bot-#{new_version}.gem"
|
|
40
|
-
raise "Expected gem file was not built: #{gem_path}" unless File.exist?(gem_path)
|
|
41
|
-
|
|
42
|
-
sh "gem push #{gem_path}"
|
|
43
|
-
end
|
|
44
|
-
end
|
|
10
|
+
Dir[File.expand_path("lib/tasks/**/*.rake", __dir__)].each { |f| load f }
|
|
45
11
|
|
|
46
12
|
task default: %i[spec rubocop]
|
|
@@ -48,7 +48,14 @@ class ProcessBot::Process::Handlers::Custom
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def stop(**_args)
|
|
51
|
+
runner = process.active_runner
|
|
52
|
+
|
|
53
|
+
unless runner
|
|
54
|
+
logger.logs "No active runner to stop"
|
|
55
|
+
return
|
|
56
|
+
end
|
|
57
|
+
|
|
51
58
|
logger.logs "Stop related processes"
|
|
52
|
-
|
|
59
|
+
runner.stop_related_processes
|
|
53
60
|
end
|
|
54
61
|
end
|
|
@@ -3,6 +3,8 @@ require "knjrbfw"
|
|
|
3
3
|
class ProcessBot::Process::Runner
|
|
4
4
|
attr_reader :command, :exit_status, :handler_instance, :handler_name, :logger, :monitor, :options, :pid, :stop_time, :subprocess_pid
|
|
5
5
|
|
|
6
|
+
READ_CHUNK_SIZE = 4096
|
|
7
|
+
|
|
6
8
|
def initialize(command:, handler_instance:, handler_name:, logger:, options:)
|
|
7
9
|
@command = command
|
|
8
10
|
@handler_instance = handler_instance
|
|
@@ -16,6 +18,17 @@ class ProcessBot::Process::Runner
|
|
|
16
18
|
logger.log(output, type: type)
|
|
17
19
|
end
|
|
18
20
|
|
|
21
|
+
def stream_output(io, type:)
|
|
22
|
+
buffer = +""
|
|
23
|
+
|
|
24
|
+
loop do
|
|
25
|
+
buffer << io.readpartial(READ_CHUNK_SIZE)
|
|
26
|
+
flush_complete_lines(type: type, buffer: buffer)
|
|
27
|
+
end
|
|
28
|
+
rescue EOFError, Errno::EIO
|
|
29
|
+
flush_remaining_output(type: type, buffer: buffer)
|
|
30
|
+
end
|
|
31
|
+
|
|
19
32
|
def running?
|
|
20
33
|
!stop_time
|
|
21
34
|
end
|
|
@@ -31,13 +44,7 @@ class ProcessBot::Process::Runner
|
|
|
31
44
|
logger.logs "Command running with PID #{pid}: #{command}"
|
|
32
45
|
|
|
33
46
|
stdout_reader_thread = Thread.new do
|
|
34
|
-
stdout
|
|
35
|
-
monitor.synchronize do
|
|
36
|
-
output(type: :stdout, output: chunk)
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
rescue Errno::EIO
|
|
40
|
-
# Process done
|
|
47
|
+
stream_output(stdout, type: :stdout)
|
|
41
48
|
ensure
|
|
42
49
|
status = Process::Status.wait(subprocess_pid, 0)
|
|
43
50
|
|
|
@@ -46,11 +53,7 @@ class ProcessBot::Process::Runner
|
|
|
46
53
|
end
|
|
47
54
|
|
|
48
55
|
stderr_reader_thread = Thread.new do
|
|
49
|
-
stderr_reader
|
|
50
|
-
monitor.synchronize do
|
|
51
|
-
output(type: :stderr, output: chunk)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
56
|
+
stream_output(stderr_reader, type: :stderr)
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
find_sidekiq_pid if handler_name == "sidekiq"
|
|
@@ -182,4 +185,37 @@ class ProcessBot::Process::Runner
|
|
|
182
185
|
break
|
|
183
186
|
end
|
|
184
187
|
end
|
|
188
|
+
|
|
189
|
+
def flush_complete_lines(type:, buffer:)
|
|
190
|
+
loop do
|
|
191
|
+
separator_index = next_separator_index(buffer)
|
|
192
|
+
break unless separator_index
|
|
193
|
+
|
|
194
|
+
monitor.synchronize do
|
|
195
|
+
output(type: type, output: buffer.slice!(0, separator_index + 1))
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
return if buffer.bytesize < READ_CHUNK_SIZE
|
|
200
|
+
|
|
201
|
+
monitor.synchronize do
|
|
202
|
+
output(type: type, output: buffer.dup)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
buffer.clear
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def flush_remaining_output(type:, buffer:)
|
|
209
|
+
return if buffer.empty?
|
|
210
|
+
|
|
211
|
+
monitor.synchronize do
|
|
212
|
+
output(type: type, output: buffer.dup)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
buffer.clear
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def next_separator_index(buffer)
|
|
219
|
+
buffer.index(/[\r\n]/)
|
|
220
|
+
end
|
|
185
221
|
end
|
data/lib/process_bot/process.rb
CHANGED
|
@@ -3,7 +3,7 @@ require "json"
|
|
|
3
3
|
require "monitor"
|
|
4
4
|
require "string-cases"
|
|
5
5
|
|
|
6
|
-
class ProcessBot::Process
|
|
6
|
+
class ProcessBot::Process # rubocop:disable Metrics/ClassLength
|
|
7
7
|
extend Forwardable
|
|
8
8
|
|
|
9
9
|
def_delegator :handler_instance, :graceful
|
|
@@ -131,8 +131,15 @@ class ProcessBot::Process
|
|
|
131
131
|
def send_control_command(command, **command_options)
|
|
132
132
|
logger.logs "Sending #{command} command"
|
|
133
133
|
response = client.send_command(command: command, options: options.options.merge(command_options))
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
if response == :nil
|
|
136
|
+
handle_missing_control_command_response(command)
|
|
137
|
+
return if options[:ignore_no_process_bot]
|
|
138
|
+
|
|
139
|
+
raise "No response from ProcessBot while sending #{command}"
|
|
140
|
+
end
|
|
135
141
|
rescue Errno::ECONNREFUSED => e
|
|
142
|
+
handle_missing_control_command_response(command)
|
|
136
143
|
raise e unless options[:ignore_no_process_bot]
|
|
137
144
|
end
|
|
138
145
|
|
|
@@ -274,6 +281,65 @@ class ProcessBot::Process
|
|
|
274
281
|
start_runner_instance
|
|
275
282
|
end
|
|
276
283
|
|
|
284
|
+
def handle_missing_control_command_response(command)
|
|
285
|
+
return unless command == "stop"
|
|
286
|
+
|
|
287
|
+
matching_processes = matching_process_bot_processes
|
|
288
|
+
log_missing_control_response_diagnostics(matching_processes)
|
|
289
|
+
force_stop_process_bot_if_configured(matching_processes)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def log_missing_control_response_diagnostics(matching_processes)
|
|
293
|
+
logger.logs "Control command response missing; attempting diagnostics for application=#{options[:application].inspect} id=#{options[:id].inspect}"
|
|
294
|
+
logger.logs "Matching process_bot lines:\n#{matching_process_bot_processes_text(matching_processes)}"
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
def matching_process_bot_processes_text(lines)
|
|
298
|
+
return "(none)" if lines.empty?
|
|
299
|
+
|
|
300
|
+
lines.join("\n")
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
def matching_process_bot_processes
|
|
304
|
+
ps_output = Knj::Os.shellcmd("ps -eo pid,args")
|
|
305
|
+
|
|
306
|
+
ps_output
|
|
307
|
+
.to_s
|
|
308
|
+
.split("\n")
|
|
309
|
+
.select { |line| process_bot_process_line_matches?(line) }
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def process_bot_process_line_matches?(line)
|
|
313
|
+
line.include?("ProcessBot {") &&
|
|
314
|
+
line.include?("\"application\":\"#{options[:application]}\"") &&
|
|
315
|
+
line.include?("\"id\":\"#{options[:id]}\"")
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def force_stop_process_bot_if_configured(matching_processes)
|
|
319
|
+
return unless truthy_option?(:force_stop_on_no_response)
|
|
320
|
+
|
|
321
|
+
matching_processes.each do |line|
|
|
322
|
+
pid = line.strip.split(/\s+/, 2).first
|
|
323
|
+
next unless pid&.match?(/\A\d+\z/)
|
|
324
|
+
|
|
325
|
+
logger.logs "Force-stopping unresponsive process_bot PID #{pid}"
|
|
326
|
+
Process.kill("TERM", Integer(pid, 10))
|
|
327
|
+
rescue Errno::ESRCH
|
|
328
|
+
logger.logs "Process bot PID #{pid} already gone during force stop"
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def truthy_option?(key)
|
|
333
|
+
value = options[key]
|
|
334
|
+
return false if value.nil?
|
|
335
|
+
return value if value == true || value == false
|
|
336
|
+
|
|
337
|
+
normalized = value.to_s.strip.downcase
|
|
338
|
+
return false if normalized == "false" || normalized == "0" || normalized == ""
|
|
339
|
+
|
|
340
|
+
true
|
|
341
|
+
end
|
|
342
|
+
|
|
277
343
|
private
|
|
278
344
|
|
|
279
345
|
attr_reader :current_runner_instance, :runner_events, :runner_monitor
|
data/lib/process_bot/version.rb
CHANGED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
require "English"
|
|
2
|
+
require "fileutils"
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "rubygems/version"
|
|
5
|
+
require "shellwords"
|
|
6
|
+
|
|
7
|
+
class ProcessBotRubygemsRelease
|
|
8
|
+
VERSION_FILE = Pathname.new(File.expand_path("../process_bot/version.rb", __dir__)) unless const_defined?(:VERSION_FILE)
|
|
9
|
+
|
|
10
|
+
def call
|
|
11
|
+
ensure_clean_worktree!
|
|
12
|
+
checkout_master!
|
|
13
|
+
fetch!
|
|
14
|
+
merge!
|
|
15
|
+
|
|
16
|
+
next_version = determine_next_version
|
|
17
|
+
|
|
18
|
+
bump_version!(next_version)
|
|
19
|
+
commit!(next_version)
|
|
20
|
+
push!
|
|
21
|
+
gem_file = build_gem!(next_version)
|
|
22
|
+
push_gem!(gem_file)
|
|
23
|
+
delete_gem_file!(gem_file)
|
|
24
|
+
rescue StandardError
|
|
25
|
+
warn "Release failed."
|
|
26
|
+
raise
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def ensure_clean_worktree!
|
|
32
|
+
dirty_entries = git_status_lines.grep_v(%r{\A\?\? process_bot-[^/]+\.gem\z})
|
|
33
|
+
return if dirty_entries.empty?
|
|
34
|
+
|
|
35
|
+
raise "Working tree must be clean before releasing:\n#{dirty_entries.join("\n")}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def checkout_master!
|
|
39
|
+
run!("git", "checkout", "master")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def fetch!
|
|
43
|
+
run!("git", "fetch", remote_name)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def merge!
|
|
47
|
+
run!("git", "merge", "--ff-only", "#{remote_name}/master")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def determine_next_version
|
|
51
|
+
requested_version || bumped_version
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def requested_version
|
|
55
|
+
version = ENV["VERSION"]&.strip
|
|
56
|
+
return if version.to_s.empty?
|
|
57
|
+
|
|
58
|
+
Gem::Version.new(version)
|
|
59
|
+
version
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def bumped_version
|
|
63
|
+
major, minor, patch = version_segments
|
|
64
|
+
|
|
65
|
+
case bump_type
|
|
66
|
+
when "major"
|
|
67
|
+
format_version(major + 1, 0, 0)
|
|
68
|
+
when "minor"
|
|
69
|
+
format_version(major, minor + 1, 0)
|
|
70
|
+
when "patch"
|
|
71
|
+
format_version(major, minor, patch + 1)
|
|
72
|
+
else
|
|
73
|
+
raise "Unsupported BUMP=#{bump_type.inspect}. Use patch, minor, major, or VERSION=x.y.z."
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def version_segments
|
|
78
|
+
@version_segments ||= begin
|
|
79
|
+
segments = Gem::Version.new(current_version).segments
|
|
80
|
+
segments << 0 while segments.length < 3
|
|
81
|
+
segments
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def current_version
|
|
86
|
+
@current_version ||= VERSION_FILE.read[/VERSION = "([^"]+)"\.freeze/, 1] || raise("Could not find current version")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def format_version(major, minor, patch)
|
|
90
|
+
[major, minor, patch].join(".")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def bump_version!(next_version)
|
|
94
|
+
raise "Next version must differ from current version" if next_version == current_version
|
|
95
|
+
|
|
96
|
+
VERSION_FILE.write(
|
|
97
|
+
VERSION_FILE.read.sub(
|
|
98
|
+
/VERSION = "[^"]+"\.freeze/,
|
|
99
|
+
%(VERSION = "#{next_version}".freeze)
|
|
100
|
+
)
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
run!("git", "add", VERSION_FILE.to_s)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def commit!(next_version)
|
|
107
|
+
run!("git", "commit", "-m", "Release #{next_version}")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def push!
|
|
111
|
+
run!("git", "push", remote_name, "master")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def build_gem!(next_version)
|
|
115
|
+
gem_file = "process_bot-#{next_version}.gem"
|
|
116
|
+
run!("gem", "build", "process_bot.gemspec")
|
|
117
|
+
gem_file
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def push_gem!(gem_file)
|
|
121
|
+
run!("gem", "push", gem_file)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def delete_gem_file!(gem_file)
|
|
125
|
+
FileUtils.rm_f(gem_file)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def git_status_lines
|
|
129
|
+
capture!("git", "status", "--porcelain").split("\n").reject(&:empty?)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def bump_type
|
|
133
|
+
ENV.fetch("BUMP", "patch")
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def remote_name
|
|
137
|
+
ENV.fetch("REMOTE", "origin")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def capture!(*command)
|
|
141
|
+
output = `#{command.map { |part| Shellwords.escape(part) }.join(" ")}`
|
|
142
|
+
raise "Command failed: #{command.join(' ')}" unless $CHILD_STATUS&.success?
|
|
143
|
+
|
|
144
|
+
output
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def run!(*command)
|
|
148
|
+
return if system(*command)
|
|
149
|
+
|
|
150
|
+
raise "Command failed: #{command.join(' ')}"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
namespace :release do
|
|
155
|
+
desc "Release a patch version from master by fetching, fast-forward merging, bumping version, pushing, and publishing"
|
|
156
|
+
task :patch do
|
|
157
|
+
ENV["BUMP"] = "patch"
|
|
158
|
+
ProcessBotRubygemsRelease.new.call
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
desc "Release a minor version from master by fetching, fast-forward merging, bumping version, pushing, and publishing"
|
|
162
|
+
task :minor do
|
|
163
|
+
ENV["BUMP"] = "minor"
|
|
164
|
+
ProcessBotRubygemsRelease.new.call
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
desc "Release a major version from master by fetching, fast-forward merging, bumping version, pushing, and publishing"
|
|
168
|
+
task :major do
|
|
169
|
+
ENV["BUMP"] = "major"
|
|
170
|
+
ProcessBotRubygemsRelease.new.call
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
desc "Release the gem from master by fetching, fast-forward merging, bumping version, pushing, and publishing"
|
|
174
|
+
task :rubygems do
|
|
175
|
+
ProcessBotRubygemsRelease.new.call
|
|
176
|
+
end
|
|
177
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: process_bot
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.28
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kaspernj
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: knjrbfw
|
|
@@ -175,6 +175,7 @@ files:
|
|
|
175
175
|
- lib/process_bot/process/runner.rb
|
|
176
176
|
- lib/process_bot/process/runner_instance.rb
|
|
177
177
|
- lib/process_bot/version.rb
|
|
178
|
+
- lib/tasks/release.rake
|
|
178
179
|
- peak_flow.yml
|
|
179
180
|
- process_bot.gemspec
|
|
180
181
|
homepage: https://github.com/kaspernj/process_bot
|