@sun-asterisk/impact-analyzer 1.0.4 → 1.0.5
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.
- package/.github/copilot-instructions.md +116 -0
- package/.github/prompts/README.md +91 -0
- package/.github/prompts/task-001-refactor.prompt.md +241 -0
- package/.specify/bugs/bug-001-database-detector.md +222 -0
- package/.specify/plans/architecture.md +186 -0
- package/.specify/specs/features/api-impact-detection.md +317 -0
- package/.specify/specs/features/component-impact-detection.md +263 -0
- package/.specify/specs/features/database-impact-detection.md +247 -0
- package/.specify/tasks/task-001-refactor-api-detector.md +284 -0
- package/.specify/tasks/task-002-database-detector.md +593 -0
- package/.specify/tasks/task-003-component-detector.md +0 -0
- package/.specify/tasks/task-004-report.md +484 -0
- package/README.md +13 -19
- package/core/detectors/database-detector.js +702 -0
- package/{modules → core}/detectors/endpoint-detector.js +11 -8
- package/{modules → core}/report-generator.js +102 -20
- package/core/utils/logger.js +12 -0
- package/index.js +6 -5
- package/package.json +1 -1
- package/modules/detectors/database-detector.js +0 -182
- /package/{modules → core}/change-detector.js +0 -0
- /package/{modules → core}/impact-analyzer.js +0 -0
- /package/{modules → core}/utils/ast-parser.js +0 -0
- /package/{modules → core}/utils/dependency-graph.js +0 -0
- /package/{modules → core}/utils/file-utils.js +0 -0
- /package/{modules → core}/utils/git-utils.js +0 -0
- /package/{modules → core}/utils/method-call-graph.js +0 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
# Task 004: Fix Report Generator - Output Format Issues
|
|
2
|
+
|
|
3
|
+
**Status:** 📋 TODO
|
|
4
|
+
**Priority:** 🔴 HIGH
|
|
5
|
+
**Assignee:** AI Agent
|
|
6
|
+
**Created:** 2025-12-25
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 📝 Overview
|
|
11
|
+
|
|
12
|
+
Fix report generator to correctly display impact analysis data in both Markdown and JSON formats. Current issues:
|
|
13
|
+
1. **Field name mismatches** - Using old field names (`table` instead of `tableName`)
|
|
14
|
+
2. **Source code in reports** - Showing code snippets instead of just affected entities
|
|
15
|
+
3. **JSON output broken** - Contains internal data structures not suitable for reports
|
|
16
|
+
|
|
17
|
+
## 🎯 Goals
|
|
18
|
+
|
|
19
|
+
### 1. Update Report Field Names
|
|
20
|
+
The database detector now returns spec-compliant output, but the report generator uses old field names.
|
|
21
|
+
|
|
22
|
+
**Current Issue:**
|
|
23
|
+
```javascript
|
|
24
|
+
// Report uses:
|
|
25
|
+
db.table // ❌ Undefined
|
|
26
|
+
db.name // ❌ Undefined
|
|
27
|
+
|
|
28
|
+
// Should use:
|
|
29
|
+
db.tableName // ✅ Correct
|
|
30
|
+
db.modelName // ✅ Correct
|
|
31
|
+
db.modelPath // ✅ Correct
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 2. Remove Source Code from Reports
|
|
35
|
+
Reports should focus on **WHAT** changed, not HOW it changed.
|
|
36
|
+
|
|
37
|
+
**Show:**
|
|
38
|
+
- ✅ Endpoint paths: `GET /users/:id`
|
|
39
|
+
- ✅ Table names: `users`, `posts`
|
|
40
|
+
- ✅ Field names: `email`, `phone`
|
|
41
|
+
- ✅ Component names: `UserProfile.tsx`
|
|
42
|
+
- ✅ Impact severity: `critical`, `high`
|
|
43
|
+
|
|
44
|
+
**Do NOT Show:**
|
|
45
|
+
- ❌ Code snippets
|
|
46
|
+
- ❌ Diff output
|
|
47
|
+
- ❌ Method implementations
|
|
48
|
+
- ❌ File contents
|
|
49
|
+
- ❌ Git diff details
|
|
50
|
+
|
|
51
|
+
### 3. Fix JSON Output
|
|
52
|
+
JSON output should be clean, structured data suitable for CI/CD integration.
|
|
53
|
+
|
|
54
|
+
**Requirements:**
|
|
55
|
+
- Remove internal data structures (AST, diff, oldContent)
|
|
56
|
+
- Remove file contents
|
|
57
|
+
- Focus on actionable insights
|
|
58
|
+
- Flatten nested structures where appropriate
|
|
59
|
+
|
|
60
|
+
## 📋 Implementation Tasks
|
|
61
|
+
|
|
62
|
+
### Phase 1: Audit Current Issues
|
|
63
|
+
|
|
64
|
+
- [ ] List all places using old field names (`table`, `name`)
|
|
65
|
+
- [ ] Identify where source code is being included
|
|
66
|
+
- [ ] Review JSON output structure
|
|
67
|
+
- [ ] Document expected vs actual output
|
|
68
|
+
|
|
69
|
+
**Audit Checklist:**
|
|
70
|
+
```bash
|
|
71
|
+
# Find old field references
|
|
72
|
+
grep -n "\.table\b" core/report-generator.js
|
|
73
|
+
grep -n "\.name\b" core/report-generator.js
|
|
74
|
+
|
|
75
|
+
# Check what's in changes object
|
|
76
|
+
grep -n "changes\." core/report-generator.js
|
|
77
|
+
|
|
78
|
+
# Check JSON output
|
|
79
|
+
grep -n "JSON.stringify" index.js
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Phase 2: Fix Database Section
|
|
83
|
+
|
|
84
|
+
**File:** `core/report-generator.js`
|
|
85
|
+
|
|
86
|
+
#### Issue 1: Wrong Field Names
|
|
87
|
+
|
|
88
|
+
**Current Code:**
|
|
89
|
+
```javascript
|
|
90
|
+
lines.push(`| \`${db.table}\` | ${db.operations.join(', ')} | ${fieldsDisplay} |`);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Fixed Code:**
|
|
94
|
+
```javascript
|
|
95
|
+
lines.push(`| \`${db.tableName}\` | ${db.operations.join(', ')} | ${fieldsDisplay} |`);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### Issue 2: Show Model Information
|
|
99
|
+
|
|
100
|
+
**Add to report:**
|
|
101
|
+
```javascript
|
|
102
|
+
// Database Impact Section
|
|
103
|
+
lines.push('| Table | Model | Impact Type | Severity | Operations |');
|
|
104
|
+
lines.push('|-------|-------|-------------|----------|-----------|');
|
|
105
|
+
|
|
106
|
+
dbImpacts.forEach(db => {
|
|
107
|
+
lines.push(`| \`${db.tableName}\` | ${db.modelName} | ${db.impactType} | ${db.severity} | ${db.operations.join(', ')} |`);
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Detailed Section:**
|
|
112
|
+
```javascript
|
|
113
|
+
dbImpacts.forEach(db => {
|
|
114
|
+
lines.push(`### \`${db.tableName}\` (${db.modelName})\n`);
|
|
115
|
+
lines.push(`- **Impact Type:** ${db.impactType}`);
|
|
116
|
+
lines.push(`- **Severity:** ${db.severity}`);
|
|
117
|
+
lines.push(`- **Operations:** ${db.operations.join(', ')}`);
|
|
118
|
+
lines.push(`- **Entity File:** ${db.modelPath}`);
|
|
119
|
+
|
|
120
|
+
if (db.fields && db.fields.length > 0) {
|
|
121
|
+
lines.push(`- **Affected Fields:** ${db.fields.map(f => `\`${f}\``).join(', ')}`);
|
|
122
|
+
}
|
|
123
|
+
lines.push('');
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Phase 3: Fix Console Report
|
|
128
|
+
|
|
129
|
+
**File:** `core/report-generator.js`
|
|
130
|
+
|
|
131
|
+
**Current Issue:**
|
|
132
|
+
```javascript
|
|
133
|
+
console.log(` • ${d.table} (${d.operations.join(', ')})`); // ❌ undefined
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Fix:**
|
|
137
|
+
```javascript
|
|
138
|
+
console.log(` • ${d.tableName} (${d.impactType}, ${d.severity})`);
|
|
139
|
+
console.log(` Operations: ${d.operations.join(', ')}`);
|
|
140
|
+
if (d.fields && d.fields.length > 0) {
|
|
141
|
+
console.log(` Fields: ${d.fields.slice(0, 5).join(', ')}${d.fields.length > 5 ? '...' : ''}`);
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Phase 4: Clean JSON Output
|
|
146
|
+
|
|
147
|
+
**File:** `index.js`
|
|
148
|
+
|
|
149
|
+
**Current Issue:**
|
|
150
|
+
```javascript
|
|
151
|
+
// This includes everything, including code and diffs
|
|
152
|
+
fs.writeFileSync(jsonOutput, JSON.stringify({ changes, impact }, null, 2));
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Solution:** Create clean report structure
|
|
156
|
+
|
|
157
|
+
```javascript
|
|
158
|
+
// Create clean JSON report
|
|
159
|
+
const jsonReport = reporter.generateJSONReport(changes, impact);
|
|
160
|
+
fs.writeFileSync(jsonOutput, JSON.stringify(jsonReport, null, 2));
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Implementation in `report-generator.js`:**
|
|
164
|
+
```javascript
|
|
165
|
+
/**
|
|
166
|
+
* Generate clean JSON report suitable for CI/CD
|
|
167
|
+
* Excludes source code, diffs, and internal data structures
|
|
168
|
+
*/
|
|
169
|
+
generateJSONReport(changes, impact) {
|
|
170
|
+
return {
|
|
171
|
+
metadata: {
|
|
172
|
+
timestamp: new Date().toISOString(),
|
|
173
|
+
filesChanged: changes.changedFiles.length,
|
|
174
|
+
symbolsChanged: changes.changedSymbols?.length || 0,
|
|
175
|
+
},
|
|
176
|
+
summary: {
|
|
177
|
+
impactScore: impact.impactScore,
|
|
178
|
+
severity: impact.severity,
|
|
179
|
+
affectedEndpoints: impact.affectedEndpoints?.length || 0,
|
|
180
|
+
affectedTables: impact.databaseImpact?.length || 0,
|
|
181
|
+
affectedComponents: this.countComponents(changes.changedFiles),
|
|
182
|
+
},
|
|
183
|
+
endpoints: this.formatEndpointsForJSON(impact.affectedEndpoints),
|
|
184
|
+
database: this.formatDatabaseForJSON(impact.databaseImpact),
|
|
185
|
+
components: this.formatComponentsForJSON(changes.changedFiles),
|
|
186
|
+
logic: {
|
|
187
|
+
riskLevel: impact.logicImpact?.riskLevel || 'low',
|
|
188
|
+
directCallers: impact.logicImpact?.directCallers?.length || 0,
|
|
189
|
+
indirectCallers: impact.logicImpact?.indirectCallers?.length || 0,
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
formatEndpointsForJSON(endpoints) {
|
|
195
|
+
if (!endpoints || endpoints.length === 0) return [];
|
|
196
|
+
|
|
197
|
+
return endpoints.map(e => ({
|
|
198
|
+
method: e.method,
|
|
199
|
+
path: e.path,
|
|
200
|
+
controller: e.controller,
|
|
201
|
+
impactLevel: e.impactLevel,
|
|
202
|
+
// DO NOT include: affectedBy, callChain with code
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
formatDatabaseForJSON(dbImpacts) {
|
|
207
|
+
if (!dbImpacts || dbImpacts.length === 0) return [];
|
|
208
|
+
|
|
209
|
+
return dbImpacts.map(db => ({
|
|
210
|
+
tableName: db.tableName,
|
|
211
|
+
modelName: db.modelName,
|
|
212
|
+
modelPath: db.modelPath,
|
|
213
|
+
impactType: db.impactType,
|
|
214
|
+
severity: db.severity,
|
|
215
|
+
operations: db.operations,
|
|
216
|
+
fields: db.fields || [],
|
|
217
|
+
// DO NOT include: changeSource with diff/content
|
|
218
|
+
}));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
formatComponentsForJSON(changedFiles) {
|
|
222
|
+
const components = changedFiles.filter(f => this.isComponentFile(f));
|
|
223
|
+
|
|
224
|
+
return components.map(c => ({
|
|
225
|
+
path: c.path,
|
|
226
|
+
type: this.detectPageType(c.path),
|
|
227
|
+
status: c.status,
|
|
228
|
+
linesAdded: c.changes?.added || 0,
|
|
229
|
+
linesDeleted: c.changes?.deleted || 0,
|
|
230
|
+
// DO NOT include: content, oldContent, diff
|
|
231
|
+
}));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
isComponentFile(file) {
|
|
235
|
+
const path = file.path.toLowerCase();
|
|
236
|
+
return (
|
|
237
|
+
path.includes('/page') || path.includes('/component') ||
|
|
238
|
+
path.includes('/view') || path.includes('/screen') ||
|
|
239
|
+
path.includes('.page.') || path.includes('.component.')
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
countComponents(changedFiles) {
|
|
244
|
+
return changedFiles.filter(f => this.isComponentFile(f)).length;
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Phase 5: Remove Code from Markdown Report
|
|
249
|
+
|
|
250
|
+
**File:** `core/report-generator.js`
|
|
251
|
+
|
|
252
|
+
**Current Issues to Fix:**
|
|
253
|
+
|
|
254
|
+
1. **Changed Files Section** - Showing diff snippets
|
|
255
|
+
```javascript
|
|
256
|
+
// REMOVE OR SIMPLIFY
|
|
257
|
+
generateChangedFilesSection(changedFiles) {
|
|
258
|
+
// Don't show: oldContent, content, diff
|
|
259
|
+
// Only show: path, status, lines changed
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
2. **Logic Impact Section** - Showing method details
|
|
264
|
+
```javascript
|
|
265
|
+
// Keep simple
|
|
266
|
+
lines.push(`**Direct Callers:** ${logicImpact.directCallers.length}`);
|
|
267
|
+
lines.push(`**Indirect Callers:** ${logicImpact.indirectCallers.length}`);
|
|
268
|
+
// Don't list all method names with signatures
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Clean Changed Files Section:**
|
|
272
|
+
```javascript
|
|
273
|
+
generateChangedFilesSection(changedFiles) {
|
|
274
|
+
const lines = ['## 📝 Changed Files\n'];
|
|
275
|
+
|
|
276
|
+
lines.push(`**Total Files Changed:** ${changedFiles.length}\n`);
|
|
277
|
+
|
|
278
|
+
lines.push('| File | Type | Status | Changes |');
|
|
279
|
+
lines.push('|------|------|--------|---------|');
|
|
280
|
+
|
|
281
|
+
changedFiles.forEach(f => {
|
|
282
|
+
const type = f.type || 'source';
|
|
283
|
+
const changes = `+${f.changes?.added || 0} -${f.changes?.deleted || 0}`;
|
|
284
|
+
const statusEmoji = this.getStatusEmoji(f.status);
|
|
285
|
+
lines.push(`| ${statusEmoji} ${f.path} | ${type} | ${f.status} | ${changes} |`);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return lines.join('\n');
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## ✅ Acceptance Criteria
|
|
293
|
+
|
|
294
|
+
### Markdown Report
|
|
295
|
+
- [ ] Database section uses `tableName`, `modelName`, `modelPath`
|
|
296
|
+
- [ ] Database section shows `impactType` and `severity`
|
|
297
|
+
- [ ] No source code snippets
|
|
298
|
+
- [ ] No diff output
|
|
299
|
+
- [ ] Only shows entity names and affected fields
|
|
300
|
+
|
|
301
|
+
### Console Report
|
|
302
|
+
- [ ] Database section uses correct field names
|
|
303
|
+
- [ ] Shows severity for each table
|
|
304
|
+
- [ ] Compact, readable format
|
|
305
|
+
- [ ] No code output
|
|
306
|
+
|
|
307
|
+
### JSON Report
|
|
308
|
+
- [ ] Clean structure suitable for CI/CD
|
|
309
|
+
- [ ] No `content`, `oldContent`, `diff` fields
|
|
310
|
+
- [ ] Uses correct field names (`tableName` not `table`)
|
|
311
|
+
- [ ] Flat structure where possible
|
|
312
|
+
- [ ] Includes metadata (timestamp, counts)
|
|
313
|
+
- [ ] Valid JSON format
|
|
314
|
+
|
|
315
|
+
## 🧪 Testing
|
|
316
|
+
|
|
317
|
+
### Manual Tests
|
|
318
|
+
|
|
319
|
+
**Test 1: Markdown Report Format**
|
|
320
|
+
```bash
|
|
321
|
+
node index.js --input=src --base=origin/main --output=test-report.md
|
|
322
|
+
|
|
323
|
+
# Check report:
|
|
324
|
+
cat test-report.md
|
|
325
|
+
|
|
326
|
+
# Expected:
|
|
327
|
+
# - Database section has tableName, modelName
|
|
328
|
+
# - No code snippets
|
|
329
|
+
# - Clean table format
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Test 2: JSON Report Format**
|
|
333
|
+
```bash
|
|
334
|
+
node index.js --input=src --base=origin/main --json=test-report.json
|
|
335
|
+
|
|
336
|
+
# Check JSON:
|
|
337
|
+
cat test-report.json | jq .
|
|
338
|
+
|
|
339
|
+
# Expected:
|
|
340
|
+
# - Valid JSON
|
|
341
|
+
# - No content/diff fields
|
|
342
|
+
# - Clean database section with tableName
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Test 3: Console Output**
|
|
346
|
+
```bash
|
|
347
|
+
node index.js --input=src --base=origin/main
|
|
348
|
+
|
|
349
|
+
# Expected:
|
|
350
|
+
# - Database impact shows tableName
|
|
351
|
+
# - No undefined values
|
|
352
|
+
# - Clean, readable output
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## 📊 Expected Output Examples
|
|
356
|
+
|
|
357
|
+
### Markdown Report
|
|
358
|
+
|
|
359
|
+
#### Database Section
|
|
360
|
+
```markdown
|
|
361
|
+
## 💾 Database Impact
|
|
362
|
+
|
|
363
|
+
**Total Tables Affected:** 2
|
|
364
|
+
|
|
365
|
+
| Table | Model | Impact Type | Severity | Operations |
|
|
366
|
+
|-------|-------|-------------|----------|-----------|
|
|
367
|
+
| `users` | UserEntity | schema | critical | SELECT, INSERT, UPDATE |
|
|
368
|
+
| `posts` | PostEntity | query | medium | INSERT |
|
|
369
|
+
|
|
370
|
+
### Details
|
|
371
|
+
|
|
372
|
+
#### `users` (UserEntity)
|
|
373
|
+
- **Impact Type:** schema
|
|
374
|
+
- **Severity:** critical
|
|
375
|
+
- **Operations:** SELECT, INSERT, UPDATE
|
|
376
|
+
- **Entity File:** src/entities/user.entity.ts
|
|
377
|
+
- **Affected Fields:** `email`, `phone`, `updatedAt`
|
|
378
|
+
|
|
379
|
+
#### `posts` (PostEntity)
|
|
380
|
+
- **Impact Type:** query
|
|
381
|
+
- **Severity:** medium
|
|
382
|
+
- **Operations:** INSERT
|
|
383
|
+
- **Entity File:** src/entities/post.entity.ts
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### JSON Report
|
|
387
|
+
```json
|
|
388
|
+
{
|
|
389
|
+
"metadata": {
|
|
390
|
+
"timestamp": "2025-12-25T03:00:00.000Z",
|
|
391
|
+
"filesChanged": 5,
|
|
392
|
+
"symbolsChanged": 8
|
|
393
|
+
},
|
|
394
|
+
"summary": {
|
|
395
|
+
"impactScore": 75,
|
|
396
|
+
"severity": "high",
|
|
397
|
+
"affectedEndpoints": 3,
|
|
398
|
+
"affectedTables": 2,
|
|
399
|
+
"affectedComponents": 1
|
|
400
|
+
},
|
|
401
|
+
"endpoints": [
|
|
402
|
+
{
|
|
403
|
+
"method": "GET",
|
|
404
|
+
"path": "/users/:id",
|
|
405
|
+
"controller": "UserController.getUser",
|
|
406
|
+
"impactLevel": "high"
|
|
407
|
+
}
|
|
408
|
+
],
|
|
409
|
+
"database": [
|
|
410
|
+
{
|
|
411
|
+
"tableName": "users",
|
|
412
|
+
"modelName": "UserEntity",
|
|
413
|
+
"modelPath": "src/entities/user.entity.ts",
|
|
414
|
+
"impactType": "schema",
|
|
415
|
+
"severity": "critical",
|
|
416
|
+
"operations": ["SELECT", "INSERT", "UPDATE"],
|
|
417
|
+
"fields": ["email", "phone", "updatedAt"]
|
|
418
|
+
}
|
|
419
|
+
],
|
|
420
|
+
"components": [
|
|
421
|
+
{
|
|
422
|
+
"path": "src/pages/UserProfile.tsx",
|
|
423
|
+
"type": "page",
|
|
424
|
+
"status": "modified",
|
|
425
|
+
"linesAdded": 15,
|
|
426
|
+
"linesDeleted": 3
|
|
427
|
+
}
|
|
428
|
+
],
|
|
429
|
+
"logic": {
|
|
430
|
+
"riskLevel": "medium",
|
|
431
|
+
"directCallers": 5,
|
|
432
|
+
"indirectCallers": 12
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Console Output
|
|
438
|
+
```
|
|
439
|
+
💾 DATABASE IMPACT:
|
|
440
|
+
• users (schema, critical)
|
|
441
|
+
Operations: SELECT, INSERT, UPDATE
|
|
442
|
+
Fields: email, phone, updatedAt
|
|
443
|
+
• posts (query, medium)
|
|
444
|
+
Operations: INSERT
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## 🎯 Definition of Done
|
|
448
|
+
|
|
449
|
+
- [ ] All field name mismatches fixed
|
|
450
|
+
- [ ] No source code in reports
|
|
451
|
+
- [ ] JSON output uses clean structure
|
|
452
|
+
- [ ] Markdown report shows proper database info
|
|
453
|
+
- [ ] Console report uses correct fields
|
|
454
|
+
- [ ] All tests pass
|
|
455
|
+
- [ ] Reports are readable and actionable
|
|
456
|
+
- [ ] JSON is valid and CI/CD friendly
|
|
457
|
+
|
|
458
|
+
## 🔗 References
|
|
459
|
+
|
|
460
|
+
- **Current Code:** `core/report-generator.js`, `index.js`
|
|
461
|
+
- **Spec:** `.specify/specs/features/database-impact-detection.md` (Section 5 - Output Schema)
|
|
462
|
+
- **Task 002:** `.specify/tasks/task-002-database-detector.md` (Database output format)
|
|
463
|
+
|
|
464
|
+
## 📝 Notes
|
|
465
|
+
|
|
466
|
+
### Report Best Practices
|
|
467
|
+
|
|
468
|
+
1. **Focus on "What" not "How"**
|
|
469
|
+
- ✅ "Table `users` changed"
|
|
470
|
+
- ❌ "Line 45: `email: string;` added"
|
|
471
|
+
|
|
472
|
+
2. **Keep JSON Clean**
|
|
473
|
+
- ✅ Include: tableName, operations, severity
|
|
474
|
+
- ❌ Exclude: diff, content, oldContent, AST
|
|
475
|
+
|
|
476
|
+
3. **Make Reports Actionable**
|
|
477
|
+
- Show severity so developers know priority
|
|
478
|
+
- Show affected entities so QA knows what to test
|
|
479
|
+
- Show file paths for quick navigation
|
|
480
|
+
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
**Last Updated:** 2025-12-25
|
|
484
|
+
**Implementation Status:** TODO
|
package/README.md
CHANGED
|
@@ -151,7 +151,7 @@ npx @sun-asterisk/impact-analyzer --input=src --base=abc123 --head=def456
|
|
|
151
151
|
|
|
152
152
|
## CI/CD Integration
|
|
153
153
|
|
|
154
|
-
### GitHub Actions
|
|
154
|
+
### GitHub Actions (Recommended - Simple)
|
|
155
155
|
|
|
156
156
|
```yaml
|
|
157
157
|
name: Impact Analysis
|
|
@@ -165,7 +165,7 @@ jobs:
|
|
|
165
165
|
steps:
|
|
166
166
|
- uses: actions/checkout@v4
|
|
167
167
|
with:
|
|
168
|
-
fetch-depth:
|
|
168
|
+
fetch-depth: 2 # Fetch current commit + parent
|
|
169
169
|
|
|
170
170
|
- uses: actions/setup-node@v3
|
|
171
171
|
with:
|
|
@@ -175,22 +175,16 @@ jobs:
|
|
|
175
175
|
run: |
|
|
176
176
|
npx @sun-asterisk/impact-analyzer \
|
|
177
177
|
--input=src \
|
|
178
|
-
--base=origin/${{ github.
|
|
179
|
-
--
|
|
180
|
-
--
|
|
178
|
+
--base=origin/${{ github.event.pull_request.base.ref }} \
|
|
179
|
+
--head=HEAD \
|
|
180
|
+
--output=impact-report.md
|
|
181
181
|
|
|
182
|
-
- name:
|
|
183
|
-
uses: actions/
|
|
182
|
+
- name: Upload impact reports
|
|
183
|
+
uses: actions/upload-artifact@v4
|
|
184
184
|
with:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
github.rest.issues.createComment({
|
|
189
|
-
issue_number: context.issue.number,
|
|
190
|
-
owner: context.repo.owner,
|
|
191
|
-
repo: context.repo.repo,
|
|
192
|
-
body: report
|
|
193
|
-
});
|
|
185
|
+
name: impact-reports-${{ github.sha }}
|
|
186
|
+
path: impact-report.md
|
|
187
|
+
retention-days: 30
|
|
194
188
|
```
|
|
195
189
|
|
|
196
190
|
### GitLab CI
|
|
@@ -200,11 +194,12 @@ impact-analysis:
|
|
|
200
194
|
stage: test
|
|
201
195
|
image: node:18
|
|
202
196
|
variables:
|
|
203
|
-
GIT_DEPTH:
|
|
197
|
+
GIT_DEPTH: 2 # Fetch current + parent commit
|
|
204
198
|
script:
|
|
205
199
|
- npx @sun-asterisk/impact-analyzer
|
|
206
200
|
--input=src
|
|
207
201
|
--base=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
|
|
202
|
+
--head=HEAD
|
|
208
203
|
--output=impact-report.md
|
|
209
204
|
--json=impact-report.json
|
|
210
205
|
artifacts:
|
|
@@ -227,6 +222,7 @@ pipeline {
|
|
|
227
222
|
npx @sun-asterisk/impact-analyzer \
|
|
228
223
|
--input=src \
|
|
229
224
|
--base=origin/main \
|
|
225
|
+
--head=HEAD \
|
|
230
226
|
--output=impact-report.md \
|
|
231
227
|
--json=impact-report.json
|
|
232
228
|
'''
|
|
@@ -236,8 +232,6 @@ pipeline {
|
|
|
236
232
|
}
|
|
237
233
|
```
|
|
238
234
|
|
|
239
|
-
## Report Output
|
|
240
|
-
|
|
241
235
|
### Severity Levels
|
|
242
236
|
|
|
243
237
|
- 🟢 **LOW** (0-20) - Minor changes
|