lex-swarm-github 0.2.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 164c564b62ef684027798c73f8c8137083a55e72df5f0d9204a627789a172472
4
- data.tar.gz: 4368bd456b18a7af926460954c76ba8c4da25bbf2233dcdc1541c9fb6949e9ff
3
+ metadata.gz: 51af406fe3fd169d214ad624baa8397ea249af6fd6b2931ce0c16e05476b3089
4
+ data.tar.gz: dff84459e2f0fb6966b1942c271feac122d146d31f44a32a1e3949db3296b7fd
5
5
  SHA512:
6
- metadata.gz: 022a87a111bda8aadf4517c53a70573f5cc9b95f53dad7eb9c4b7c870d695ce783084ff98e64e64b3d769ec8849e8c03112ea0f6ce55e59a9d2dd6f508a2bdb5
7
- data.tar.gz: 60ac0a083878d8bfd2bce7513a91998cddb4c26e324a1160a8f9af1f6f62c05f040ebff300efef86fc399647bccad08561d4e1608e2b7a3db4420232b194f69a
6
+ metadata.gz: 185c32b2089ea81b7d714437c5ea2a468e6e20114831c466466905b548fe499ff1c7734bc6a76cf5fcdad91c279bd56baa0887e5519fdf7c15c58b1c6c5026c4
7
+ data.tar.gz: f17146fded2ba6da1e07e742aaec32f942d2efa8501a66958fbdb00bf15c9c9aa2f308048cd54b1332b7f5009a2e3cf6f20de92d372b3ca53cfa914ee93bb6bb
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module SwarmGithub
6
+ module Helpers
7
+ module MeshIntegration
8
+ AGENT_ID = 'swarm-github-code-reviewer'
9
+ CAPABILITIES = %i[code_review pr_review].freeze
10
+
11
+ module_function
12
+
13
+ def register_reviewer
14
+ return { skipped: true, reason: 'lex-mesh not available' } unless mesh_available?
15
+
16
+ Legion::Extensions::Mesh::Client.new.register(
17
+ agent_id: AGENT_ID,
18
+ capabilities: CAPABILITIES,
19
+ endpoint: 'local'
20
+ )
21
+ end
22
+
23
+ def record_review_start(charter_id:, owner:, repo:, pull_number:)
24
+ return unless workspace_available?
25
+
26
+ Legion::Extensions::Swarm::Client.new.workspace_put(
27
+ charter_id: charter_id,
28
+ key: "review:#{owner}/#{repo}##{pull_number}",
29
+ value: { status: 'in_progress', started_at: Time.now.utc.to_s },
30
+ author: AGENT_ID
31
+ )
32
+ end
33
+
34
+ def record_review_complete(charter_id:, owner:, repo:, pull_number:, result:)
35
+ return unless workspace_available?
36
+
37
+ Legion::Extensions::Swarm::Client.new.workspace_put(
38
+ charter_id: charter_id,
39
+ key: "review:#{owner}/#{repo}##{pull_number}",
40
+ value: {
41
+ status: result[:review]&.dig(:status) || 'unknown',
42
+ posted: result[:post]&.dig(:posted) || false,
43
+ comments_count: result[:post]&.dig(:comments_count) || 0,
44
+ completed_at: Time.now.utc.to_s
45
+ },
46
+ author: AGENT_ID
47
+ )
48
+ end
49
+
50
+ def mesh_available?
51
+ defined?(Legion::Extensions::Mesh::Client)
52
+ end
53
+
54
+ def workspace_available?
55
+ defined?(Legion::Extensions::Swarm::Client)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative '../helpers/mesh_integration'
4
+
3
5
  module Legion
4
6
  module Extensions
5
7
  module SwarmGithub
@@ -32,6 +34,27 @@ module Legion
32
34
  run_review_pipeline(owner: owner, repo: repo, pull_number: pull_number,
33
35
  slack_channel: slack_channel)
34
36
  end
37
+
38
+ def handle_mesh_review_request(payload:, charter_id: nil, **)
39
+ owner = payload[:owner] || payload['owner']
40
+ repo = payload[:repo] || payload['repo']
41
+ pull_number = payload[:pull_number] || payload['pull_number']
42
+
43
+ return { success: false, reason: :missing_params } unless owner && repo && pull_number
44
+
45
+ cid = charter_id || "mesh-review-#{owner}-#{repo}-#{pull_number}"
46
+ Helpers::MeshIntegration.record_review_start(
47
+ charter_id: cid, owner: owner, repo: repo, pull_number: pull_number
48
+ )
49
+
50
+ result = run_review_pipeline(owner: owner, repo: repo, pull_number: pull_number)
51
+
52
+ Helpers::MeshIntegration.record_review_complete(
53
+ charter_id: cid, owner: owner, repo: repo, pull_number: pull_number, result: result
54
+ )
55
+
56
+ result.merge(success: true)
57
+ end
35
58
  end
