simplecov-mcp 1.0.1 → 2.0.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 +4 -4
- data/README.md +98 -50
- data/docs/{ARCHITECTURE.md → dev/ARCHITECTURE.md} +11 -10
- data/docs/dev/BRANCH_ONLY_COVERAGE.md +158 -0
- data/docs/{DEVELOPMENT.md → dev/DEVELOPMENT.md} +2 -1
- data/docs/dev/README.md +10 -0
- data/docs/dev/RELEASING.md +146 -0
- data/docs/{arch-decisions → dev/arch-decisions}/001-x-arch-decision.md +3 -1
- data/docs/{arch-decisions → dev/arch-decisions}/002-x-arch-decision.md +7 -5
- data/docs/{arch-decisions → dev/arch-decisions}/003-x-arch-decision.md +2 -0
- data/docs/{arch-decisions → dev/arch-decisions}/004-x-arch-decision.md +6 -2
- data/docs/{arch-decisions → dev/arch-decisions}/005-x-arch-decision.md +4 -2
- data/docs/{arch-decisions → dev/arch-decisions}/README.md +3 -3
- data/docs/{presentations → dev/presentations}/simplecov-mcp-presentation.md +28 -22
- data/docs/fixtures/demo_project/README.md +9 -0
- data/docs/{ADVANCED_USAGE.md → user/ADVANCED_USAGE.md} +129 -319
- data/docs/user/CLI_FALLBACK_FOR_LLMS.md +34 -0
- data/docs/user/CLI_USAGE.md +750 -0
- data/docs/{ERROR_HANDLING.md → user/ERROR_HANDLING.md} +12 -12
- data/docs/user/EXAMPLES.md +588 -0
- data/docs/user/INSTALLATION.md +130 -0
- data/docs/{LIBRARY_API.md → user/LIBRARY_API.md} +90 -32
- data/docs/{MCP_INTEGRATION.md → user/MCP_INTEGRATION.md} +36 -34
- data/docs/user/README.md +14 -0
- data/docs/{TROUBLESHOOTING.md → user/TROUBLESHOOTING.md} +21 -100
- data/docs/user/V2-BREAKING-CHANGES.md +472 -0
- data/exe/simplecov-mcp +1 -1
- data/lib/simplecov_mcp/{cli_config.rb → app_config.rb} +12 -12
- data/lib/simplecov_mcp/app_context.rb +1 -1
- data/lib/simplecov_mcp/base_tool.rb +66 -38
- data/lib/simplecov_mcp/cli.rb +67 -123
- data/lib/simplecov_mcp/commands/base_command.rb +16 -27
- data/lib/simplecov_mcp/commands/command_factory.rb +8 -2
- data/lib/simplecov_mcp/commands/detailed_command.rb +16 -2
- data/lib/simplecov_mcp/commands/list_command.rb +1 -1
- data/lib/simplecov_mcp/commands/raw_command.rb +18 -2
- data/lib/simplecov_mcp/commands/summary_command.rb +20 -3
- data/lib/simplecov_mcp/commands/totals_command.rb +53 -0
- data/lib/simplecov_mcp/commands/uncovered_command.rb +24 -5
- data/lib/simplecov_mcp/commands/validate_command.rb +60 -0
- data/lib/simplecov_mcp/commands/version_command.rb +19 -4
- data/lib/simplecov_mcp/config_parser.rb +32 -0
- data/lib/simplecov_mcp/constants.rb +3 -3
- data/lib/simplecov_mcp/coverage_reporter.rb +31 -0
- data/lib/simplecov_mcp/error_handler.rb +81 -40
- data/lib/simplecov_mcp/error_handler_factory.rb +2 -2
- data/lib/simplecov_mcp/errors.rb +12 -19
- data/lib/simplecov_mcp/formatters/source_formatter.rb +23 -19
- data/lib/simplecov_mcp/formatters.rb +51 -0
- data/lib/simplecov_mcp/mcp_server.rb +9 -7
- data/lib/simplecov_mcp/mode_detector.rb +6 -5
- data/lib/simplecov_mcp/model.rb +122 -88
- data/lib/simplecov_mcp/option_normalizers.rb +39 -18
- data/lib/simplecov_mcp/option_parser_builder.rb +82 -65
- data/lib/simplecov_mcp/option_parsers/env_options_parser.rb +3 -5
- data/lib/simplecov_mcp/option_parsers/error_helper.rb +18 -17
- data/lib/simplecov_mcp/path_relativizer.rb +17 -14
- data/lib/simplecov_mcp/predicate_evaluator.rb +72 -0
- data/lib/simplecov_mcp/presenters/base_coverage_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_detailed_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_raw_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_summary_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/coverage_uncovered_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/project_coverage_presenter.rb +1 -3
- data/lib/simplecov_mcp/presenters/project_totals_presenter.rb +27 -0
- data/lib/simplecov_mcp/resolvers/coverage_line_resolver.rb +14 -18
- data/lib/simplecov_mcp/resolvers/resultset_path_resolver.rb +7 -9
- data/lib/simplecov_mcp/resultset_loader.rb +20 -25
- data/lib/simplecov_mcp/staleness_checker.rb +50 -46
- data/lib/simplecov_mcp/table_formatter.rb +64 -0
- data/lib/simplecov_mcp/tools/all_files_coverage_tool.rb +20 -50
- data/lib/simplecov_mcp/tools/coverage_detailed_tool.rb +13 -7
- data/lib/simplecov_mcp/tools/coverage_raw_tool.rb +12 -7
- data/lib/simplecov_mcp/tools/coverage_summary_tool.rb +13 -8
- data/lib/simplecov_mcp/tools/coverage_table_tool.rb +20 -60
- data/lib/simplecov_mcp/tools/coverage_totals_tool.rb +44 -0
- data/lib/simplecov_mcp/tools/help_tool.rb +38 -66
- data/lib/simplecov_mcp/tools/uncovered_lines_tool.rb +13 -8
- data/lib/simplecov_mcp/tools/validate_tool.rb +72 -0
- data/lib/simplecov_mcp/tools/version_tool.rb +7 -14
- data/lib/simplecov_mcp/util.rb +18 -12
- data/lib/simplecov_mcp/version.rb +1 -1
- data/lib/simplecov_mcp.rb +23 -29
- data/spec/all_files_coverage_tool_spec.rb +4 -3
- data/spec/{cli_config_spec.rb → app_config_spec.rb} +31 -26
- data/spec/base_tool_spec.rb +17 -14
- data/spec/cli/show_default_report_spec.rb +2 -2
- data/spec/cli_enumerated_options_spec.rb +31 -9
- data/spec/cli_error_spec.rb +46 -23
- data/spec/cli_format_spec.rb +123 -0
- data/spec/cli_json_options_spec.rb +50 -0
- data/spec/cli_source_spec.rb +11 -63
- data/spec/cli_spec.rb +82 -97
- data/spec/cli_usage_spec.rb +15 -15
- data/spec/commands/base_command_spec.rb +12 -92
- data/spec/commands/command_factory_spec.rb +7 -3
- data/spec/commands/detailed_command_spec.rb +10 -24
- data/spec/commands/list_command_spec.rb +28 -0
- data/spec/commands/raw_command_spec.rb +43 -20
- data/spec/commands/summary_command_spec.rb +10 -23
- data/spec/commands/totals_command_spec.rb +34 -0
- data/spec/commands/uncovered_command_spec.rb +29 -23
- data/spec/commands/validate_command_spec.rb +213 -0
- data/spec/commands/version_command_spec.rb +38 -0
- data/spec/constants_spec.rb +3 -3
- data/spec/coverage_reporter_spec.rb +102 -0
- data/spec/coverage_table_tool_spec.rb +21 -10
- data/spec/coverage_totals_tool_spec.rb +37 -0
- data/spec/error_handler_spec.rb +120 -4
- data/spec/error_mode_spec.rb +18 -22
- data/spec/errors_edge_cases_spec.rb +101 -28
- data/spec/errors_stale_spec.rb +34 -0
- data/spec/file_based_mcp_tools_spec.rb +6 -6
- data/spec/fixtures/project1/lib/bar.rb +2 -0
- data/spec/fixtures/project1/lib/foo.rb +2 -0
- data/spec/help_tool_spec.rb +2 -18
- data/spec/integration_spec.rb +103 -161
- data/spec/logging_fallback_spec.rb +3 -3
- data/spec/mcp_server_integration_spec.rb +1 -1
- data/spec/mcp_server_spec.rb +70 -53
- data/spec/mode_detector_spec.rb +46 -41
- data/spec/model_error_handling_spec.rb +139 -78
- data/spec/model_staleness_spec.rb +13 -13
- data/spec/option_normalizers_spec.rb +111 -112
- data/spec/option_parsers/env_options_parser_spec.rb +25 -37
- data/spec/option_parsers/error_helper_spec.rb +56 -56
- data/spec/path_relativizer_spec.rb +15 -0
- data/spec/presenters/coverage_detailed_presenter_spec.rb +1 -1
- data/spec/presenters/coverage_summary_presenter_spec.rb +1 -1
- data/spec/presenters/coverage_uncovered_presenter_spec.rb +1 -1
- data/spec/presenters/project_coverage_presenter_spec.rb +9 -8
- data/spec/presenters/project_totals_presenter_spec.rb +144 -0
- data/spec/resolvers/coverage_line_resolver_spec.rb +261 -36
- data/spec/resolvers/resultset_path_resolver_spec.rb +13 -8
- data/spec/shared_examples/file_based_mcp_tools.rb +23 -18
- data/spec/shared_examples/formatted_command_examples.rb +64 -0
- data/spec/simple_cov_mcp_module_spec.rb +24 -3
- data/spec/simplecov_mcp/formatters/source_formatter_spec.rb +267 -0
- data/spec/simplecov_mcp/formatters_spec.rb +76 -0
- data/spec/simplecov_mcp/presenters/base_coverage_presenter_spec.rb +79 -0
- data/spec/simplecov_mcp_model_spec.rb +97 -47
- data/spec/simplecov_mcp_opts_spec.rb +42 -39
- data/spec/spec_helper.rb +27 -92
- data/spec/staleness_checker_spec.rb +10 -9
- data/spec/staleness_more_spec.rb +4 -4
- data/spec/support/cli_helpers.rb +22 -0
- data/spec/support/control_flow_helpers.rb +20 -0
- data/spec/support/fake_mcp.rb +40 -0
- data/spec/support/io_helpers.rb +29 -0
- data/spec/support/mcp_helpers.rb +35 -0
- data/spec/support/mcp_runner.rb +10 -8
- data/spec/support/mocking_helpers.rb +30 -0
- data/spec/table_format_spec.rb +70 -0
- data/spec/tools/validate_tool_spec.rb +132 -0
- data/spec/tools_error_handling_spec.rb +34 -48
- data/spec/util_spec.rb +5 -4
- data/spec/version_spec.rb +7 -7
- data/spec/version_tool_spec.rb +20 -22
- metadata +90 -23
- data/docs/BRANCH_ONLY_COVERAGE.md +0 -81
- data/docs/CLI_USAGE.md +0 -637
- data/docs/EXAMPLES.md +0 -430
- data/docs/INSTALLATION.md +0 -352
- data/spec/cli_success_predicate_spec.rb +0 -141
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Advanced Usage Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Back to main README](../README.md)
|
|
4
|
+
|
|
5
|
+
> Examples use `smcp`, an alias pointed at the demo fixture with partial coverage:
|
|
6
|
+
> `alias smcp='simplecov-mcp --root docs/fixtures/demo_project'`
|
|
7
|
+
> Swap `smcp` with `simplecov-mcp` if you want to target your own project/resultset.
|
|
4
8
|
|
|
5
9
|
## Table of Contents
|
|
6
10
|
|
|
@@ -20,7 +24,7 @@ This guide covers advanced usage patterns, integration strategies, and optimizat
|
|
|
20
24
|
|
|
21
25
|
### MCP Error Handling
|
|
22
26
|
|
|
23
|
-
The MCP server uses structured error responses
|
|
27
|
+
The MCP server uses structured error responses:
|
|
24
28
|
|
|
25
29
|
```json
|
|
26
30
|
{
|
|
@@ -37,54 +41,11 @@ The MCP server uses structured error responses. Understanding the error types he
|
|
|
37
41
|
}
|
|
38
42
|
```
|
|
39
43
|
|
|
40
|
-
**Error Types:**
|
|
41
|
-
- `FileError` - File not found in coverage or filesystem
|
|
42
|
-
- `FileNotFoundError` - Source file missing from filesystem
|
|
43
|
-
- `CoverageDataError` - Invalid or corrupt `.resultset.json`
|
|
44
|
-
- `CoverageDataStaleError` - Coverage older than source (single file)
|
|
45
|
-
- `CoverageDataProjectStaleError` - Project-wide staleness issues
|
|
46
|
-
|
|
47
44
|
### MCP Server Logging
|
|
48
45
|
|
|
49
|
-
The MCP server logs to `simplecov_mcp.log` in the current directory by default.
|
|
50
|
-
|
|
51
|
-
**Claude Code (`claude_desktop_config.json`):**
|
|
52
|
-
```json
|
|
53
|
-
{
|
|
54
|
-
"mcpServers": {
|
|
55
|
-
"simplecov-mcp": {
|
|
56
|
-
"command": "simplecov-mcp",
|
|
57
|
-
"args": ["--log-file", "/var/log/coverage/mcp.log"]
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
**Or use environment variables:**
|
|
64
|
-
```json
|
|
65
|
-
{
|
|
66
|
-
"mcpServers": {
|
|
67
|
-
"simplecov-mcp": {
|
|
68
|
-
"command": "simplecov-mcp",
|
|
69
|
-
"env": {
|
|
70
|
-
"SIMPLECOV_MCP_OPTS": "--log-file /var/log/coverage/mcp.log"
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
```
|
|
46
|
+
The MCP server logs to `simplecov_mcp.log` in the current directory by default.
|
|
76
47
|
|
|
77
|
-
|
|
78
|
-
```json
|
|
79
|
-
{
|
|
80
|
-
"mcpServers": {
|
|
81
|
-
"simplecov-mcp": {
|
|
82
|
-
"command": "simplecov-mcp",
|
|
83
|
-
"args": ["--log-file", "stderr"]
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
48
|
+
To override the default log file location, specify the `--log-file` argument wherever and however you configure your MCP server. For example, to log to a different file path, include `--log-file /path/to/logfile.log` in your server configuration. To log to standard error, use `--log-file stderr`.
|
|
88
49
|
|
|
89
50
|
**Note:** Logging to `stdout` is not permitted in MCP mode.
|
|
90
51
|
|
|
@@ -94,16 +55,16 @@ Use JSON-RPC over stdin to test the MCP server:
|
|
|
94
55
|
|
|
95
56
|
```sh
|
|
96
57
|
# Get version
|
|
97
|
-
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' |
|
|
58
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"version_tool","arguments":{}}}' | smcp
|
|
98
59
|
|
|
99
60
|
# Get file summary
|
|
100
|
-
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"
|
|
61
|
+
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"coverage_summary_tool","arguments":{"path":"app/models/order.rb"}}}' | smcp
|
|
101
62
|
|
|
102
63
|
# List all files with sorting
|
|
103
|
-
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"all_files_coverage_tool","arguments":{"sort_order":"ascending"}}}' |
|
|
64
|
+
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"all_files_coverage_tool","arguments":{"sort_order":"ascending"}}}' | smcp
|
|
104
65
|
|
|
105
66
|
# Get uncovered lines
|
|
106
|
-
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"uncovered_lines_tool","arguments":{"path":"
|
|
67
|
+
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"uncovered_lines_tool","arguments":{"path":"app/controllers/orders_controller.rb"}}}' | smcp
|
|
107
68
|
```
|
|
108
69
|
|
|
109
70
|
---
|
|
@@ -133,11 +94,8 @@ A file is considered stale when any of the following are true:
|
|
|
133
94
|
|
|
134
95
|
**CLI Usage:**
|
|
135
96
|
```sh
|
|
136
|
-
# Fail if any file is stale
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# Check specific file staleness
|
|
140
|
-
simplecov-mcp summary lib/model.rb --stale error
|
|
97
|
+
# Fail if any file is stale (option before subcommand)
|
|
98
|
+
smcp --staleness error summary app/models/order.rb
|
|
141
99
|
```
|
|
142
100
|
|
|
143
101
|
**Ruby API:**
|
|
@@ -147,7 +105,7 @@ model = SimpleCovMcp::CoverageModel.new(
|
|
|
147
105
|
)
|
|
148
106
|
|
|
149
107
|
begin
|
|
150
|
-
summary = model.summary_for('
|
|
108
|
+
summary = model.summary_for('app/models/order.rb')
|
|
151
109
|
rescue SimpleCovMcp::CoverageDataStaleError => e
|
|
152
110
|
puts "File modified after coverage: #{e.file_path}"
|
|
153
111
|
puts "Coverage timestamp: #{e.cov_timestamp}"
|
|
@@ -168,19 +126,19 @@ Detects system-wide staleness issues:
|
|
|
168
126
|
**CLI Usage:**
|
|
169
127
|
```sh
|
|
170
128
|
# Track specific patterns
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
129
|
+
smcp --staleness error \
|
|
130
|
+
-g "lib/payments/**/*.rb" \
|
|
131
|
+
-g "lib/ops/jobs/**/*.rb" # -g = --tracked-globs
|
|
174
132
|
|
|
175
133
|
# Combine with JSON output for parsing
|
|
176
|
-
|
|
134
|
+
smcp --staleness error -fJ list > stale-check.json
|
|
177
135
|
```
|
|
178
136
|
|
|
179
137
|
**Ruby API:**
|
|
180
138
|
```ruby
|
|
181
139
|
model = SimpleCovMcp::CoverageModel.new(
|
|
182
140
|
staleness: 'error',
|
|
183
|
-
tracked_globs: ['lib/**/*.rb', '
|
|
141
|
+
tracked_globs: ['lib/payments/**/*.rb', 'lib/ops/jobs/**/*.rb']
|
|
184
142
|
)
|
|
185
143
|
|
|
186
144
|
begin
|
|
@@ -194,51 +152,37 @@ end
|
|
|
194
152
|
|
|
195
153
|
### Staleness in CI/CD
|
|
196
154
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
```
|
|
155
|
+
Staleness checking is particularly useful in CI/CD pipelines to ensure coverage data is fresh:
|
|
156
|
+
|
|
157
|
+
```sh
|
|
158
|
+
# Run tests to generate coverage
|
|
159
|
+
bundle exec rspec
|
|
160
|
+
|
|
161
|
+
# Validate coverage freshness (fails with exit code 1 if stale)
|
|
162
|
+
smcp --staleness error -g "lib/**/*.rb"
|
|
207
163
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
coverage:validate:
|
|
211
|
-
script:
|
|
212
|
-
- bundle exec rspec
|
|
213
|
-
- simplecov-mcp list --stale error --json > coverage.json
|
|
214
|
-
artifacts:
|
|
215
|
-
reports:
|
|
216
|
-
coverage_report:
|
|
217
|
-
coverage_format: cobertura
|
|
218
|
-
path: coverage.json
|
|
164
|
+
# Export validated data for CI artifacts
|
|
165
|
+
smcp -fJ list > coverage.json
|
|
219
166
|
```
|
|
220
167
|
|
|
168
|
+
The `--staleness error` flag causes the command to exit with a non-zero status when coverage is outdated, making it suitable for pipeline failure conditions.
|
|
169
|
+
|
|
221
170
|
---
|
|
222
171
|
|
|
223
172
|
## Advanced Path Resolution
|
|
224
173
|
|
|
225
174
|
### Multi-Strategy Path Matching
|
|
226
175
|
|
|
227
|
-
|
|
176
|
+
Path resolution order:
|
|
228
177
|
|
|
229
178
|
1. **Exact absolute path match**
|
|
230
179
|
2. **Relative path resolution from root**
|
|
231
|
-
3. **Basename (filename) fallback**
|
|
232
|
-
|
|
233
|
-
This allows flexible path specifications:
|
|
234
180
|
|
|
235
181
|
```ruby
|
|
236
182
|
model = SimpleCovMcp::CoverageModel.new(root: '/project')
|
|
237
183
|
|
|
238
|
-
#
|
|
239
|
-
model.summary_for('/
|
|
240
|
-
model.summary_for('lib/model.rb') # Relative
|
|
241
|
-
model.summary_for('model.rb') # Basename only
|
|
184
|
+
model.summary_for('/project/app/models/order.rb') # Absolute
|
|
185
|
+
model.summary_for('app/models/order.rb') # Relative
|
|
242
186
|
```
|
|
243
187
|
|
|
244
188
|
### Working with Multiple Projects
|
|
@@ -270,35 +214,24 @@ coverage_b = model_b.all_files
|
|
|
270
214
|
|
|
271
215
|
### Context-Aware Error Handling
|
|
272
216
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
**CLI Mode:**
|
|
276
|
-
- User-friendly messages
|
|
277
|
-
- Exit codes (0 = success, 1 = error)
|
|
278
|
-
- Optional debug mode
|
|
217
|
+
**CLI Mode:** user-facing messages, exit codes, optional debug mode
|
|
279
218
|
|
|
280
|
-
**Library Mode:**
|
|
281
|
-
- Raises typed exceptions
|
|
282
|
-
- Programmatic error handling
|
|
283
|
-
- Full exception details
|
|
219
|
+
**Library Mode:** typed exceptions with full details
|
|
284
220
|
|
|
285
|
-
**MCP Server Mode:**
|
|
286
|
-
- JSON-RPC error responses
|
|
287
|
-
- Logging to file
|
|
288
|
-
- Structured error data
|
|
221
|
+
**MCP Server Mode:** JSON-RPC errors logged to file with structured data
|
|
289
222
|
|
|
290
223
|
### Error Modes
|
|
291
224
|
|
|
292
225
|
**CLI Error Modes:**
|
|
293
226
|
```sh
|
|
294
227
|
# Silent mode - minimal output
|
|
295
|
-
|
|
228
|
+
smcp --error-mode off summary app/models/order.rb
|
|
296
229
|
|
|
297
230
|
# Standard mode - user-friendly errors (default)
|
|
298
|
-
|
|
231
|
+
smcp --error-mode log summary app/models/order.rb
|
|
299
232
|
|
|
300
233
|
# Verbose mode - full stack traces
|
|
301
|
-
|
|
234
|
+
smcp --error-mode debug summary app/models/order.rb
|
|
302
235
|
```
|
|
303
236
|
|
|
304
237
|
**Ruby API Error Handling:**
|
|
@@ -321,7 +254,7 @@ end
|
|
|
321
254
|
|
|
322
255
|
### Custom Error Handlers
|
|
323
256
|
|
|
324
|
-
|
|
257
|
+
Provide custom error handlers when embedding the CLI:
|
|
325
258
|
|
|
326
259
|
```ruby
|
|
327
260
|
class CustomErrorHandler
|
|
@@ -334,9 +267,7 @@ class CustomErrorHandler
|
|
|
334
267
|
end
|
|
335
268
|
end
|
|
336
269
|
|
|
337
|
-
cli = SimpleCovMcp::CoverageCLI.new(
|
|
338
|
-
error_handler: CustomErrorHandler.new
|
|
339
|
-
)
|
|
270
|
+
cli = SimpleCovMcp::CoverageCLI.new(error_handler: CustomErrorHandler.new)
|
|
340
271
|
```
|
|
341
272
|
|
|
342
273
|
---
|
|
@@ -345,7 +276,7 @@ cli = SimpleCovMcp::CoverageCLI.new(
|
|
|
345
276
|
|
|
346
277
|
### Building Custom Coverage Policies
|
|
347
278
|
|
|
348
|
-
Use
|
|
279
|
+
Use the `validate` subcommand to enforce custom coverage policies in CI/CD. Example predicates are in [`examples/success_predicates/`](../../examples/success_predicates/).
|
|
349
280
|
|
|
350
281
|
> **⚠️ SECURITY WARNING**
|
|
351
282
|
>
|
|
@@ -364,13 +295,16 @@ Use `--success-predicate` to enforce custom coverage policies in CI/CD. Example
|
|
|
364
295
|
**Quick Usage:**
|
|
365
296
|
```sh
|
|
366
297
|
# All files must be >= 80%
|
|
367
|
-
|
|
298
|
+
smcp validate examples/success_predicates/all_files_above_threshold_predicate.rb
|
|
368
299
|
|
|
369
300
|
# Total project coverage >= 85%
|
|
370
|
-
|
|
301
|
+
smcp validate examples/success_predicates/project_coverage_minimum_predicate.rb
|
|
302
|
+
|
|
303
|
+
# Custom predicate from file
|
|
304
|
+
smcp validate coverage_policy.rb
|
|
371
305
|
|
|
372
|
-
#
|
|
373
|
-
|
|
306
|
+
# Inline string mode
|
|
307
|
+
smcp validate -i '->(m) { m.all_files.all? { |f| f["percentage"] >= 80 } }'
|
|
374
308
|
```
|
|
375
309
|
|
|
376
310
|
**Creating a predicate:**
|
|
@@ -383,6 +317,7 @@ end
|
|
|
383
317
|
```
|
|
384
318
|
|
|
385
319
|
**Advanced predicate with reporting:**
|
|
320
|
+
|
|
386
321
|
```ruby
|
|
387
322
|
# coverage_policy.rb
|
|
388
323
|
class CoveragePolicy
|
|
@@ -419,216 +354,64 @@ Convert absolute paths to relative for cleaner output:
|
|
|
419
354
|
model = SimpleCovMcp::CoverageModel.new(root: '/project')
|
|
420
355
|
|
|
421
356
|
# Get data with absolute paths
|
|
422
|
-
data = model.summary_for('
|
|
423
|
-
# => { 'file' => '/project/
|
|
357
|
+
data = model.summary_for('app/models/order.rb')
|
|
358
|
+
# => { 'file' => '/project/app/models/order.rb', ... }
|
|
424
359
|
|
|
425
360
|
# Relativize paths
|
|
426
361
|
relative_data = model.relativize(data)
|
|
427
|
-
# => { 'file' => '
|
|
362
|
+
# => { 'file' => 'app/models/order.rb', ... }
|
|
428
363
|
|
|
429
364
|
# Works with arrays too
|
|
430
365
|
files = model.all_files
|
|
431
366
|
relative_files = model.relativize(files)
|
|
432
367
|
```
|
|
433
368
|
|
|
434
|
-
### Batch Operations
|
|
435
|
-
|
|
436
|
-
```ruby
|
|
437
|
-
# Process multiple files efficiently
|
|
438
|
-
files_to_check = ['lib/model.rb', 'lib/controller.rb', 'lib/view.rb']
|
|
439
|
-
|
|
440
|
-
model = SimpleCovMcp::CoverageModel.new
|
|
441
|
-
|
|
442
|
-
results = files_to_check.map do |file|
|
|
443
|
-
begin
|
|
444
|
-
{
|
|
445
|
-
file: file,
|
|
446
|
-
summary: model.summary_for(file),
|
|
447
|
-
uncovered: model.uncovered_for(file)
|
|
448
|
-
}
|
|
449
|
-
rescue SimpleCovMcp::FileError => e
|
|
450
|
-
{ file: file, error: e.message }
|
|
451
|
-
end
|
|
452
|
-
end
|
|
453
|
-
```
|
|
454
|
-
|
|
455
369
|
---
|
|
456
370
|
|
|
457
|
-
## CI/CD Integration
|
|
458
|
-
|
|
459
|
-
### GitHub Actions
|
|
460
|
-
|
|
461
|
-
**Complete Workflow:**
|
|
462
|
-
```yaml
|
|
463
|
-
name: Coverage Analysis
|
|
464
|
-
|
|
465
|
-
on: [push, pull_request]
|
|
466
|
-
|
|
467
|
-
jobs:
|
|
468
|
-
coverage:
|
|
469
|
-
runs-on: ubuntu-latest
|
|
470
|
-
steps:
|
|
471
|
-
- uses: actions/checkout@v3
|
|
472
|
-
|
|
473
|
-
- name: Set up Ruby
|
|
474
|
-
uses: ruby/setup-ruby@v1
|
|
475
|
-
with:
|
|
476
|
-
ruby-version: 3.2
|
|
477
|
-
bundler-cache: true
|
|
478
|
-
|
|
479
|
-
- name: Run tests with coverage
|
|
480
|
-
run: bundle exec rspec
|
|
481
|
-
|
|
482
|
-
- name: Install simplecov-mcp
|
|
483
|
-
run: gem install simplecov-mcp
|
|
484
|
-
|
|
485
|
-
- name: Validate coverage freshness
|
|
486
|
-
run: |
|
|
487
|
-
simplecov-mcp --stale error \
|
|
488
|
-
--tracked-globs "lib/**/*.rb" \
|
|
489
|
-
--tracked-globs "app/**/*.rb"
|
|
490
|
-
|
|
491
|
-
- name: Check minimum coverage
|
|
492
|
-
run: |
|
|
493
|
-
# Export coverage data
|
|
494
|
-
simplecov-mcp list --json > coverage.json
|
|
495
|
-
|
|
496
|
-
# Use jq to check minimum threshold
|
|
497
|
-
MIN_COVERAGE=$(jq '[.files[].percentage] | add / length' coverage.json)
|
|
498
|
-
if (( $(echo "$MIN_COVERAGE < 80" | bc -l) )); then
|
|
499
|
-
echo "Coverage below 80%: $MIN_COVERAGE%"
|
|
500
|
-
exit 1
|
|
501
|
-
fi
|
|
502
|
-
|
|
503
|
-
- name: Upload coverage report
|
|
504
|
-
uses: actions/upload-artifact@v3
|
|
505
|
-
with:
|
|
506
|
-
name: coverage-report
|
|
507
|
-
path: coverage.json
|
|
508
|
-
|
|
509
|
-
- name: Comment PR with coverage
|
|
510
|
-
if: github.event_name == 'pull_request'
|
|
511
|
-
run: |
|
|
512
|
-
COVERAGE=$(simplecov-mcp list)
|
|
513
|
-
gh pr comment ${{ github.event.pull_request.number }} \
|
|
514
|
-
--body "## Coverage Report\n\`\`\`\n$COVERAGE\n\`\`\`"
|
|
515
|
-
env:
|
|
516
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
517
|
-
```
|
|
518
|
-
|
|
519
|
-
### GitLab CI
|
|
520
|
-
|
|
521
|
-
```yaml
|
|
522
|
-
coverage:
|
|
523
|
-
stage: test
|
|
524
|
-
script:
|
|
525
|
-
- bundle exec rspec
|
|
526
|
-
- gem install simplecov-mcp
|
|
527
|
-
- simplecov-mcp --stale error
|
|
528
|
-
artifacts:
|
|
529
|
-
reports:
|
|
530
|
-
coverage_report:
|
|
531
|
-
coverage_format: cobertura
|
|
532
|
-
path: coverage/coverage.xml
|
|
533
|
-
paths:
|
|
534
|
-
- coverage/
|
|
535
|
-
coverage: '/TOTAL.*\s(\d+\.\d+)%/'
|
|
536
|
-
```
|
|
537
|
-
|
|
538
|
-
### Jenkins Pipeline
|
|
539
|
-
|
|
540
|
-
```groovy
|
|
541
|
-
pipeline {
|
|
542
|
-
agent any
|
|
543
|
-
|
|
544
|
-
stages {
|
|
545
|
-
stage('Test') {
|
|
546
|
-
steps {
|
|
547
|
-
sh 'bundle exec rspec'
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
stage('Coverage Analysis') {
|
|
552
|
-
steps {
|
|
553
|
-
sh 'gem install simplecov-mcp'
|
|
554
|
-
sh '''
|
|
555
|
-
simplecov-mcp list --json > coverage.json
|
|
556
|
-
simplecov-mcp --stale error || exit 1
|
|
557
|
-
'''
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
stage('Coverage Report') {
|
|
562
|
-
steps {
|
|
563
|
-
publishHTML([
|
|
564
|
-
reportDir: 'coverage',
|
|
565
|
-
reportFiles: 'index.html',
|
|
566
|
-
reportName: 'Coverage Report'
|
|
567
|
-
])
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
```
|
|
371
|
+
## CI/CD Integration
|
|
573
372
|
|
|
574
|
-
|
|
373
|
+
The CLI is designed for CI/CD use with features that integrate naturally into pipeline workflows:
|
|
575
374
|
|
|
576
|
-
|
|
577
|
-
#!/bin/bash
|
|
578
|
-
# .git/hooks/pre-commit
|
|
375
|
+
### Key Integration Features
|
|
579
376
|
|
|
580
|
-
|
|
581
|
-
|
|
377
|
+
- **Exit codes**: Non-zero on failure, making it suitable for pipeline failure conditions
|
|
378
|
+
- **JSON output**: `-fJ` format for parsing by CI tools and custom processing
|
|
379
|
+
- **Staleness checking**: `--stale error` to fail on outdated coverage data
|
|
380
|
+
- **Success predicates**: Custom Ruby policies for coverage enforcement
|
|
582
381
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
}
|
|
382
|
+
### Basic CI Pattern
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
# 1. Run tests to generate coverage
|
|
386
|
+
bundle exec rspec
|
|
589
387
|
|
|
590
|
-
#
|
|
591
|
-
|
|
592
|
-
jq -r '.files[] | select(.percentage < 80) | .file' | \
|
|
593
|
-
head -5)
|
|
388
|
+
# 2. Validate coverage freshness (fails with exit code 1 if stale)
|
|
389
|
+
smcp --staleness error -g "lib/**/*.rb"
|
|
594
390
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
echo "$LOW_COVERAGE"
|
|
598
|
-
fi
|
|
391
|
+
# 3. Export data for CI artifacts or further processing
|
|
392
|
+
smcp -fJ list > coverage.json
|
|
599
393
|
```
|
|
600
394
|
|
|
601
|
-
### Using
|
|
395
|
+
### Using Coverage Validation
|
|
602
396
|
|
|
603
|
-
|
|
397
|
+
Enforce custom coverage policies with the `validate` subcommand:
|
|
604
398
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
run: |
|
|
609
|
-
bundle exec rspec
|
|
610
|
-
bundle exec simplecov-mcp --success-predicate coverage_policy.rb
|
|
611
|
-
```
|
|
399
|
+
```bash
|
|
400
|
+
# Run tests
|
|
401
|
+
bundle exec rspec
|
|
612
402
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
coverage:enforce:
|
|
616
|
-
script:
|
|
617
|
-
- bundle exec rspec
|
|
618
|
-
- bundle exec simplecov-mcp --success-predicate coverage_policy.rb
|
|
403
|
+
# Apply coverage policy (fails with exit code 1 if predicate returns false)
|
|
404
|
+
smcp validate coverage_policy.rb
|
|
619
405
|
```
|
|
620
406
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
```
|
|
407
|
+
Exit codes:
|
|
408
|
+
- `0` - Success (coverage meets requirements)
|
|
409
|
+
- `1` - Failure (coverage policy not met or stale data detected)
|
|
410
|
+
- `2` - Error (invalid predicate or system error)
|
|
411
|
+
|
|
412
|
+
### Platform-Specific Examples
|
|
630
413
|
|
|
631
|
-
|
|
414
|
+
For platform-specific integration examples (GitHub Actions, GitLab CI, Jenkins, CircleCI, etc.), see community contributions in the [GitHub Discussions](https://github.com/simplecov-ruby/simplecov-mcp/discussions).
|
|
632
415
|
|
|
633
416
|
---
|
|
634
417
|
|
|
@@ -649,10 +432,20 @@ Uses Ruby's `File.fnmatch` with extended glob support:
|
|
|
649
432
|
--tracked-globs "lib/**/*.rb"
|
|
650
433
|
|
|
651
434
|
# Multiple patterns
|
|
652
|
-
--tracked-globs "lib/**/*.rb" --tracked-globs "
|
|
435
|
+
--tracked-globs "lib/payments/**/*.rb" --tracked-globs "lib/ops/jobs/**/*.rb"
|
|
653
436
|
|
|
654
437
|
# Exclude patterns (use CLI filtering)
|
|
655
|
-
|
|
438
|
+
smcp -fJ list | jq '.files[] | select(.file | test("spec") | not)'
|
|
439
|
+
|
|
440
|
+
# Ruby alternative:
|
|
441
|
+
smcp -fJ list | ruby -r json -e '
|
|
442
|
+
JSON.parse($stdin.read)["files"].reject { |f| f["file"].include?("spec") }.each do |f|
|
|
443
|
+
puts JSON.pretty_generate(f)
|
|
444
|
+
end
|
|
445
|
+
'
|
|
446
|
+
|
|
447
|
+
# Rexe alternative:
|
|
448
|
+
smcp -fJ list | rexe -ij -mb -oJ 'self["files"].reject { |f| f["file"].include?("spec") }'
|
|
656
449
|
|
|
657
450
|
# Complex patterns
|
|
658
451
|
--tracked-globs "lib/{models,controllers}/**/*.rb"
|
|
@@ -664,26 +457,23 @@ simplecov-mcp list --json | jq '.files[] | select(.file | test("spec") | not)'
|
|
|
664
457
|
**1. Monitor Subsystem Coverage:**
|
|
665
458
|
```sh
|
|
666
459
|
# API layer only
|
|
667
|
-
|
|
460
|
+
smcp -g "lib/api/**/*.rb" list
|
|
668
461
|
|
|
669
462
|
# Core business logic
|
|
670
|
-
|
|
463
|
+
smcp -g "lib/domain/**/*.rb" list
|
|
671
464
|
```
|
|
672
465
|
|
|
673
466
|
**2. Ensure New Files Have Coverage:**
|
|
674
467
|
```sh
|
|
675
468
|
# Fail if any tracked file lacks coverage
|
|
676
|
-
|
|
677
|
-
--tracked-globs "lib/features/**/*.rb"
|
|
469
|
+
smcp --staleness error -g "lib/features/**/*.rb"
|
|
678
470
|
```
|
|
679
471
|
|
|
680
472
|
**3. Multi-tier Reporting:**
|
|
681
473
|
```sh
|
|
682
474
|
# Generate separate reports per layer
|
|
683
475
|
for layer in models views controllers; do
|
|
684
|
-
|
|
685
|
-
--tracked-globs "app/${layer}/**/*.rb" \
|
|
686
|
-
--json > "coverage-${layer}.json"
|
|
476
|
+
smcp -g "app/${layer}/**/*.rb" -fJ list > "coverage-${layer}.json"
|
|
687
477
|
done
|
|
688
478
|
```
|
|
689
479
|
|
|
@@ -868,12 +658,12 @@ The CLI supports annotated source viewing:
|
|
|
868
658
|
|
|
869
659
|
```sh
|
|
870
660
|
# Show uncovered lines with context
|
|
871
|
-
|
|
661
|
+
smcp uncovered app/models/order.rb \
|
|
872
662
|
--source uncovered \
|
|
873
663
|
--source-context 3
|
|
874
664
|
|
|
875
665
|
# Show full file with coverage annotations
|
|
876
|
-
|
|
666
|
+
smcp uncovered app/models/order.rb \
|
|
877
667
|
--source full \
|
|
878
668
|
--source-context 0
|
|
879
669
|
```
|
|
@@ -903,7 +693,7 @@ def annotate_source(file_path)
|
|
|
903
693
|
output.join
|
|
904
694
|
end
|
|
905
695
|
|
|
906
|
-
puts annotate_source('
|
|
696
|
+
puts annotate_source('app/models/order.rb')
|
|
907
697
|
```
|
|
908
698
|
|
|
909
699
|
### Integration with Coverage Trackers
|
|
@@ -912,7 +702,7 @@ puts annotate_source('lib/model.rb')
|
|
|
912
702
|
```sh
|
|
913
703
|
#!/bin/bash
|
|
914
704
|
bundle exec rspec
|
|
915
|
-
|
|
705
|
+
smcp -fJ list > coverage.json
|
|
916
706
|
|
|
917
707
|
# Transform to Codecov format (example)
|
|
918
708
|
jq '{
|
|
@@ -925,6 +715,30 @@ jq '{
|
|
|
925
715
|
}' coverage.json | curl -X POST \
|
|
926
716
|
-H "Authorization: token $CODECOV_TOKEN" \
|
|
927
717
|
-d @- https://codecov.io/upload
|
|
718
|
+
|
|
719
|
+
# Ruby alternative:
|
|
720
|
+
ruby -r json -e '
|
|
721
|
+
data = JSON.parse(File.read("coverage.json"))
|
|
722
|
+
transformed = {
|
|
723
|
+
coverage: data["files"].map { |f|
|
|
724
|
+
{name: f["file"], coverage: f["percentage"]}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
puts JSON.pretty_generate(transformed)
|
|
728
|
+
' | curl -X POST \
|
|
729
|
+
-H "Authorization: token $CODECOV_TOKEN" \
|
|
730
|
+
-d @- https://codecov.io/upload
|
|
731
|
+
|
|
732
|
+
# Rexe alternative:
|
|
733
|
+
rexe -f coverage.json -oJ '
|
|
734
|
+
{
|
|
735
|
+
coverage: self["files"].map { |f|
|
|
736
|
+
{name: f["file"], coverage: f["percentage"]}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
' | curl -X POST \
|
|
740
|
+
-H "Authorization: token $CODECOV_TOKEN" \
|
|
741
|
+
-d @- https://codecov.io/upload
|
|
928
742
|
```
|
|
929
743
|
|
|
930
744
|
**Send to Coveralls:**
|
|
@@ -961,7 +775,3 @@ Net::HTTP.post(uri, coveralls_data.to_json, {
|
|
|
961
775
|
- [MCP Integration Guide](MCP_INTEGRATION.md)
|
|
962
776
|
- [Error Handling Details](ERROR_HANDLING.md)
|
|
963
777
|
- [Troubleshooting](TROUBLESHOOTING.md)
|
|
964
|
-
|
|
965
|
-
---
|
|
966
|
-
|
|
967
|
-
**Made with ❤️ for sophisticated Ruby test coverage analysis**
|