deprisker 0.1.0__tar.gz
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.
- deprisker-0.1.0/.gitignore +15 -0
- deprisker-0.1.0/PKG-INFO +297 -0
- deprisker-0.1.0/README.md +270 -0
- deprisker-0.1.0/deprisker/__init__.py +5 -0
- deprisker-0.1.0/deprisker/analyzer.py +433 -0
- deprisker-0.1.0/deprisker/cli.py +170 -0
- deprisker-0.1.0/deprisker/config.py +41 -0
- deprisker-0.1.0/deprisker/exceptions.py +17 -0
- deprisker-0.1.0/deprisker/mcp_server.py +216 -0
- deprisker-0.1.0/deprisker/parsers.py +174 -0
- deprisker-0.1.0/deprisker/reporter.py +262 -0
- deprisker-0.1.0/deprisker/scorer.py +73 -0
- deprisker-0.1.0/deprisker-PRD.md +1672 -0
- deprisker-0.1.0/pyproject.toml +47 -0
- deprisker-0.1.0/tests/fixtures/go_project/auth/middleware.go +3 -0
- deprisker-0.1.0/tests/fixtures/go_project/go.mod +3 -0
- deprisker-0.1.0/tests/fixtures/go_project/main.go +8 -0
- deprisker-0.1.0/tests/fixtures/go_project/utils/logger.go +5 -0
- deprisker-0.1.0/tests/fixtures/java_project/com/example/app/Main.java +8 -0
- deprisker-0.1.0/tests/fixtures/java_project/com/example/app/auth/Middleware.java +5 -0
- deprisker-0.1.0/tests/fixtures/java_project/com/example/app/utils/Logger.java +3 -0
- deprisker-0.1.0/tests/fixtures/js_project/components/Button.jsx +1 -0
- deprisker-0.1.0/tests/fixtures/js_project/index.js +2 -0
- deprisker-0.1.0/tests/fixtures/js_project/utils/api.ts +1 -0
- deprisker-0.1.0/tests/fixtures/mixed_project/app.py +1 -0
- deprisker-0.1.0/tests/fixtures/mixed_project/helpers.js +1 -0
- deprisker-0.1.0/tests/fixtures/mixed_project/index.js +1 -0
- deprisker-0.1.0/tests/fixtures/mixed_project/utils.py +1 -0
- deprisker-0.1.0/tests/fixtures/python_project/auth/__init__.py +0 -0
- deprisker-0.1.0/tests/fixtures/python_project/auth/middleware.py +2 -0
- deprisker-0.1.0/tests/fixtures/python_project/auth/tokens.py +1 -0
- deprisker-0.1.0/tests/fixtures/python_project/main.py +3 -0
- deprisker-0.1.0/tests/fixtures/python_project/utils/__init__.py +0 -0
- deprisker-0.1.0/tests/fixtures/python_project/utils/logger.py +1 -0
- deprisker-0.1.0/tests/fixtures/ruby_project/auth/middleware.rb +1 -0
- deprisker-0.1.0/tests/fixtures/ruby_project/main.rb +2 -0
- deprisker-0.1.0/tests/fixtures/ruby_project/utils/logger.rb +1 -0
- deprisker-0.1.0/tests/fixtures/rust_project/Cargo.toml +4 -0
- deprisker-0.1.0/tests/fixtures/rust_project/src/auth/middleware.rs +2 -0
- deprisker-0.1.0/tests/fixtures/rust_project/src/auth/mod.rs +2 -0
- deprisker-0.1.0/tests/fixtures/rust_project/src/main.rs +5 -0
- deprisker-0.1.0/tests/fixtures/rust_project/src/utils.rs +2 -0
- deprisker-0.1.0/tests/test_analyzer.py +69 -0
- deprisker-0.1.0/tests/test_cli.py +55 -0
- deprisker-0.1.0/tests/test_config.py +31 -0
- deprisker-0.1.0/tests/test_mcp.py +84 -0
- deprisker-0.1.0/tests/test_parsers.py +162 -0
- deprisker-0.1.0/tests/test_reporter.py +53 -0
- deprisker-0.1.0/tests/test_scorer.py +70 -0
deprisker-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deprisker
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Find which files will hurt the most when they break — dependency risk analysis for any codebase.
|
|
5
|
+
Project-URL: Homepage, https://github.com/pratik-sonigra/deprisker
|
|
6
|
+
Project-URL: Repository, https://github.com/pratik-sonigra/deprisker
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/pratik-sonigra/deprisker/issues
|
|
8
|
+
Author-email: Pratik Sonigra <pratik.s@dashtechinc.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: code-quality,dependency,devtools,graph,mcp,refactoring,risk,static-analysis
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: click>=8.0
|
|
24
|
+
Requires-Dist: fastmcp>=2.0
|
|
25
|
+
Requires-Dist: networkx>=3.0
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# deprisker
|
|
29
|
+
|
|
30
|
+
**Find which files will hurt the most when they break.**
|
|
31
|
+
|
|
32
|
+
`deprisker` builds a directed dependency graph from your codebase and scores every module by its blast radius — how many other modules would break if it did. It surfaces this as a terminal report, a self-contained interactive HTML visualization, and a structured JSON output for CI pipelines and AI agents.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Why this exists
|
|
37
|
+
|
|
38
|
+
Every codebase has files that, if incorrectly modified, cascade failures across a disproportionate number of other modules. These high-risk files are not obvious from reading the code. A large file is not necessarily risky. A heavily tested file is not necessarily safe. What actually determines blast radius is **structural position in the dependency graph** — how many other modules depend on it, whether it bridges otherwise disconnected parts of the system, and whether it participates in circular dependency chains.
|
|
39
|
+
|
|
40
|
+
`deprisker` answers the question _"which file should I be most careful editing?"_ before a refactor, release, or code review — in under 10 seconds, with no configuration required.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
- **Zero configuration** — point at a directory, get results
|
|
47
|
+
- **Multi-language** — Python, JavaScript/TypeScript, Go, Rust, Ruby, and Java
|
|
48
|
+
- **Graph-theoretic scoring** — risk is computed from in-degree, betweenness centrality, lines of code, and cycle participation; not heuristics
|
|
49
|
+
- **Interactive HTML report** — force-directed dependency graph, bar chart of top risks, sortable table; all in a single self-contained file with no server required
|
|
50
|
+
- **CI-ready** — `--fail-on-high` and `--fail-on <score>` flags for pipeline integration
|
|
51
|
+
- **MCP server** — expose analysis as queryable tools for Claude and other AI agents
|
|
52
|
+
- **Structured JSON** — `--json` flag for agent pipelines and custom tooling
|
|
53
|
+
- **No LLM required** — purely deterministic static analysis
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install deprisker
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Requires Python 3.9+.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Quick start
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Analyze the current directory
|
|
71
|
+
deprisker analyze .
|
|
72
|
+
|
|
73
|
+
# Analyze a specific project
|
|
74
|
+
deprisker analyze ~/projects/myapp
|
|
75
|
+
|
|
76
|
+
# Top 5 only, skip the HTML report
|
|
77
|
+
deprisker analyze . --top 5 --no-html
|
|
78
|
+
|
|
79
|
+
# Save the HTML report to a custom path
|
|
80
|
+
deprisker analyze . --output reports/risk.html
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Sample terminal output:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
deprisker | analyzing /home/user/myapp
|
|
87
|
+
|
|
88
|
+
Files scanned : 42
|
|
89
|
+
Import edges : 87
|
|
90
|
+
Cycles found : 2
|
|
91
|
+
High risk : 3
|
|
92
|
+
Medium risk : 11
|
|
93
|
+
Low risk : 28
|
|
94
|
+
|
|
95
|
+
-- Top 10 riskiest modules ------------------------------------------
|
|
96
|
+
1. [HIGH ] ################.... 74.3 src/auth/middleware.py
|
|
97
|
+
2. [HIGH ] ##############...... 68.1 src/db/connection.py
|
|
98
|
+
3. [HIGH ] #############....... 62.7 src/core/router.py
|
|
99
|
+
4. [MEDIUM] ########............ 41.2 src/utils/logger.py
|
|
100
|
+
5. [MEDIUM] #######............. 37.8 src/models/user.py
|
|
101
|
+
|
|
102
|
+
HTML report saved -> /home/user/myapp/deprisker_report.html
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## CLI reference
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
deprisker analyze [PATH] [OPTIONS]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`PATH` defaults to `.` if not provided.
|
|
114
|
+
|
|
115
|
+
| Flag | Short | Description |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `--output PATH` | `-o` | Output path for the HTML report (default: `deprisker_report.html`) |
|
|
118
|
+
| `--top N` | `-t` | Number of top-risk files to print (default: 10) |
|
|
119
|
+
| `--json` | `-j` | Print JSON to stdout, suppress all other output |
|
|
120
|
+
| `--no-html` | | Skip writing the HTML report |
|
|
121
|
+
| `--threshold FLOAT` | | Report only files with score ≥ threshold |
|
|
122
|
+
| `--fail-on-high` | | Exit code 1 if any HIGH risk modules exist |
|
|
123
|
+
| `--fail-on FLOAT` | | Exit code 1 if any module score ≥ this value |
|
|
124
|
+
| `--include TEXT` | | Comma-separated path prefixes to include only |
|
|
125
|
+
| `--exclude TEXT` | | Comma-separated path prefixes to exclude |
|
|
126
|
+
| `--version` | `-v` | Print version and exit |
|
|
127
|
+
|
|
128
|
+
**Exit codes:** `0` = success · `1` = threshold violated · `2` = input error · `3` = output error · `4` = invalid arguments
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## HTML report
|
|
133
|
+
|
|
134
|
+
The generated report is a single `.html` file that works offline. It contains:
|
|
135
|
+
|
|
136
|
+
- **Force-directed graph** — nodes sized by risk score, colored by risk level (red/amber/green), with zoom, pan, drag, and hover tooltips showing full risk breakdown
|
|
137
|
+
- **Bar chart** — top 10 modules ranked by score
|
|
138
|
+
- **Sortable table** — all modules with score, risk level, and dependent count; clicking a row highlights the node in the graph
|
|
139
|
+
|
|
140
|
+
No web server required. The file can be committed to the repo, shared with the team, or attached to a pull request.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Python API
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from deprisker import analyze, render_html
|
|
148
|
+
|
|
149
|
+
report = analyze("./my-project")
|
|
150
|
+
|
|
151
|
+
# Summary statistics
|
|
152
|
+
print(report.summary)
|
|
153
|
+
# {'total_files': 42, 'total_edges': 87, 'cyclic_dependencies': 2,
|
|
154
|
+
# 'high_risk_count': 3, 'medium_risk_count': 11, 'low_risk_count': 28, ...}
|
|
155
|
+
|
|
156
|
+
# Top riskiest files
|
|
157
|
+
for path, score in report.top_risks[:5]:
|
|
158
|
+
node = report.nodes[path]
|
|
159
|
+
print(f"{score:.1f} [{node.risk_level}] {path}")
|
|
160
|
+
print(f" dependents={node.risk_factors['dependents']}, "
|
|
161
|
+
f"in_cycle={node.risk_factors['in_cycle']}")
|
|
162
|
+
|
|
163
|
+
# All circular dependency chains
|
|
164
|
+
for cycle in report.cycles:
|
|
165
|
+
print(" -> ".join(cycle) + " -> ...")
|
|
166
|
+
|
|
167
|
+
# Write the HTML report
|
|
168
|
+
out = render_html(report, "risk_report.html")
|
|
169
|
+
print(f"Report saved to {out}")
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## CI integration
|
|
175
|
+
|
|
176
|
+
Fail a build if any HIGH risk module is present in the changed files:
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
# .github/workflows/risk-check.yml
|
|
180
|
+
- name: Install deprisker
|
|
181
|
+
run: pip install deprisker
|
|
182
|
+
|
|
183
|
+
- name: Check dependency risk
|
|
184
|
+
run: deprisker analyze . --no-html --fail-on-high
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Fail if any module score exceeds a custom threshold:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
deprisker analyze . --no-html --fail-on 70
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Use JSON output for custom logic:
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
import json, subprocess, sys
|
|
197
|
+
|
|
198
|
+
result = subprocess.run(
|
|
199
|
+
["deprisker", "analyze", ".", "--json"],
|
|
200
|
+
capture_output=True, text=True
|
|
201
|
+
)
|
|
202
|
+
data = json.loads(result.stdout)
|
|
203
|
+
|
|
204
|
+
high_risk = [m for m in data["modules"] if m["risk_level"] == "HIGH"]
|
|
205
|
+
if high_risk:
|
|
206
|
+
print(f"ERROR: {len(high_risk)} HIGH risk modules")
|
|
207
|
+
sys.exit(1)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## MCP server
|
|
213
|
+
|
|
214
|
+
`deprisker` exposes its analysis as an MCP server, allowing Claude and other AI agents to query dependency risk data without running the CLI.
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
deprisker mcp # stdio transport (for Claude Desktop)
|
|
218
|
+
deprisker mcp --transport http --port 8080 # HTTP transport
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Add to `claude_desktop_config.json`:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"mcpServers": {
|
|
226
|
+
"deprisker": {
|
|
227
|
+
"command": "deprisker",
|
|
228
|
+
"args": ["mcp"]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Available tools:
|
|
235
|
+
|
|
236
|
+
| Tool | Description |
|
|
237
|
+
|---|---|
|
|
238
|
+
| `analyze_project` | Analyze a directory, cache the result |
|
|
239
|
+
| `get_top_risks` | Return the N riskiest modules, with optional level/language filter |
|
|
240
|
+
| `get_module_risk` | Full risk breakdown for a specific file |
|
|
241
|
+
| `get_dependents` | Direct and transitive dependents of a module |
|
|
242
|
+
| `get_cycles` | All circular dependency chains |
|
|
243
|
+
| `check_blast_radius` | Given a list of files (e.g. a PR diff), compute total affected modules |
|
|
244
|
+
| `generate_report` | Write an HTML report to disk |
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Risk scoring
|
|
249
|
+
|
|
250
|
+
Each module is scored 0–100 using four weighted graph metrics:
|
|
251
|
+
|
|
252
|
+
| Metric | Weight | What it measures |
|
|
253
|
+
|---|---|---|
|
|
254
|
+
| In-degree | 35 | How many other modules import this one — the primary blast radius signal |
|
|
255
|
+
| Betweenness centrality | 30 | How often this module is the bridge between others — breaking it disconnects the graph |
|
|
256
|
+
| Lines of code | 15 | Surface area for bugs; larger files are harder to change safely |
|
|
257
|
+
| Cycle participation | 20 | Flat penalty for being in a circular dependency — changes ripple unpredictably |
|
|
258
|
+
|
|
259
|
+
**Risk levels:**
|
|
260
|
+
- `HIGH` — score ≥ 60. A bug here cascades widely.
|
|
261
|
+
- `MEDIUM` — score 30–59. Changes warrant extra review.
|
|
262
|
+
- `LOW` — score < 30. Relatively safe to modify independently.
|
|
263
|
+
|
|
264
|
+
All weights and thresholds are configurable via the Python API:
|
|
265
|
+
|
|
266
|
+
```python
|
|
267
|
+
from deprisker import analyze
|
|
268
|
+
from deprisker.config import Config
|
|
269
|
+
|
|
270
|
+
cfg = Config(
|
|
271
|
+
weight_in_degree=40,
|
|
272
|
+
weight_betweenness=25,
|
|
273
|
+
weight_loc=15,
|
|
274
|
+
weight_cycle=20,
|
|
275
|
+
high_threshold=65.0,
|
|
276
|
+
)
|
|
277
|
+
report = analyze(".", config=cfg)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Language support
|
|
283
|
+
|
|
284
|
+
| Language | Extensions | Import strategy |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| Python | `.py` | AST-based (`ast` module) |
|
|
287
|
+
| JavaScript / TypeScript | `.js` `.ts` `.jsx` `.tsx` `.mjs` `.cjs` | Regex — ESM imports and `require()` |
|
|
288
|
+
| Go | `.go` | Regex — single and block imports; `go.mod`-aware |
|
|
289
|
+
| Rust | `.rs` | Regex — `use crate::`, `use super::`, `mod name;` |
|
|
290
|
+
| Ruby | `.rb` | Regex — `require_relative` and `require` |
|
|
291
|
+
| Java | `.java` | Regex — fully-qualified imports; base package auto-detected |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## License
|
|
296
|
+
|
|
297
|
+
MIT
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# deprisker
|
|
2
|
+
|
|
3
|
+
**Find which files will hurt the most when they break.**
|
|
4
|
+
|
|
5
|
+
`deprisker` builds a directed dependency graph from your codebase and scores every module by its blast radius — how many other modules would break if it did. It surfaces this as a terminal report, a self-contained interactive HTML visualization, and a structured JSON output for CI pipelines and AI agents.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Why this exists
|
|
10
|
+
|
|
11
|
+
Every codebase has files that, if incorrectly modified, cascade failures across a disproportionate number of other modules. These high-risk files are not obvious from reading the code. A large file is not necessarily risky. A heavily tested file is not necessarily safe. What actually determines blast radius is **structural position in the dependency graph** — how many other modules depend on it, whether it bridges otherwise disconnected parts of the system, and whether it participates in circular dependency chains.
|
|
12
|
+
|
|
13
|
+
`deprisker` answers the question _"which file should I be most careful editing?"_ before a refactor, release, or code review — in under 10 seconds, with no configuration required.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Zero configuration** — point at a directory, get results
|
|
20
|
+
- **Multi-language** — Python, JavaScript/TypeScript, Go, Rust, Ruby, and Java
|
|
21
|
+
- **Graph-theoretic scoring** — risk is computed from in-degree, betweenness centrality, lines of code, and cycle participation; not heuristics
|
|
22
|
+
- **Interactive HTML report** — force-directed dependency graph, bar chart of top risks, sortable table; all in a single self-contained file with no server required
|
|
23
|
+
- **CI-ready** — `--fail-on-high` and `--fail-on <score>` flags for pipeline integration
|
|
24
|
+
- **MCP server** — expose analysis as queryable tools for Claude and other AI agents
|
|
25
|
+
- **Structured JSON** — `--json` flag for agent pipelines and custom tooling
|
|
26
|
+
- **No LLM required** — purely deterministic static analysis
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install deprisker
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Requires Python 3.9+.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Quick start
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Analyze the current directory
|
|
44
|
+
deprisker analyze .
|
|
45
|
+
|
|
46
|
+
# Analyze a specific project
|
|
47
|
+
deprisker analyze ~/projects/myapp
|
|
48
|
+
|
|
49
|
+
# Top 5 only, skip the HTML report
|
|
50
|
+
deprisker analyze . --top 5 --no-html
|
|
51
|
+
|
|
52
|
+
# Save the HTML report to a custom path
|
|
53
|
+
deprisker analyze . --output reports/risk.html
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Sample terminal output:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
deprisker | analyzing /home/user/myapp
|
|
60
|
+
|
|
61
|
+
Files scanned : 42
|
|
62
|
+
Import edges : 87
|
|
63
|
+
Cycles found : 2
|
|
64
|
+
High risk : 3
|
|
65
|
+
Medium risk : 11
|
|
66
|
+
Low risk : 28
|
|
67
|
+
|
|
68
|
+
-- Top 10 riskiest modules ------------------------------------------
|
|
69
|
+
1. [HIGH ] ################.... 74.3 src/auth/middleware.py
|
|
70
|
+
2. [HIGH ] ##############...... 68.1 src/db/connection.py
|
|
71
|
+
3. [HIGH ] #############....... 62.7 src/core/router.py
|
|
72
|
+
4. [MEDIUM] ########............ 41.2 src/utils/logger.py
|
|
73
|
+
5. [MEDIUM] #######............. 37.8 src/models/user.py
|
|
74
|
+
|
|
75
|
+
HTML report saved -> /home/user/myapp/deprisker_report.html
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## CLI reference
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
deprisker analyze [PATH] [OPTIONS]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`PATH` defaults to `.` if not provided.
|
|
87
|
+
|
|
88
|
+
| Flag | Short | Description |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `--output PATH` | `-o` | Output path for the HTML report (default: `deprisker_report.html`) |
|
|
91
|
+
| `--top N` | `-t` | Number of top-risk files to print (default: 10) |
|
|
92
|
+
| `--json` | `-j` | Print JSON to stdout, suppress all other output |
|
|
93
|
+
| `--no-html` | | Skip writing the HTML report |
|
|
94
|
+
| `--threshold FLOAT` | | Report only files with score ≥ threshold |
|
|
95
|
+
| `--fail-on-high` | | Exit code 1 if any HIGH risk modules exist |
|
|
96
|
+
| `--fail-on FLOAT` | | Exit code 1 if any module score ≥ this value |
|
|
97
|
+
| `--include TEXT` | | Comma-separated path prefixes to include only |
|
|
98
|
+
| `--exclude TEXT` | | Comma-separated path prefixes to exclude |
|
|
99
|
+
| `--version` | `-v` | Print version and exit |
|
|
100
|
+
|
|
101
|
+
**Exit codes:** `0` = success · `1` = threshold violated · `2` = input error · `3` = output error · `4` = invalid arguments
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## HTML report
|
|
106
|
+
|
|
107
|
+
The generated report is a single `.html` file that works offline. It contains:
|
|
108
|
+
|
|
109
|
+
- **Force-directed graph** — nodes sized by risk score, colored by risk level (red/amber/green), with zoom, pan, drag, and hover tooltips showing full risk breakdown
|
|
110
|
+
- **Bar chart** — top 10 modules ranked by score
|
|
111
|
+
- **Sortable table** — all modules with score, risk level, and dependent count; clicking a row highlights the node in the graph
|
|
112
|
+
|
|
113
|
+
No web server required. The file can be committed to the repo, shared with the team, or attached to a pull request.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Python API
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from deprisker import analyze, render_html
|
|
121
|
+
|
|
122
|
+
report = analyze("./my-project")
|
|
123
|
+
|
|
124
|
+
# Summary statistics
|
|
125
|
+
print(report.summary)
|
|
126
|
+
# {'total_files': 42, 'total_edges': 87, 'cyclic_dependencies': 2,
|
|
127
|
+
# 'high_risk_count': 3, 'medium_risk_count': 11, 'low_risk_count': 28, ...}
|
|
128
|
+
|
|
129
|
+
# Top riskiest files
|
|
130
|
+
for path, score in report.top_risks[:5]:
|
|
131
|
+
node = report.nodes[path]
|
|
132
|
+
print(f"{score:.1f} [{node.risk_level}] {path}")
|
|
133
|
+
print(f" dependents={node.risk_factors['dependents']}, "
|
|
134
|
+
f"in_cycle={node.risk_factors['in_cycle']}")
|
|
135
|
+
|
|
136
|
+
# All circular dependency chains
|
|
137
|
+
for cycle in report.cycles:
|
|
138
|
+
print(" -> ".join(cycle) + " -> ...")
|
|
139
|
+
|
|
140
|
+
# Write the HTML report
|
|
141
|
+
out = render_html(report, "risk_report.html")
|
|
142
|
+
print(f"Report saved to {out}")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## CI integration
|
|
148
|
+
|
|
149
|
+
Fail a build if any HIGH risk module is present in the changed files:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
# .github/workflows/risk-check.yml
|
|
153
|
+
- name: Install deprisker
|
|
154
|
+
run: pip install deprisker
|
|
155
|
+
|
|
156
|
+
- name: Check dependency risk
|
|
157
|
+
run: deprisker analyze . --no-html --fail-on-high
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Fail if any module score exceeds a custom threshold:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
deprisker analyze . --no-html --fail-on 70
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Use JSON output for custom logic:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
import json, subprocess, sys
|
|
170
|
+
|
|
171
|
+
result = subprocess.run(
|
|
172
|
+
["deprisker", "analyze", ".", "--json"],
|
|
173
|
+
capture_output=True, text=True
|
|
174
|
+
)
|
|
175
|
+
data = json.loads(result.stdout)
|
|
176
|
+
|
|
177
|
+
high_risk = [m for m in data["modules"] if m["risk_level"] == "HIGH"]
|
|
178
|
+
if high_risk:
|
|
179
|
+
print(f"ERROR: {len(high_risk)} HIGH risk modules")
|
|
180
|
+
sys.exit(1)
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## MCP server
|
|
186
|
+
|
|
187
|
+
`deprisker` exposes its analysis as an MCP server, allowing Claude and other AI agents to query dependency risk data without running the CLI.
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
deprisker mcp # stdio transport (for Claude Desktop)
|
|
191
|
+
deprisker mcp --transport http --port 8080 # HTTP transport
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Add to `claude_desktop_config.json`:
|
|
195
|
+
|
|
196
|
+
```json
|
|
197
|
+
{
|
|
198
|
+
"mcpServers": {
|
|
199
|
+
"deprisker": {
|
|
200
|
+
"command": "deprisker",
|
|
201
|
+
"args": ["mcp"]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Available tools:
|
|
208
|
+
|
|
209
|
+
| Tool | Description |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `analyze_project` | Analyze a directory, cache the result |
|
|
212
|
+
| `get_top_risks` | Return the N riskiest modules, with optional level/language filter |
|
|
213
|
+
| `get_module_risk` | Full risk breakdown for a specific file |
|
|
214
|
+
| `get_dependents` | Direct and transitive dependents of a module |
|
|
215
|
+
| `get_cycles` | All circular dependency chains |
|
|
216
|
+
| `check_blast_radius` | Given a list of files (e.g. a PR diff), compute total affected modules |
|
|
217
|
+
| `generate_report` | Write an HTML report to disk |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Risk scoring
|
|
222
|
+
|
|
223
|
+
Each module is scored 0–100 using four weighted graph metrics:
|
|
224
|
+
|
|
225
|
+
| Metric | Weight | What it measures |
|
|
226
|
+
|---|---|---|
|
|
227
|
+
| In-degree | 35 | How many other modules import this one — the primary blast radius signal |
|
|
228
|
+
| Betweenness centrality | 30 | How often this module is the bridge between others — breaking it disconnects the graph |
|
|
229
|
+
| Lines of code | 15 | Surface area for bugs; larger files are harder to change safely |
|
|
230
|
+
| Cycle participation | 20 | Flat penalty for being in a circular dependency — changes ripple unpredictably |
|
|
231
|
+
|
|
232
|
+
**Risk levels:**
|
|
233
|
+
- `HIGH` — score ≥ 60. A bug here cascades widely.
|
|
234
|
+
- `MEDIUM` — score 30–59. Changes warrant extra review.
|
|
235
|
+
- `LOW` — score < 30. Relatively safe to modify independently.
|
|
236
|
+
|
|
237
|
+
All weights and thresholds are configurable via the Python API:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from deprisker import analyze
|
|
241
|
+
from deprisker.config import Config
|
|
242
|
+
|
|
243
|
+
cfg = Config(
|
|
244
|
+
weight_in_degree=40,
|
|
245
|
+
weight_betweenness=25,
|
|
246
|
+
weight_loc=15,
|
|
247
|
+
weight_cycle=20,
|
|
248
|
+
high_threshold=65.0,
|
|
249
|
+
)
|
|
250
|
+
report = analyze(".", config=cfg)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Language support
|
|
256
|
+
|
|
257
|
+
| Language | Extensions | Import strategy |
|
|
258
|
+
|---|---|---|
|
|
259
|
+
| Python | `.py` | AST-based (`ast` module) |
|
|
260
|
+
| JavaScript / TypeScript | `.js` `.ts` `.jsx` `.tsx` `.mjs` `.cjs` | Regex — ESM imports and `require()` |
|
|
261
|
+
| Go | `.go` | Regex — single and block imports; `go.mod`-aware |
|
|
262
|
+
| Rust | `.rs` | Regex — `use crate::`, `use super::`, `mod name;` |
|
|
263
|
+
| Ruby | `.rb` | Regex — `require_relative` and `require` |
|
|
264
|
+
| Java | `.java` | Regex — fully-qualified imports; base package auto-detected |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT
|