36
59
  end
37
60
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module SwarmGithub
6
- VERSION = '0.2.0'
6
+ VERSION = '0.2.1'
7
7
  end
8
8
  end
9
9
  end
@@ -3,6 +3,7 @@
3
3
  require 'legion/extensions/swarm_github/version'
4
4
  require 'legion/extensions/swarm_github/helpers/pipeline'
5
5
  require 'legion/extensions/swarm_github/helpers/issue_tracker'
6
+ require 'legion/extensions/swarm_github/helpers/mesh_integration'
6
7
  require 'legion/extensions/swarm_github/runners/github_swarm'
7
8
  require 'legion/extensions/swarm_github/runners/pull_request_reviewer'
8
9
  require 'legion/extensions/swarm_github/helpers/diff_chunker'
@@ -0,0 +1,155 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'legion/extensions/swarm_github/helpers/mesh_integration'
5
+
6
+ RSpec.describe Legion::Extensions::SwarmGithub::Helpers::MeshIntegration do
7
+ subject(:mod) { described_class }
8
+
9
+ describe '.mesh_available?' do
10
+ it 'returns falsy when Mesh::Client is not defined' do
11
+ expect(mod.mesh_available?).to be_falsy
12
+ end
13
+
14
+ it 'returns truthy when Mesh::Client is defined' do
15
+ stub_const('Legion::Extensions::Mesh::Client', Class.new)
16
+ expect(mod.mesh_available?).to be_truthy
17
+ end
18
+ end
19
+
20
+ describe '.workspace_available?' do
21
+ it 'returns falsy when Swarm::Client is not defined' do
22
+ expect(mod.workspace_available?).to be_falsy
23
+ end
24
+
25
+ it 'returns truthy when Swarm::Client is defined' do
26
+ stub_const('Legion::Extensions::Swarm::Client', Class.new)
27
+ expect(mod.workspace_available?).to be_truthy
28
+ end
29
+ end
30
+
31
+ describe '.register_reviewer' do
32
+ context 'when lex-mesh is not available' do
33
+ it 'returns skipped hash' do
34
+ result = mod.register_reviewer
35
+ expect(result[:skipped]).to be true
36
+ expect(result[:reason]).to eq('lex-mesh not available')
37
+ end
38
+ end
39
+
40
+ context 'when lex-mesh is available' do
41
+ let(:mesh_client) { instance_double('Legion::Extensions::Mesh::Client') }
42
+
43
+ before do
44
+ stub_const('Legion::Extensions::Mesh::Client', Class.new)
45
+ allow(Legion::Extensions::Mesh::Client).to receive(:new).and_return(mesh_client)
46
+ allow(mesh_client).to receive(:register).and_return({ success: true, registered: true,
47
+ agent_id: described_class::AGENT_ID })
48
+ end
49
+
50
+ it 'calls register on a Mesh::Client instance' do
51
+ expect(mesh_client).to receive(:register).with(
52
+ agent_id: described_class::AGENT_ID,
53
+ capabilities: described_class::CAPABILITIES,
54
+ endpoint: 'local'
55
+ )
56
+ mod.register_reviewer
57
+ end
58
+
59
+ it 'returns the registration result' do
60
+ result = mod.register_reviewer
61
+ expect(result[:success]).to be true
62
+ expect(result[:registered]).to be true
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '.record_review_start' do
68
+ let(:params) { { charter_id: 'cid-1', owner: 'org', repo: 'myrepo', pull_number: 42 } }
69
+
70
+ context 'when lex-swarm is not available' do
71
+ it 'returns nil' do
72
+ expect(mod.record_review_start(**params)).to be_nil
73
+ end
74
+ end
75
+
76
+ context 'when lex-swarm is available' do
77
+ let(:swarm_client) { instance_double('Legion::Extensions::Swarm::Client') }
78
+
79
+ before do
80
+ stub_const('Legion::Extensions::Swarm::Client', Class.new)
81
+ allow(Legion::Extensions::Swarm::Client).to receive(:new).and_return(swarm_client)
82
+ allow(swarm_client).to receive(:workspace_put).and_return({ success: true })
83
+ end
84
+
85
+ it 'calls workspace_put with in_progress status' do
86
+ expect(swarm_client).to receive(:workspace_put).with(
87
+ charter_id: 'cid-1',
88
+ key: 'review:org/myrepo#42',
89
+ value: hash_including(status: 'in_progress'),
90
+ author: described_class::AGENT_ID
91
+ )
92
+ mod.record_review_start(**params)
93
+ end
94
+
95
+ it 'includes started_at timestamp' do
96
+ expect(swarm_client).to receive(:workspace_put).with(
97
+ hash_including(value: hash_including(:started_at))
98
+ )
99
+ mod.record_review_start(**params)
100
+ end
101
+ end
102
+ end
103
+
104
+ describe '.record_review_complete' do
105
+ let(:result) do
106
+ {
107
+ review: { status: 'reviewed' },
108
+ post: { posted: true, comments_count: 3 },
109
+ notify: { notified: true }
110
+ }
111
+ end
112
+ let(:params) { { charter_id: 'cid-1', owner: 'org', repo: 'myrepo', pull_number: 42, result: result } }
113
+
114
+ context 'when lex-swarm is not available' do
115
+ it 'returns nil' do
116
+ expect(mod.record_review_complete(**params)).to be_nil
117
+ end
118
+ end
119
+
120
+ context 'when lex-swarm is available' do
121
+ let(:swarm_client) { instance_double('Legion::Extensions::Swarm::Client') }
122
+
123
+ before do
124
+ stub_const('Legion::Extensions::Swarm::Client', Class.new)
125
+ allow(Legion::Extensions::Swarm::Client).to receive(:new).and_return(swarm_client)
126
+ allow(swarm_client).to receive(:workspace_put).and_return({ success: true })
127
+ end
128
+
129
+ it 'calls workspace_put with final status from result' do
130
+ expect(swarm_client).to receive(:workspace_put).with(
131
+ charter_id: 'cid-1',
132
+ key: 'review:org/myrepo#42',
133
+ value: hash_including(status: 'reviewed', posted: true, comments_count: 3),
134
+ author: described_class::AGENT_ID
135
+ )
136
+ mod.record_review_complete(**params)
137
+ end
138
+
139
+ it 'includes completed_at timestamp' do
140
+ expect(swarm_client).to receive(:workspace_put).with(
141
+ hash_including(value: hash_including(:completed_at))
142
+ )
143
+ mod.record_review_complete(**params)
144
+ end
145
+
146
+ it 'handles missing review status gracefully' do
147
+ result_no_status = { review: nil, post: nil, notify: nil }
148
+ expect(swarm_client).to receive(:workspace_put).with(
149
+ hash_including(value: hash_including(status: 'unknown', posted: false, comments_count: 0))
150
+ )
151
+ mod.record_review_complete(**params, result: result_no_status)
152
+ end
153
+ end
154
+ end
155
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
  require 'legion/extensions/swarm_github/helpers/pipeline'
