process_bot 0.1.30 → 0.1.31

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: 5e091db49a7e39df21edb300dc0ebb57cb5b98a73be033b220d24f72a7f72c36
4
- data.tar.gz: 59e9442735c2a07cc568e8f9b0f1ed3c3660fa407d1f85ed7326348722ed7dbc
3
+ metadata.gz: c2183ea1e8ec1a90a39ec3d3d7d2753150f99e164f31e3650d83a40a784d1a67
4
+ data.tar.gz: 0b009604dcd29677832a88cd814b29e7259cef2709d22f5ef140673d298a0981
5
5
  SHA512:
6
- metadata.gz: 3459f12d21d2d221c152ed047cd51dc4c9134e285cfc52847997099ace48a1ddd60fc8c7c54d5a6b6ca8535b2054e47f9ae5b72da010188e56eca304194b30e6
7
- data.tar.gz: 8b7bd9482806698b84f3ea356b00c2f71d58850249fb0e2aabb28591495094e727324eb6bad5f0e5ee4740adef932c58f91f232d90e8ea8488f7f453a9bde138
6
+ metadata.gz: f6239960b599dc220ab6e8519f7edd7061556b69e0918d48cd655a25bd1239307b6f7b836599811cc3b69dd72ad40a830988aef00d3cb92fdfbbd9ebf02428c2
7
+ data.tar.gz: 4566c50a189d90b5c638369db712d63355700894a6643f17b44e4b0544bee9fdb949e13046c9f24c21652742e4352d8139bf80a5c79612d007a8114f06a4fe9c
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.8
1
+ 3.2.5
data/CHANGELOG.md CHANGED
@@ -1,6 +1,7 @@
1
1
  ## [Unreleased]
2
2
  - Drop Ruby 2.x support. Minimum Ruby is now 3.2; CI covers 3.2/3.3/3.4 and RuboCop's `TargetRubyVersion` follows. Shorthand anonymous forwarding (`*, **, &`) is applied where it replaces redundant `*args, **opts, &block` pass-throughs.
3
3
  - Fail `start_tcp_server` when another ProcessBot with the same `--id` is already running instead of silently drifting to a new port. Port drift across unrelated services is still supported; drift for a duplicate id was the root cause of Capistrano deploys leaving a stale previous-release ProcessBot alive on a drifted port while every subsequent `stop --port X` hit the wrong instance.
4
+ - Treat legacy ProcessBot titles without `application_basename` as duplicates when they share the same `--id` and control port, and include the same legacy match in forced stop diagnostics.
4
5
  - Stop accepting new control commands during shutdown so in-flight responses complete reliably.
5
6
  - Stream ProcessBot logs to connected control clients for Capistrano output.
6
7
  - Sanitize broadcast log output to keep JSON encoding safe.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- process_bot (0.1.30)
4
+ process_bot (0.1.31)
5
5
  knjrbfw (>= 0.0.116)
6
6
  pry
7
7
  rake
@@ -18,7 +18,7 @@ GEM
18
18
  http2 (0.0.36)
19
19
  string-cases (~> 0)
20
20
  io-console (0.8.2)
21
- json (2.19.3)
21
+ json (2.19.5)
22
22
  knjrbfw (0.0.116)
23
23
  datet
24
24
  http2
@@ -62,7 +62,7 @@ GEM
62
62
  diff-lcs (>= 1.2.0, < 2.0)
63
63
  rspec-support (~> 3.13.0)
64
64
  rspec-support (3.13.7)
65
- rubocop (1.86.1)
65
+ rubocop (1.86.2)
66
66
  json (~> 2.3)
67
67
  language_server-protocol (~> 3.17.0.2)
68
68
  lint_roller (~> 1.1.0)
@@ -74,10 +74,23 @@ class ProcessBot::ControlSocket
74
74
 
75
75
  def find_duplicate_id_entries(id, basename)
76
76
  running_process_bot_entries.select do |entry|
77
- entry[:id] == id && entry[:application_basename] == basename
77
+ duplicate_id_entry_matches?(entry, id, basename)
78
78
  end
79
79
  end
80
80
 
81
+ def duplicate_id_entry_matches?(entry, id, basename)
82
+ return false unless entry[:id] == id
83
+ return true if basename && entry[:application_basename] == basename
84
+
85
+ entry[:application_basename].nil? && same_control_port?(entry)
86
+ end
87
+
88
+ def same_control_port?(entry)
89
+ return false unless entry[:port] && options[:port]
90
+
91
+ entry[:port].to_i == options[:port].to_i
92
+ end
93
+
81
94
  def duplicate_id_error_message(id, duplicates)
