spec_scout 0.1.0
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 +7 -0
- data/.idea/.gitignore +10 -0
- data/.idea/Projects.iml +41 -0
- data/.idea/copilot.data.migration.ask2agent.xml +6 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.rspec_status +236 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +72 -0
- data/LICENSE +21 -0
- data/README.md +433 -0
- data/Rakefile +12 -0
- data/examples/README.md +321 -0
- data/examples/best_practices.md +401 -0
- data/examples/configurations/basic_config.rb +24 -0
- data/examples/configurations/ci_config.rb +35 -0
- data/examples/configurations/conservative_config.rb +32 -0
- data/examples/configurations/development_config.rb +37 -0
- data/examples/configurations/performance_focused_config.rb +38 -0
- data/examples/output_formatter_demo.rb +67 -0
- data/examples/sample_outputs/console_output_high_confidence.txt +27 -0
- data/examples/sample_outputs/console_output_medium_confidence.txt +27 -0
- data/examples/sample_outputs/console_output_no_action.txt +27 -0
- data/examples/sample_outputs/console_output_risk_detected.txt +27 -0
- data/examples/sample_outputs/json_output_high_confidence.json +108 -0
- data/examples/sample_outputs/json_output_no_action.json +108 -0
- data/examples/workflows/basic_workflow.md +159 -0
- data/examples/workflows/ci_integration.md +372 -0
- data/exe/spec_scout +7 -0
- data/lib/spec_scout/agent_result.rb +44 -0
- data/lib/spec_scout/agents/database_agent.rb +113 -0
- data/lib/spec_scout/agents/factory_agent.rb +179 -0
- data/lib/spec_scout/agents/intent_agent.rb +223 -0
- data/lib/spec_scout/agents/risk_agent.rb +290 -0
- data/lib/spec_scout/base_agent.rb +72 -0
- data/lib/spec_scout/cli.rb +158 -0
- data/lib/spec_scout/configuration.rb +162 -0
- data/lib/spec_scout/consensus_engine.rb +535 -0
- data/lib/spec_scout/enforcement_handler.rb +182 -0
- data/lib/spec_scout/output_formatter.rb +307 -0
- data/lib/spec_scout/profile_data.rb +37 -0
- data/lib/spec_scout/profile_normalizer.rb +238 -0
- data/lib/spec_scout/recommendation.rb +62 -0
- data/lib/spec_scout/safety_validator.rb +127 -0
- data/lib/spec_scout/spec_scout.rb +519 -0
- data/lib/spec_scout/testprof_integration.rb +206 -0
- data/lib/spec_scout/version.rb +5 -0
- data/lib/spec_scout.rb +43 -0
- metadata +166 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# Basic SpecScout Workflow
|
|
2
|
+
|
|
3
|
+
This document outlines the recommended workflow for using SpecScout in your development process.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. **Install SpecScout**
|
|
8
|
+
```bash
|
|
9
|
+
# Add to Gemfile
|
|
10
|
+
gem 'spec_scout'
|
|
11
|
+
|
|
12
|
+
# Install
|
|
13
|
+
bundle install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
2. **Configure SpecScout**
|
|
17
|
+
```ruby
|
|
18
|
+
# spec/spec_helper.rb
|
|
19
|
+
require 'spec_scout'
|
|
20
|
+
|
|
21
|
+
SpecScout.configure do |config|
|
|
22
|
+
config.enable = true
|
|
23
|
+
config.use_test_prof = true
|
|
24
|
+
config.enabled_agents = [:database, :factory, :intent, :risk]
|
|
25
|
+
config.output_format = :console
|
|
26
|
+
end
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Development Workflow
|
|
30
|
+
|
|
31
|
+
### Step 1: Run Your Tests Normally
|
|
32
|
+
```bash
|
|
33
|
+
# Run your test suite as usual
|
|
34
|
+
bundle exec rspec spec/models/user_spec.rb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Step 2: Analyze with SpecScout
|
|
38
|
+
```bash
|
|
39
|
+
# Analyze specific spec file
|
|
40
|
+
bundle exec spec_scout spec/models/user_spec.rb
|
|
41
|
+
|
|
42
|
+
# Or analyze entire test suite
|
|
43
|
+
bundle exec spec_scout
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Step 3: Review Recommendations
|
|
47
|
+
SpecScout will output recommendations like:
|
|
48
|
+
```
|
|
49
|
+
✔ Spec Scout Recommendation
|
|
50
|
+
|
|
51
|
+
spec/models/user_spec.rb:42
|
|
52
|
+
|
|
53
|
+
Summary:
|
|
54
|
+
- Factory :user used `create` (3x)
|
|
55
|
+
- DB inserts: 3, selects: 5
|
|
56
|
+
- Runtime: 150ms
|
|
57
|
+
|
|
58
|
+
Agent Signals:
|
|
59
|
+
- Database Agent: DB unnecessary (✔ HIGH)
|
|
60
|
+
- Factory Agent: prefer build_stubbed (⚠ MEDIUM)
|
|
61
|
+
- Intent Agent: unit test behavior (✔ HIGH)
|
|
62
|
+
- Risk Agent: safe to optimize (✔ HIGH)
|
|
63
|
+
|
|
64
|
+
Final Recommendation:
|
|
65
|
+
✔ Replace `create(:user)` with `build_stubbed(:user)`
|
|
66
|
+
Confidence: ✔ HIGH
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Step 4: Apply Recommendations
|
|
70
|
+
Based on the confidence level:
|
|
71
|
+
|
|
72
|
+
**High Confidence (✔)**: Safe to apply immediately
|
|
73
|
+
```ruby
|
|
74
|
+
# Before
|
|
75
|
+
let(:user) { create(:user) }
|
|
76
|
+
|
|
77
|
+
# After
|
|
78
|
+
let(:user) { build_stubbed(:user) }
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Medium Confidence (⚠)**: Review and test carefully
|
|
82
|
+
- Apply in development environment first
|
|
83
|
+
- Run full test suite after changes
|
|
84
|
+
- Monitor for any behavioral changes
|
|
85
|
+
|
|
86
|
+
**Low Confidence (?)**: Manual investigation required
|
|
87
|
+
- Review the reasoning provided
|
|
88
|
+
- Consider the specific test context
|
|
89
|
+
- May require domain knowledge to decide
|
|
90
|
+
|
|
91
|
+
### Step 5: Verify Changes
|
|
92
|
+
```bash
|
|
93
|
+
# Run tests again to ensure they still pass
|
|
94
|
+
bundle exec rspec spec/models/user_spec.rb
|
|
95
|
+
|
|
96
|
+
# Check performance improvement
|
|
97
|
+
bundle exec rspec spec/models/user_spec.rb --profile
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Best Practices
|
|
101
|
+
|
|
102
|
+
### 1. Start Small
|
|
103
|
+
- Begin with high-confidence recommendations
|
|
104
|
+
- Apply changes to one spec file at a time
|
|
105
|
+
- Verify each change before moving to the next
|
|
106
|
+
|
|
107
|
+
### 2. Understand Your Tests
|
|
108
|
+
- Review the agent reasoning
|
|
109
|
+
- Consider your test's specific requirements
|
|
110
|
+
- Don't blindly apply all recommendations
|
|
111
|
+
|
|
112
|
+
### 3. Monitor Performance
|
|
113
|
+
- Measure test suite performance before and after changes
|
|
114
|
+
- Use TestProf directly for detailed performance analysis
|
|
115
|
+
- Track improvements over time
|
|
116
|
+
|
|
117
|
+
### 4. Safety First
|
|
118
|
+
- Always run your full test suite after applying changes
|
|
119
|
+
- Use version control to track changes
|
|
120
|
+
- Consider the risk assessment from the Risk Agent
|
|
121
|
+
|
|
122
|
+
## Common Scenarios
|
|
123
|
+
|
|
124
|
+
### Unit Tests
|
|
125
|
+
- High confidence for `build_stubbed` recommendations
|
|
126
|
+
- Focus on Database and Factory agents
|
|
127
|
+
- Usually safe to optimize aggressively
|
|
128
|
+
|
|
129
|
+
### Integration Tests
|
|
130
|
+
- More conservative approach recommended
|
|
131
|
+
- Pay attention to Intent Agent feedback
|
|
132
|
+
- Database persistence often required
|
|
133
|
+
|
|
134
|
+
### Controller Tests
|
|
135
|
+
- Mixed signals are common
|
|
136
|
+
- Consider test boundaries carefully
|
|
137
|
+
- May benefit from stubbing external dependencies
|
|
138
|
+
|
|
139
|
+
### System/Feature Tests
|
|
140
|
+
- Usually require database persistence
|
|
141
|
+
- Focus on factory optimization rather than strategy changes
|
|
142
|
+
- Consider test data setup efficiency
|
|
143
|
+
|
|
144
|
+
## Troubleshooting
|
|
145
|
+
|
|
146
|
+
### No Recommendations
|
|
147
|
+
- Ensure TestProf is working: `bundle exec rspec --profile`
|
|
148
|
+
- Check SpecScout configuration
|
|
149
|
+
- Verify agents are enabled
|
|
150
|
+
|
|
151
|
+
### Unexpected Recommendations
|
|
152
|
+
- Enable debug mode: `SPEC_SCOUT_DEBUG=1`
|
|
153
|
+
- Review agent reasoning
|
|
154
|
+
- Consider test-specific context
|
|
155
|
+
|
|
156
|
+
### Performance Regression
|
|
157
|
+
- Revert changes and analyze
|
|
158
|
+
- Check for missing test coverage
|
|
159
|
+
- Consider test intent vs. implementation
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
# CI Integration Workflow
|
|
2
|
+
|
|
3
|
+
This document provides guidance for integrating SpecScout into your Continuous Integration pipeline.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
SpecScout can be integrated into CI to:
|
|
8
|
+
- Automatically identify optimization opportunities
|
|
9
|
+
- Enforce performance standards
|
|
10
|
+
- Generate reports for code review
|
|
11
|
+
- Track test performance over time
|
|
12
|
+
|
|
13
|
+
## GitHub Actions Integration
|
|
14
|
+
|
|
15
|
+
### Basic Analysis
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
name: SpecScout Analysis
|
|
19
|
+
|
|
20
|
+
on: [push, pull_request]
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
spec_scout:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
|
|
26
|
+
steps:
|
|
27
|
+
- name: Checkout code
|
|
28
|
+
uses: actions/checkout@v3
|
|
29
|
+
|
|
30
|
+
- name: Setup Ruby
|
|
31
|
+
uses: ruby/setup-ruby@v1
|
|
32
|
+
with:
|
|
33
|
+
ruby-version: 3.1
|
|
34
|
+
bundler-cache: true
|
|
35
|
+
|
|
36
|
+
- name: Setup database
|
|
37
|
+
run: |
|
|
38
|
+
bundle exec rails db:create
|
|
39
|
+
bundle exec rails db:migrate
|
|
40
|
+
|
|
41
|
+
- name: Run SpecScout Analysis
|
|
42
|
+
run: |
|
|
43
|
+
bundle exec spec_scout --output json > spec_scout_results.json
|
|
44
|
+
|
|
45
|
+
- name: Upload SpecScout Results
|
|
46
|
+
uses: actions/upload-artifact@v3
|
|
47
|
+
with:
|
|
48
|
+
name: spec-scout-results
|
|
49
|
+
path: spec_scout_results.json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Enforcement Mode
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
name: SpecScout Enforcement
|
|
56
|
+
|
|
57
|
+
on: [push, pull_request]
|
|
58
|
+
|
|
59
|
+
jobs:
|
|
60
|
+
spec_scout_enforcement:
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
|
|
63
|
+
steps:
|
|
64
|
+
- name: Checkout code
|
|
65
|
+
uses: actions/checkout@v3
|
|
66
|
+
|
|
67
|
+
- name: Setup Ruby
|
|
68
|
+
uses: ruby/setup-ruby@v1
|
|
69
|
+
with:
|
|
70
|
+
ruby-version: 3.1
|
|
71
|
+
bundler-cache: true
|
|
72
|
+
|
|
73
|
+
- name: Setup database
|
|
74
|
+
run: |
|
|
75
|
+
bundle exec rails db:create
|
|
76
|
+
bundle exec rails db:migrate
|
|
77
|
+
|
|
78
|
+
- name: Run SpecScout with Enforcement
|
|
79
|
+
run: |
|
|
80
|
+
bundle exec spec_scout --enforce --fail-on-high-confidence --output json
|
|
81
|
+
continue-on-error: true
|
|
82
|
+
id: spec_scout
|
|
83
|
+
|
|
84
|
+
- name: Process Results
|
|
85
|
+
if: always()
|
|
86
|
+
run: |
|
|
87
|
+
if [ ${{ steps.spec_scout.outcome }} == 'failure' ]; then
|
|
88
|
+
echo "High confidence optimizations found!"
|
|
89
|
+
echo "Review SpecScout recommendations before merging."
|
|
90
|
+
exit 1
|
|
91
|
+
else
|
|
92
|
+
echo "No high confidence optimizations found."
|
|
93
|
+
fi
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Performance Tracking
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
name: Performance Tracking
|
|
100
|
+
|
|
101
|
+
on: [push, pull_request]
|
|
102
|
+
|
|
103
|
+
jobs:
|
|
104
|
+
performance_tracking:
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
|
|
107
|
+
steps:
|
|
108
|
+
- name: Checkout code
|
|
109
|
+
uses: actions/checkout@v3
|
|
110
|
+
|
|
111
|
+
- name: Setup Ruby
|
|
112
|
+
uses: ruby/setup-ruby@v1
|
|
113
|
+
with:
|
|
114
|
+
ruby-version: 3.1
|
|
115
|
+
bundler-cache: true
|
|
116
|
+
|
|
117
|
+
- name: Setup database
|
|
118
|
+
run: |
|
|
119
|
+
bundle exec rails db:create
|
|
120
|
+
bundle exec rails db:migrate
|
|
121
|
+
|
|
122
|
+
- name: Run Tests with Profiling
|
|
123
|
+
run: |
|
|
124
|
+
bundle exec rspec --profile > test_profile.txt
|
|
125
|
+
|
|
126
|
+
- name: Run SpecScout Analysis
|
|
127
|
+
run: |
|
|
128
|
+
bundle exec spec_scout --output json > spec_scout_results.json
|
|
129
|
+
|
|
130
|
+
- name: Generate Performance Report
|
|
131
|
+
run: |
|
|
132
|
+
echo "## SpecScout Performance Analysis" >> $GITHUB_STEP_SUMMARY
|
|
133
|
+
echo "" >> $GITHUB_STEP_SUMMARY
|
|
134
|
+
|
|
135
|
+
# Extract high confidence recommendations
|
|
136
|
+
HIGH_CONFIDENCE=$(jq -r 'select(.confidence == "high") | .spec_location' spec_scout_results.json)
|
|
137
|
+
|
|
138
|
+
if [ -n "$HIGH_CONFIDENCE" ]; then
|
|
139
|
+
echo "### High Confidence Optimizations Available:" >> $GITHUB_STEP_SUMMARY
|
|
140
|
+
echo "$HIGH_CONFIDENCE" >> $GITHUB_STEP_SUMMARY
|
|
141
|
+
else
|
|
142
|
+
echo "### No high confidence optimizations found" >> $GITHUB_STEP_SUMMARY
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
- name: Upload Results
|
|
146
|
+
uses: actions/upload-artifact@v3
|
|
147
|
+
with:
|
|
148
|
+
name: performance-analysis
|
|
149
|
+
path: |
|
|
150
|
+
spec_scout_results.json
|
|
151
|
+
test_profile.txt
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## GitLab CI Integration
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
stages:
|
|
158
|
+
- test
|
|
159
|
+
- analysis
|
|
160
|
+
|
|
161
|
+
spec_scout_analysis:
|
|
162
|
+
stage: analysis
|
|
163
|
+
image: ruby:3.1
|
|
164
|
+
|
|
165
|
+
before_script:
|
|
166
|
+
- bundle install
|
|
167
|
+
- bundle exec rails db:create
|
|
168
|
+
- bundle exec rails db:migrate
|
|
169
|
+
|
|
170
|
+
script:
|
|
171
|
+
- bundle exec spec_scout --output json > spec_scout_results.json
|
|
172
|
+
|
|
173
|
+
artifacts:
|
|
174
|
+
reports:
|
|
175
|
+
junit: spec_scout_results.json
|
|
176
|
+
paths:
|
|
177
|
+
- spec_scout_results.json
|
|
178
|
+
expire_in: 1 week
|
|
179
|
+
|
|
180
|
+
only:
|
|
181
|
+
- merge_requests
|
|
182
|
+
- main
|
|
183
|
+
|
|
184
|
+
spec_scout_enforcement:
|
|
185
|
+
stage: analysis
|
|
186
|
+
image: ruby:3.1
|
|
187
|
+
|
|
188
|
+
before_script:
|
|
189
|
+
- bundle install
|
|
190
|
+
- bundle exec rails db:create
|
|
191
|
+
- bundle exec rails db:migrate
|
|
192
|
+
|
|
193
|
+
script:
|
|
194
|
+
- bundle exec spec_scout --enforce --fail-on-high-confidence
|
|
195
|
+
|
|
196
|
+
allow_failure: false
|
|
197
|
+
|
|
198
|
+
only:
|
|
199
|
+
- main
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Configuration for CI
|
|
203
|
+
|
|
204
|
+
### Environment-Specific Configuration
|
|
205
|
+
|
|
206
|
+
```ruby
|
|
207
|
+
# config/spec_scout.rb
|
|
208
|
+
SpecScout.configure do |config|
|
|
209
|
+
config.enable = true
|
|
210
|
+
config.use_test_prof = true
|
|
211
|
+
|
|
212
|
+
if ENV['CI']
|
|
213
|
+
# CI-specific configuration
|
|
214
|
+
config.output_format = :json
|
|
215
|
+
config.enforcement_mode = ENV['SPEC_SCOUT_ENFORCE'] == 'true'
|
|
216
|
+
config.fail_on_high_confidence = ENV['SPEC_SCOUT_FAIL_ON_HIGH'] == 'true'
|
|
217
|
+
|
|
218
|
+
# Focus on performance-critical agents in CI
|
|
219
|
+
config.enabled_agents = [:database, :factory]
|
|
220
|
+
else
|
|
221
|
+
# Development configuration
|
|
222
|
+
config.output_format = :console
|
|
223
|
+
config.enforcement_mode = false
|
|
224
|
+
config.enabled_agents = [:database, :factory, :intent, :risk]
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Environment Variables
|
|
230
|
+
|
|
231
|
+
Set these in your CI environment:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Enable enforcement mode
|
|
235
|
+
SPEC_SCOUT_ENFORCE=true
|
|
236
|
+
|
|
237
|
+
# Fail on high confidence recommendations
|
|
238
|
+
SPEC_SCOUT_FAIL_ON_HIGH=true
|
|
239
|
+
|
|
240
|
+
# Enable debug output
|
|
241
|
+
SPEC_SCOUT_DEBUG=true
|
|
242
|
+
|
|
243
|
+
# Disable SpecScout entirely (for debugging CI issues)
|
|
244
|
+
SPEC_SCOUT_DISABLE=true
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Processing Results
|
|
248
|
+
|
|
249
|
+
### JSON Output Processing
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
#!/bin/bash
|
|
253
|
+
# process_spec_scout_results.sh
|
|
254
|
+
|
|
255
|
+
RESULTS_FILE="spec_scout_results.json"
|
|
256
|
+
|
|
257
|
+
if [ ! -f "$RESULTS_FILE" ]; then
|
|
258
|
+
echo "No SpecScout results found"
|
|
259
|
+
exit 0
|
|
260
|
+
fi
|
|
261
|
+
|
|
262
|
+
# Extract high confidence recommendations
|
|
263
|
+
HIGH_CONFIDENCE=$(jq -r 'select(.confidence == "high")' "$RESULTS_FILE")
|
|
264
|
+
|
|
265
|
+
if [ -n "$HIGH_CONFIDENCE" ]; then
|
|
266
|
+
echo "High confidence optimizations found:"
|
|
267
|
+
echo "$HIGH_CONFIDENCE" | jq -r '.spec_location + ": " + .action'
|
|
268
|
+
|
|
269
|
+
# Fail if enforcement is enabled
|
|
270
|
+
if [ "$SPEC_SCOUT_ENFORCE" = "true" ]; then
|
|
271
|
+
exit 1
|
|
272
|
+
fi
|
|
273
|
+
else
|
|
274
|
+
echo "No high confidence optimizations found"
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
# Generate summary
|
|
278
|
+
TOTAL_RECOMMENDATIONS=$(jq -r 'length' "$RESULTS_FILE")
|
|
279
|
+
echo "Total recommendations: $TOTAL_RECOMMENDATIONS"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Pull Request Comments
|
|
283
|
+
|
|
284
|
+
```yaml
|
|
285
|
+
- name: Comment PR with SpecScout Results
|
|
286
|
+
uses: actions/github-script@v6
|
|
287
|
+
if: github.event_name == 'pull_request'
|
|
288
|
+
with:
|
|
289
|
+
script: |
|
|
290
|
+
const fs = require('fs');
|
|
291
|
+
|
|
292
|
+
if (!fs.existsSync('spec_scout_results.json')) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const results = JSON.parse(fs.readFileSync('spec_scout_results.json', 'utf8'));
|
|
297
|
+
|
|
298
|
+
if (results.confidence === 'high') {
|
|
299
|
+
const comment = `## SpecScout Analysis
|
|
300
|
+
|
|
301
|
+
High confidence optimization found in \`${results.spec_location}\`:
|
|
302
|
+
|
|
303
|
+
**Recommendation:** ${results.action}
|
|
304
|
+
**Confidence:** ${results.confidence}
|
|
305
|
+
|
|
306
|
+
**Reasoning:**
|
|
307
|
+
${results.explanation.map(e => `- ${e}`).join('\n')}
|
|
308
|
+
|
|
309
|
+
Consider applying this optimization to improve test performance.`;
|
|
310
|
+
|
|
311
|
+
github.rest.issues.createComment({
|
|
312
|
+
issue_number: context.issue.number,
|
|
313
|
+
owner: context.repo.owner,
|
|
314
|
+
repo: context.repo.repo,
|
|
315
|
+
body: comment
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Best Practices for CI
|
|
321
|
+
|
|
322
|
+
### 1. Gradual Rollout
|
|
323
|
+
- Start with analysis-only mode
|
|
324
|
+
- Monitor results for several weeks
|
|
325
|
+
- Enable enforcement gradually
|
|
326
|
+
|
|
327
|
+
### 2. Performance Baselines
|
|
328
|
+
- Track test suite performance over time
|
|
329
|
+
- Set up alerts for performance regressions
|
|
330
|
+
- Use SpecScout data to identify trends
|
|
331
|
+
|
|
332
|
+
### 3. Team Communication
|
|
333
|
+
- Share SpecScout results in code reviews
|
|
334
|
+
- Document optimization decisions
|
|
335
|
+
- Train team on interpreting results
|
|
336
|
+
|
|
337
|
+
### 4. Maintenance
|
|
338
|
+
- Regularly review CI configuration
|
|
339
|
+
- Update SpecScout version
|
|
340
|
+
- Monitor for false positives
|
|
341
|
+
|
|
342
|
+
## Troubleshooting CI Issues
|
|
343
|
+
|
|
344
|
+
### Common Problems
|
|
345
|
+
|
|
346
|
+
1. **TestProf not working in CI**
|
|
347
|
+
- Ensure database is properly set up
|
|
348
|
+
- Check Rails environment configuration
|
|
349
|
+
- Verify TestProf dependencies
|
|
350
|
+
|
|
351
|
+
2. **SpecScout timing out**
|
|
352
|
+
- Reduce enabled agents
|
|
353
|
+
- Focus on specific spec files
|
|
354
|
+
- Increase CI timeout limits
|
|
355
|
+
|
|
356
|
+
3. **False positives in enforcement**
|
|
357
|
+
- Review agent configuration
|
|
358
|
+
- Consider test-specific context
|
|
359
|
+
- Adjust confidence thresholds
|
|
360
|
+
|
|
361
|
+
### Debug Commands
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
# Test TestProf integration
|
|
365
|
+
bundle exec rspec --profile
|
|
366
|
+
|
|
367
|
+
# Test SpecScout with debug output
|
|
368
|
+
SPEC_SCOUT_DEBUG=1 bundle exec spec_scout
|
|
369
|
+
|
|
370
|
+
# Validate configuration
|
|
371
|
+
bundle exec ruby -e "require 'spec_scout'; puts SpecScout.configuration.to_h"
|
|
372
|
+
```
|
data/exe/spec_scout
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SpecScout
|
|
4
|
+
VALID_CONFIDENCE_LEVELS = %i[high medium low].freeze
|
|
5
|
+
|
|
6
|
+
# Agent output containing recommendation, confidence level, and reasoning
|
|
7
|
+
AgentResult = Struct.new(
|
|
8
|
+
:agent_name, # Symbol: :database, :factory, :intent, :risk
|
|
9
|
+
:verdict, # Symbol: :db_unnecessary, :prefer_build_stubbed, etc.
|
|
10
|
+
:confidence, # Symbol: :high, :medium, :low
|
|
11
|
+
:reasoning, # String: Human-readable explanation
|
|
12
|
+
:metadata, # Hash: Additional agent-specific data
|
|
13
|
+
keyword_init: true
|
|
14
|
+
) do
|
|
15
|
+
def initialize(**args)
|
|
16
|
+
super
|
|
17
|
+
self.agent_name ||= :unknown
|
|
18
|
+
self.verdict ||= :no_verdict
|
|
19
|
+
self.confidence ||= :low
|
|
20
|
+
self.reasoning ||= ''
|
|
21
|
+
self.metadata ||= {}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def valid?
|
|
25
|
+
agent_name.is_a?(Symbol) &&
|
|
26
|
+
verdict.is_a?(Symbol) &&
|
|
27
|
+
VALID_CONFIDENCE_LEVELS.include?(confidence) &&
|
|
28
|
+
reasoning.is_a?(String) &&
|
|
29
|
+
metadata.is_a?(Hash)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def high_confidence?
|
|
33
|
+
confidence == :high
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def medium_confidence?
|
|
37
|
+
confidence == :medium
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def low_confidence?
|
|
41
|
+
confidence == :low
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../base_agent'
|
|
4
|
+
|
|
5
|
+
module SpecScout
|
|
6
|
+
module Agents
|
|
7
|
+
# Agent that analyzes database usage patterns and identifies unnecessary persistence
|
|
8
|
+
class DatabaseAgent < BaseAgent
|
|
9
|
+
# Verdict types for database optimization
|
|
10
|
+
VERDICTS = {
|
|
11
|
+
db_unnecessary: :db_unnecessary,
|
|
12
|
+
db_required: :db_required,
|
|
13
|
+
db_unclear: :db_unclear
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
def evaluate
|
|
17
|
+
return no_database_data_result unless database_operations_present?
|
|
18
|
+
|
|
19
|
+
insert_count = profile_data.db[:inserts] || 0
|
|
20
|
+
select_count = profile_data.db[:selects] || 0
|
|
21
|
+
total_queries = profile_data.db[:total_queries] || 0
|
|
22
|
+
|
|
23
|
+
verdict, confidence, reasoning = analyze_database_usage(
|
|
24
|
+
insert_count: insert_count,
|
|
25
|
+
select_count: select_count,
|
|
26
|
+
total_queries: total_queries
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
create_result(
|
|
30
|
+
verdict: verdict,
|
|
31
|
+
confidence: confidence,
|
|
32
|
+
reasoning: reasoning,
|
|
33
|
+
metadata: {
|
|
34
|
+
insert_count: insert_count,
|
|
35
|
+
select_count: select_count,
|
|
36
|
+
total_queries: total_queries
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def analyze_database_usage(insert_count:, select_count:, total_queries:)
|
|
44
|
+
if no_db_writes_and_minimal_reads?(insert_count, select_count)
|
|
45
|
+
db_unnecessary_minimal_reads_result(select_count)
|
|
46
|
+
elsif no_db_writes_but_some_reads?(insert_count, select_count)
|
|
47
|
+
db_unnecessary_some_reads_result(select_count)
|
|
48
|
+
elsif db_writes_present?(insert_count)
|
|
49
|
+
db_required_result(insert_count)
|
|
50
|
+
else
|
|
51
|
+
db_unclear_result(total_queries)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def no_db_writes_and_minimal_reads?(insert_count, select_count)
|
|
56
|
+
insert_count.zero? && select_count <= 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def no_db_writes_but_some_reads?(insert_count, select_count)
|
|
60
|
+
insert_count.zero? && select_count > 1
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def db_writes_present?(insert_count)
|
|
64
|
+
insert_count.positive?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def db_unnecessary_minimal_reads_result(select_count)
|
|
68
|
+
[
|
|
69
|
+
VERDICTS[:db_unnecessary],
|
|
70
|
+
:high,
|
|
71
|
+
"No database writes detected and minimal reads (#{select_count}). " \
|
|
72
|
+
'Consider using build_stubbed or avoiding database persistence.'
|
|
73
|
+
]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def db_unnecessary_some_reads_result(select_count)
|
|
77
|
+
[
|
|
78
|
+
VERDICTS[:db_unnecessary],
|
|
79
|
+
:medium,
|
|
80
|
+
"No database writes detected but #{select_count} reads. " \
|
|
81
|
+
'Database persistence may be unnecessary.'
|
|
82
|
+
]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def db_required_result(insert_count)
|
|
86
|
+
[
|
|
87
|
+
VERDICTS[:db_required],
|
|
88
|
+
:high,
|
|
89
|
+
"Database writes detected (#{insert_count} inserts). " \
|
|
90
|
+
'Database persistence appears necessary.'
|
|
91
|
+
]
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def db_unclear_result(total_queries)
|
|
95
|
+
[
|
|
96
|
+
VERDICTS[:db_unclear],
|
|
97
|
+
:low,
|
|
98
|
+
"Mixed database usage pattern (#{total_queries} total queries). " \
|
|
99
|
+
'Unable to determine clear optimization opportunity.'
|
|
100
|
+
]
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def no_database_data_result
|
|
104
|
+
create_result(
|
|
105
|
+
verdict: VERDICTS[:db_unclear],
|
|
106
|
+
confidence: :low,
|
|
107
|
+
reasoning: 'No database usage data available for analysis.',
|
|
108
|
+
metadata: { no_data: true }
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|