lex-health 0.1.7 → 0.2.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 +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +26 -0
- data/CLAUDE.md +1 -1
- data/README.md +2 -2
- data/lex-health.gemspec +8 -0
- data/lib/legion/extensions/health/runners/health.rb +20 -10
- data/lib/legion/extensions/health/runners/watchdog.rb +3 -1
- data/lib/legion/extensions/health/transport/messages/watchdog.rb +1 -1
- data/lib/legion/extensions/health/version.rb +1 -1
- data/lib/legion/extensions/health.rb +0 -4
- metadata +99 -3
- data/.circleci/config.yml +0 -61
- data/Gemfile.lock +0 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d482b0f36c50c6fb14c9aecdb9accbbc689202f4f2977a6c81cd123379aa1745
|
|
4
|
+
data.tar.gz: 3e980332379f3748c013eb06e22cb5cb20a8b89f028708bbb94ba05b039cf0d6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ceb0f962def03f38956dda15300e678262a57d6cfb4e844343ea76a39b03ac49242138f9c3310cf64c10a640acdac60251db2f8d7714907893aa8656815ee29d
|
|
7
|
+
data.tar.gz: e1ce74c59b555aec02f12bfe35f81fa6c31789b754e0b46ac9f53767a291567e5a784f8aa246a02c6db2b4258cd99497612f354c424e020c5ad0dbf4941ad5b1
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - 2026-03-22
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Add legion-cache, legion-crypt, legion-data, legion-json, legion-logging, legion-settings, legion-transport as runtime dependencies
|
|
7
|
+
- Replace direct Legion::JSON.dump calls with json_dump helper in runners/health.rb
|
|
8
|
+
- Update spec_helper with real sub-gem helper stubs
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2026-03-18
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- `active` column now uses boolean `true` instead of integer `1` (PostgreSQL compatibility)
|
|
14
|
+
- Watchdog message routing key changed from `'health'` to `'node.health'` to match queue binding
|
|
15
|
+
- Added `require 'time'` for `Time.parse`
|
|
16
|
+
- Nil guard on `updated` timestamp in back-in-time comparison
|
|
17
|
+
- TOCTOU race condition on concurrent heartbeat inserts (rescue UniqueConstraintViolation)
|
|
18
|
+
- `delete` method nil guard for nonexistent nodes
|
|
19
|
+
- `mark_workers_offline` now clears `health_node` on expired workers
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- Entry point `data_required?` is now `self.` (class method) matching framework expectation
|
|
23
|
+
|
|
24
|
+
## [0.1.8] - 2026-03-17
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- Watchdog `expire` guards against missing `Legion::Data::Model::Node` constant before use, returning an error hash when the model is unavailable
|
|
28
|
+
|
|
3
29
|
## [0.1.7] - 2026-03-16
|
|
4
30
|
|
|
5
31
|
### Fixed
|
data/CLAUDE.md
CHANGED
data/README.md
CHANGED
|
@@ -15,9 +15,9 @@ gem install lex-health
|
|
|
15
15
|
|
|
16
16
|
## How It Works
|
|
17
17
|
|
|
18
|
-
The Health runner receives heartbeat messages published by `lex-node` and upserts node records in the database. It uses timestamp comparison to prevent out-of-order updates from rolling back newer status.
|
|
18
|
+
The Health runner receives heartbeat messages published by `lex-node` and upserts node records in the database. It uses timestamp comparison to prevent out-of-order updates from rolling back newer status. On each update it also marks all digital workers reported by the node as `online` and any workers no longer reported as `unknown`.
|
|
19
19
|
|
|
20
|
-
The Watchdog actor runs every 5 seconds and queries for healthy nodes whose last heartbeat timestamp is older than `expire_time` seconds (default: 60 seconds).
|
|
20
|
+
The Watchdog actor runs every 5 seconds and queries for healthy nodes whose last heartbeat timestamp is older than `expire_time` seconds (default: 60 seconds). Expired nodes are transitioned to `unknown` and all digital workers hosted on that node are marked `offline`.
|
|
21
21
|
|
|
22
22
|
## Requirements
|
|
23
23
|
|
data/lex-health.gemspec
CHANGED
|
@@ -28,6 +28,14 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
end
|
|
29
29
|
spec.require_paths = ['lib']
|
|
30
30
|
|
|
31
|
+
spec.add_dependency 'legion-cache', '>= 1.3.11'
|
|
32
|
+
spec.add_dependency 'legion-crypt', '>= 1.4.9'
|
|
33
|
+
spec.add_dependency 'legion-data', '>= 1.4.17'
|
|
34
|
+
spec.add_dependency 'legion-json', '>= 1.2.1'
|
|
35
|
+
spec.add_dependency 'legion-logging', '>= 1.3.2'
|
|
36
|
+
spec.add_dependency 'legion-settings', '>= 1.3.14'
|
|
37
|
+
spec.add_dependency 'legion-transport', '>= 1.3.9'
|
|
38
|
+
|
|
31
39
|
spec.add_development_dependency 'rake'
|
|
32
40
|
spec.add_development_dependency 'rspec'
|
|
33
41
|
spec.add_development_dependency 'rubocop'
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
3
5
|
module Legion
|
|
4
6
|
module Extensions
|
|
5
7
|
module Health
|
|
@@ -16,7 +18,7 @@ module Legion
|
|
|
16
18
|
return { success: result, hostname: hostname, **opts }
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
if opts.key?(:timestamp) &&
|
|
21
|
+
if opts.key?(:timestamp) && item.values[:updated] && item.values[:updated] > Time.parse(opts[:timestamp])
|
|
20
22
|
return { success: false,
|
|
21
23
|
reason: 'entry already updated',
|
|
22
24
|
hostname: hostname,
|
|
@@ -24,9 +26,9 @@ module Legion
|
|
|
24
26
|
**opts }
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
update_hash = { active:
|
|
28
|
-
update_hash[:metrics] =
|
|
29
|
-
update_hash[:hosted_worker_ids] =
|
|
29
|
+
update_hash = { active: true, status: opts[:status], name: hostname, updated: Sequel::CURRENT_TIMESTAMP }
|
|
30
|
+
update_hash[:metrics] = json_dump(opts[:metrics]) if opts[:metrics]
|
|
31
|
+
update_hash[:hosted_worker_ids] = json_dump(opts[:hosted_worker_ids]) if opts[:hosted_worker_ids]
|
|
30
32
|
update_hash[:version] = opts[:version] if opts[:version]
|
|
31
33
|
item.update(update_hash)
|
|
32
34
|
|
|
@@ -36,19 +38,27 @@ module Legion
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def insert(hostname:, status: 'unknown', **opts)
|
|
39
|
-
insert = { active:
|
|
41
|
+
insert = { active: true, status: status, name: hostname }
|
|
40
42
|
insert[:datacenter_id] = opts[:datacenter_id] if opts.key? :datacenter_id
|
|
41
43
|
insert[:environment_id] = opts[:environment_id] if opts.key? :environment_id
|
|
42
|
-
insert[:
|
|
43
|
-
insert[:
|
|
44
|
-
insert[:hosted_worker_ids] = Legion::JSON.dump(opts[:hosted_worker_ids]) if opts[:hosted_worker_ids]
|
|
44
|
+
insert[:metrics] = json_dump(opts[:metrics]) if opts[:metrics]
|
|
45
|
+
insert[:hosted_worker_ids] = json_dump(opts[:hosted_worker_ids]) if opts[:hosted_worker_ids]
|
|
45
46
|
insert[:version] = opts[:version] if opts[:version]
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
node_id = begin
|
|
49
|
+
Legion::Data::Model::Node.insert(insert)
|
|
50
|
+
rescue Sequel::UniqueConstraintViolation
|
|
51
|
+
item = Legion::Data::Model::Node[name: hostname]
|
|
52
|
+
item&.id
|
|
53
|
+
end
|
|
54
|
+
{ success: true, hostname: hostname, node_id: node_id, **insert }
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
def delete(node_id:, **_opts)
|
|
51
|
-
Legion::Data::Model::Node[node_id]
|
|
58
|
+
node = Legion::Data::Model::Node[node_id]
|
|
59
|
+
return { success: false, error: 'node not found', node_id: node_id } if node.nil?
|
|
60
|
+
|
|
61
|
+
node.delete
|
|
52
62
|
{ success: true, node_id: node_id }
|
|
53
63
|
end
|
|
54
64
|
|
|
@@ -8,6 +8,8 @@ module Legion
|
|
|
8
8
|
include Legion::Extensions::Helpers::Lex
|
|
9
9
|
|
|
10
10
|
def expire(expire_time: 60, **_opts)
|
|
11
|
+
return { success: false, reason: 'Legion::Data::Model::Node not available' } unless defined?(Legion::Data::Model::Node)
|
|
12
|
+
|
|
11
13
|
cutoff = Time.now - expire_time
|
|
12
14
|
nodes = []
|
|
13
15
|
Legion::Data::Model::Node
|
|
@@ -36,7 +38,7 @@ module Legion
|
|
|
36
38
|
Legion::Data::Model::DigitalWorker
|
|
37
39
|
.where(health_node: node_name, health_status: 'online')
|
|
38
40
|
.each do |worker|
|
|
39
|
-
worker.update(health_status: 'offline')
|
|
41
|
+
worker.update(health_status: 'offline', health_node: nil)
|
|
40
42
|
end
|
|
41
43
|
rescue StandardError => e
|
|
42
44
|
log.warn "worker offline marking failed: #{e.message}" if respond_to?(:log)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-health
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -9,6 +9,104 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-cache
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.3.11
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 1.3.11
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: legion-crypt
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.4.9
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 1.4.9
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: legion-data
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 1.4.17
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 1.4.17
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: legion-json
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: 1.2.1
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: 1.2.1
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: legion-logging
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 1.3.2
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: 1.3.2
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: legion-settings
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: 1.3.14
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: 1.3.14
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: legion-transport
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 1.3.9
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: 1.3.9
|
|
12
110
|
- !ruby/object:Gem::Dependency
|
|
13
111
|
name: rake
|
|
14
112
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,7 +198,6 @@ executables: []
|
|
|
100
198
|
extensions: []
|
|
101
199
|
extra_rdoc_files: []
|
|
102
200
|
files:
|
|
103
|
-
- ".circleci/config.yml"
|
|
104
201
|
- ".github/workflows/ci.yml"
|
|
105
202
|
- ".gitignore"
|
|
106
203
|
- ".rspec"
|
|
@@ -109,7 +206,6 @@ files:
|
|
|
109
206
|
- CLAUDE.md
|
|
110
207
|
- Dockerfile
|
|
111
208
|
- Gemfile
|
|
112
|
-
- Gemfile.lock
|
|
113
209
|
- LICENSE.txt
|
|
114
210
|
- README.md
|
|
115
211
|
- Rakefile
|
data/.circleci/config.yml
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
version: 2.1
|
|
2
|
-
orbs:
|
|
3
|
-
ruby: circleci/ruby@0.2.1
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
"rubocop":
|
|
7
|
-
docker:
|
|
8
|
-
- image: circleci/ruby:2.5-node
|
|
9
|
-
steps:
|
|
10
|
-
- checkout
|
|
11
|
-
- ruby/load-cache
|
|
12
|
-
- ruby/install-deps
|
|
13
|
-
- run:
|
|
14
|
-
name: Run Rubocop
|
|
15
|
-
command: bundle exec rubocop
|
|
16
|
-
- ruby/save-cache
|
|
17
|
-
"ruby-two-five":
|
|
18
|
-
docker:
|
|
19
|
-
- image: circleci/ruby:2.5
|
|
20
|
-
- image: memcached:1.5-alpine
|
|
21
|
-
steps:
|
|
22
|
-
- checkout
|
|
23
|
-
- ruby/load-cache
|
|
24
|
-
- ruby/install-deps
|
|
25
|
-
- ruby/run-tests
|
|
26
|
-
- ruby/save-cache
|
|
27
|
-
"ruby-two-six":
|
|
28
|
-
docker:
|
|
29
|
-
- image: circleci/ruby:2.6
|
|
30
|
-
- image: memcached:1.5-alpine
|
|
31
|
-
steps:
|
|
32
|
-
- checkout
|
|
33
|
-
- ruby/load-cache
|
|
34
|
-
- ruby/install-deps
|
|
35
|
-
- ruby/run-tests
|
|
36
|
-
- ruby/save-cache
|
|
37
|
-
"ruby-two-seven":
|
|
38
|
-
docker:
|
|
39
|
-
- image: circleci/ruby:2.7
|
|
40
|
-
- image: memcached:1.5-alpine
|
|
41
|
-
steps:
|
|
42
|
-
- checkout
|
|
43
|
-
- ruby/load-cache
|
|
44
|
-
- ruby/install-deps
|
|
45
|
-
- ruby/run-tests
|
|
46
|
-
- ruby/save-cache
|
|
47
|
-
|
|
48
|
-
workflows:
|
|
49
|
-
version: 2
|
|
50
|
-
rubocop-rspec:
|
|
51
|
-
jobs:
|
|
52
|
-
- rubocop
|
|
53
|
-
- ruby-two-five:
|
|
54
|
-
requires:
|
|
55
|
-
- rubocop
|
|
56
|
-
- ruby-two-six:
|
|
57
|
-
requires:
|
|
58
|
-
- ruby-two-five
|
|
59
|
-
- ruby-two-seven:
|
|
60
|
-
requires:
|
|
61
|
-
- ruby-two-five
|
data/Gemfile.lock
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
lex-health (0.1.7)
|
|
5
|
-
|
|
6
|
-
GEM
|
|
7
|
-
remote: https://rubygems.org/
|
|
8
|
-
specs:
|
|
9
|
-
addressable (2.8.9)
|
|
10
|
-
public_suffix (>= 2.0.2, < 8.0)
|
|
11
|
-
ast (2.4.3)
|
|
12
|
-
bigdecimal (4.0.1)
|
|
13
|
-
diff-lcs (1.6.2)
|
|
14
|
-
json (2.19.1)
|
|
15
|
-
json-schema (6.2.0)
|
|
16
|
-
addressable (~> 2.8)
|
|
17
|
-
bigdecimal (>= 3.1, < 5)
|
|
18
|
-
language_server-protocol (3.17.0.5)
|
|
19
|
-
lint_roller (1.1.0)
|
|
20
|
-
mcp (0.8.0)
|
|
21
|
-
json-schema (>= 4.1)
|
|
22
|
-
parallel (1.27.0)
|
|
23
|
-
parser (3.3.10.2)
|
|
24
|
-
ast (~> 2.4.1)
|
|
25
|
-
racc
|
|
26
|
-
prism (1.9.0)
|
|
27
|
-
public_suffix (7.0.5)
|
|
28
|
-
racc (1.8.1)
|
|
29
|
-
rainbow (3.1.1)
|
|
30
|
-
rake (13.3.1)
|
|
31
|
-
regexp_parser (2.11.3)
|
|
32
|
-
rspec (3.13.2)
|
|
33
|
-
rspec-core (~> 3.13.0)
|
|
34
|
-
rspec-expectations (~> 3.13.0)
|
|
35
|
-
rspec-mocks (~> 3.13.0)
|
|
36
|
-
rspec-core (3.13.6)
|
|
37
|
-
rspec-support (~> 3.13.0)
|
|
38
|
-
rspec-expectations (3.13.5)
|
|
39
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
40
|
-
rspec-support (~> 3.13.0)
|
|
41
|
-
rspec-mocks (3.13.8)
|
|
42
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
43
|
-
rspec-support (~> 3.13.0)
|
|
44
|
-
rspec-support (3.13.7)
|
|
45
|
-
rubocop (1.85.1)
|
|
46
|
-
json (~> 2.3)
|
|
47
|
-
language_server-protocol (~> 3.17.0.2)
|
|
48
|
-
lint_roller (~> 1.1.0)
|
|
49
|
-
mcp (~> 0.6)
|
|
50
|
-
parallel (~> 1.10)
|
|
51
|
-
parser (>= 3.3.0.2)
|
|
52
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
53
|
-
regexp_parser (>= 2.9.3, < 3.0)
|
|
54
|
-
rubocop-ast (>= 1.49.0, < 2.0)
|
|
55
|
-
ruby-progressbar (~> 1.7)
|
|
56
|
-
unicode-display_width (>= 2.4.0, < 4.0)
|
|
57
|
-
rubocop-ast (1.49.1)
|
|
58
|
-
parser (>= 3.3.7.2)
|
|
59
|
-
prism (~> 1.7)
|
|
60
|
-
rubocop-rspec (3.9.0)
|
|
61
|
-
lint_roller (~> 1.1)
|
|
62
|
-
rubocop (~> 1.81)
|
|
63
|
-
ruby-progressbar (1.13.0)
|
|
64
|
-
sequel (5.102.0)
|
|
65
|
-
bigdecimal
|
|
66
|
-
sqlite3 (2.9.2-arm64-darwin)
|
|
67
|
-
sqlite3 (2.9.2-x86_64-linux-gnu)
|
|
68
|
-
unicode-display_width (3.2.0)
|
|
69
|
-
unicode-emoji (~> 4.1)
|
|
70
|
-
unicode-emoji (4.2.0)
|
|
71
|
-
|
|
72
|
-
PLATFORMS
|
|
73
|
-
arm64-darwin-25
|
|
74
|
-
x86_64-linux
|
|
75
|
-
|
|
76
|
-
DEPENDENCIES
|
|
77
|
-
lex-health!
|
|
78
|
-
rake
|
|
79
|
-
rspec
|
|
80
|
-
rubocop
|
|
81
|
-
rubocop-rspec
|
|
82
|
-
sequel
|
|
83
|
-
sqlite3
|
|
84
|
-
|
|
85
|
-
BUNDLED WITH
|
|
86
|
-
2.6.9
|