82
95
  details = duplicates.map { |entry| "PID #{entry[:pid]} on port #{entry[:port]}" }.join(", ")
83
96
  example_port = duplicates.first[:port]
@@ -235,15 +248,19 @@ class ProcessBot::ControlSocket
235
248
  next
236
249
  end
237
250
 
238
- pid = process.data["pid"] || process.pid
239
- entries << {
240
- application_basename: process_data["application_basename"],
241
- id: process_data["id"]&.to_s,
242
- pid: pid,
243
- port: process_data["port"]&.to_i
244
- }
251
+ entries << process_bot_entry_from_process_data(process, process_data)
245
252
  end
246
253
 
247
254
  entries
248
255
  end
256
+
257
+ def process_bot_entry_from_process_data(process, process_data)
258
+ {
259
+ application: process_data["application"],
260
+ application_basename: process_data["application_basename"],
261
+ id: process_data["id"]&.to_s,
262
+ pid: process.data["pid"] || process.pid,
263
+ port: process_data["port"]&.to_i
264
+ }
265
+ end
249
266
  end
@@ -36,17 +36,19 @@ class ProcessBot::Options
36
36
  end
37
37
 
38
38
  def application_basename
39
- @application_basename ||= begin
40
- app_path_parts = release_path.split("/")
39
+ @application_basename ||= application_basename_from_release_path
40
+ end
41
41
 
42
- if release_path.include?("/releases/")
43
- app_path_parts.pop(2)
44
- elsif release_path.end_with?("/current")
45
- app_path_parts.pop
46
- end
42
+ def application_basename_from_release_path
43
+ app_path_parts = release_path.split("/")
44
+ deployment_marker_index = [
45
+ app_path_parts.rindex("releases"),
46
+ app_path_parts.rindex("current")
47
+ ].compact.max
47
48
 
48
- app_path_parts.last
49
- end
49
+ return app_path_parts[0...deployment_marker_index].last if deployment_marker_index
50
+
51
+ app_path_parts.last
50
52
  end
51
53
 
52
54
  def possible_process_titles
@@ -334,9 +334,35 @@ class ProcessBot::Process # rubocop:disable Metrics/ClassLength
334
334
  end
335
335
 
336
336
  def process_bot_process_line_matches?(line)
337
- line.include?("ProcessBot {") &&
338
- line.include?("\"application\":\"#{options[:application]}\"") &&
339
- line.include?("\"id\":\"#{options[:id]}\"")
337
+ process_data = process_bot_data_from_line(line)
338
+ return false unless process_data
339
+ return false unless process_data["id"]&.to_s == options[:id].to_s
340
+
341
+ process_bot_application_matches?(process_data) || legacy_process_bot_port_matches?(process_data)
342
+ end
343
+
344
+ def process_bot_data_from_line(line)
345
+ match = line.match(/ProcessBot (\{.+\})/)
346
+ return unless match
347
+
348
+ JSON.parse(match[1])
349
+ rescue JSON::ParserError
350
+ nil
351
+ end
352
+
353
+ def process_bot_application_matches?(process_data)
354
+ application = options[:application]
355
+ return true if application && process_data["application"] == application
356
+
357
+ basename = safe_application_basename
358
+ basename && process_data["application_basename"] == basename
359
+ end
360
+
361
+ def legacy_process_bot_port_matches?(process_data)
362
+ return false unless process_data["port"] && options[:port]
363
+
364
+ process_data["application_basename"].nil? &&
365
+ process_data["port"].to_i == options[:port].to_i
340
366
  end
341
367
 
342
368
  def force_stop_process_bot_if_configured(matching_processes)
@@ -1,3 +1,3 @@
1
1
  module ProcessBot
2
- VERSION = "0.1.30".freeze
2
+ VERSION = "0.1.31".freeze
3
3
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: process_bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.30
4
+ version: 0.1.31
5
5
  platform: ruby
6
6
  authors:
7
7
  - kaspernj
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-05-20 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: knjrbfw
@@ -186,6 +187,7 @@ metadata:
186
187
  source_code_uri: https://github.com/kaspernj/process_bot
187
188
  changelog_uri: https://github.com/kaspernj/process_bot/blob/master/CHANGELOG.md
188
189
  rubygems_mfa_required: 'true'
190
+ post_install_message:
189
191
  rdoc_options: []
190
192
  require_paths:
191
193
  - lib
@@ -200,7 +202,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
200
202
  - !ruby/object:Gem::Version
201
203
  version: '0'
202
204
  requirements: []
203
- rubygems_version: 3.6.9
205
+ rubygems_version: 3.4.19
206
+ signing_key:
204
207
  specification_version: 4
205
208
  summary: Run and control processes.
206
209
  test_files: []