5
+ require 'legion/extensions/swarm_github/helpers/mesh_integration'
5
6
  require 'legion/extensions/swarm_github/runners/pull_request_reviewer'
6
7
  require 'legion/extensions/swarm_github/runners/review_poster'
7
8
  require 'legion/extensions/swarm_github/runners/review_notifier'
@@ -109,4 +110,89 @@ RSpec.describe Legion::Extensions::SwarmGithub::Runners::PrPipeline do
109
110
  expect(result[:reason]).to eq('action not reviewable')
110
111
  end
111
112
  end
113
+
114
+ describe '#handle_mesh_review_request' do
115
+ let(:review_result) do
116
+ { review: { status: 'reviewed' }, post: { posted: true, comments_count: 2 }, notify: { notified: true } }
117
+ end
118
+
119
+ before do
120
+ allow(pipeline).to receive(:run_review_pipeline).and_return(review_result)
121
+ allow(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_start)
122
+ allow(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_complete)
123
+ end
124
+
125
+ it 'returns success: false when owner is missing' do
126
+ result = pipeline.handle_mesh_review_request(payload: { repo: 'myrepo', pull_number: 1 })
127
+ expect(result[:success]).to be false
128
+ expect(result[:reason]).to eq(:missing_params)
129
+ end
130
+
131
+ it 'returns success: false when repo is missing' do
132
+ result = pipeline.handle_mesh_review_request(payload: { owner: 'org', pull_number: 1 })
133
+ expect(result[:success]).to be false
134
+ expect(result[:reason]).to eq(:missing_params)
135
+ end
136
+
137
+ it 'returns success: false when pull_number is missing' do
138
+ result = pipeline.handle_mesh_review_request(payload: { owner: 'org', repo: 'myrepo' })
139
+ expect(result[:success]).to be false
140
+ expect(result[:reason]).to eq(:missing_params)
141
+ end
142
+
143
+ it 'calls run_review_pipeline with extracted params' do
144
+ expect(pipeline).to receive(:run_review_pipeline)
145
+ .with(hash_including(owner: 'org', repo: 'myrepo', pull_number: 42))
146
+ .and_return(review_result)
147
+
148
+ pipeline.handle_mesh_review_request(payload: { owner: 'org', repo: 'myrepo', pull_number: 42 })
149
+ end
150
+
151
+ it 'merges success: true into pipeline result' do
152
+ result = pipeline.handle_mesh_review_request(
153
+ payload: { owner: 'org', repo: 'myrepo', pull_number: 42 }
154
+ )
155
+ expect(result[:success]).to be true
156
+ expect(result[:review][:status]).to eq('reviewed')
157
+ end
158
+
159
+ it 'accepts string-keyed payload' do
160
+ expect(pipeline).to receive(:run_review_pipeline)
161
+ .with(hash_including(owner: 'org', repo: 'myrepo', pull_number: 5))
162
+ .and_return(review_result)
163
+
164
+ pipeline.handle_mesh_review_request(payload: { 'owner' => 'org', 'repo' => 'myrepo', 'pull_number' => 5 })
165
+ end
166
+
167
+ it 'records workspace start before pipeline runs' do
168
+ expect(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_start).ordered
169
+ expect(pipeline).to receive(:run_review_pipeline).ordered.and_return(review_result)
170
+
171
+ pipeline.handle_mesh_review_request(payload: { owner: 'org', repo: 'myrepo', pull_number: 1 })
172
+ end
173
+
174
+ it 'records workspace complete after pipeline runs' do
175
+ expect(pipeline).to receive(:run_review_pipeline).ordered.and_return(review_result)
176
+ expect(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_complete).ordered
177
+
178
+ pipeline.handle_mesh_review_request(payload: { owner: 'org', repo: 'myrepo', pull_number: 1 })
179
+ end
180
+
181
+ it 'uses provided charter_id for workspace calls' do
182
+ expect(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_start)
183
+ .with(hash_including(charter_id: 'my-charter'))
184
+
185
+ pipeline.handle_mesh_review_request(
186
+ payload: { owner: 'org', repo: 'myrepo', pull_number: 1 },
187
+ charter_id: 'my-charter'
188
+ )
189
+ end
190
+
191
+ it 'generates a charter_id when none provided' do
192
+ expect(Legion::Extensions::SwarmGithub::Helpers::MeshIntegration).to receive(:record_review_start)
193
+ .with(hash_including(charter_id: 'mesh-review-org-myrepo-42'))
194
+
195
+ pipeline.handle_mesh_review_request(payload: { owner: 'org', repo: 'myrepo', pull_number: 42 })
196
+ end
197
+ end
112
198
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-swarm-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -25,6 +25,7 @@ files:
25
25
  - lib/legion/extensions/swarm_github/client.rb
26
26
  - lib/legion/extensions/swarm_github/helpers/diff_chunker.rb
27
27
  - lib/legion/extensions/swarm_github/helpers/issue_tracker.rb
28
+ - lib/legion/extensions/swarm_github/helpers/mesh_integration.rb
28
29
  - lib/legion/extensions/swarm_github/helpers/pipeline.rb
29
30
  - lib/legion/extensions/swarm_github/runners/github_swarm.rb
30
31
  - lib/legion/extensions/swarm_github/runners/pr_pipeline.rb
@@ -37,6 +38,7 @@ files:
37
38
  - spec/legion/extensions/swarm_github/client_spec.rb
38
39
  - spec/legion/extensions/swarm_github/helpers/diff_chunker_spec.rb
39
40
  - spec/legion/extensions/swarm_github/helpers/issue_tracker_spec.rb
41
+ - spec/legion/extensions/swarm_github/helpers/mesh_integration_spec.rb
40
42
  - spec/legion/extensions/swarm_github/helpers/pipeline_spec.rb
41
43
  - spec/legion/extensions/swarm_github/runners/github_swarm_spec.rb
42
44
  - spec/legion/extensions/swarm_github/runners/pr_pipeline_spec.rb