@sun-asterisk/impact-analyzer 1.0.2 → 1.0.4

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/README.md CHANGED
@@ -163,9 +163,9 @@ jobs:
163
163
  analyze:
164
164
  runs-on: ubuntu-latest
165
165
  steps:
166
- - uses: actions/checkout@v3
166
+ - uses: actions/checkout@v4
167
167
  with:
168
- fetch-depth: 0
168
+ fetch-depth: 0 # Fetch full history
169
169
 
170
170
  - uses: actions/setup-node@v3
171
171
  with:
@@ -176,7 +176,6 @@ jobs:
176
176
  npx @sun-asterisk/impact-analyzer \
177
177
  --input=src \
178
178
  --base=origin/${{ github.base_ref }} \
179
- --head=${{ github.sha }} \
180
179
  --output=impact-report.md \
181
180
  --json=impact-report.json
182
181
 
@@ -200,11 +199,12 @@ jobs:
200
199
  impact-analysis:
201
200
  stage: test
202
201
  image: node:18
202
+ variables:
203
+ GIT_DEPTH: 0 # Fetch full history
203
204
  script:
204
205
  - npx @sun-asterisk/impact-analyzer
205
206
  --input=src
206
207
  --base=origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
207
- --head=$CI_COMMIT_SHA
208
208
  --output=impact-report.md
209
209
  --json=impact-report.json
210
210
  artifacts:
@@ -15,7 +15,7 @@ export function loadConfig(cli) {
15
15
 
16
16
  // Git references
17
17
  baseRef: cli.getArg('base', 'origin/main'),
18
- headRef: cli.getArg('head', 'HEAD'),
18
+ headRef: cli.getArg('head', ''), // Empty means current working directory
19
19
 
20
20
  // Analysis options
21
21
  maxDepth: parseInt(cli.getArg('max-depth', '3')),
@@ -38,9 +38,11 @@ function validateConfig(config) {
38
38
  throw new Error('Source directory (--input) is required');
39
39
  }
40
40
 
41
- if (!config.baseRef || !config.headRef) {
42
- throw new Error('Git references (--base and --head) are required');
41
+ if (!config.baseRef) {
42
+ throw new Error('Base git reference (--base) is required');
43
43
  }
44
+
45
+ // headRef is optional, defaults to working directory comparison
44
46
  }
45
47
 
46
48
  export const DEFAULT_CONFIG = {
@@ -35,9 +35,14 @@ export class ReportGenerator {
35
35
  // Summary
36
36
  console.log('📊 SUMMARY:');
37
37
  console.log(` Files Changed: ${changes.changedFiles.length}`);
38
- console.log(` Symbols Modified: ${changes.changedSymbols.length}`);
39
38
  console.log(` Impact Score: ${impact.impactScore}`);
40
39
  console.log(` Severity: ${this.getSeverityEmoji(impact.severity)} ${impact.severity.toUpperCase()}`);
40
+ if (impact.affectedEndpoints.length > 0) {
41
+ console.log(` Affected Endpoints: ${impact.affectedEndpoints.length}`);
42
+ }
43
+ if (impact.databaseImpact.length > 0) {
44
+ console.log(` Database Tables: ${impact.databaseImpact.length}`);
45
+ }
41
46
  console.log('');
42
47
 
43
48
  // Endpoints
@@ -106,7 +111,8 @@ export class ReportGenerator {
106
111
  timestamp: new Date().toISOString(),
107
112
  summary: {
108
113
  filesChanged: changes.changedFiles.length,
109
- symbolsModified: changes.changedSymbols.length,
114
+ affectedEndpoints: impact.affectedEndpoints.length,
115
+ databaseTables: impact.databaseImpact.length,
110
116
  impactScore: impact.impactScore,
111
117
  severity: impact.severity,
112
118
  },
@@ -124,7 +130,8 @@ export class ReportGenerator {
124
130
  | Metric | Value |
125
131
  |--------|-------|
126
132
  | Files Changed | ${changes.changedFiles.length} |
127
- | Symbols Modified | ${changes.changedSymbols.length} |
133
+ | Affected Endpoints | ${impact.affectedEndpoints.length} |
134
+ | Database Tables | ${impact.databaseImpact.length} |
128
135
  | Impact Score | **${impact.impactScore}** |
129
136
  | Severity | ${this.getSeverityEmoji(impact.severity)} **${impact.severity.toUpperCase()}** |
130
137
 
@@ -11,7 +11,7 @@ export class GitUtils {
11
11
  /**
12
12
  * Get list of changed files between two refs
13
13
  * @param {string} baseRef - Base git reference
14
- * @param {string} headRef - Head git reference
14
+ * @param {string} headRef - Head git reference (empty = working directory)
15
15
  * @param {string} workDir - Working directory (optional, defaults to cwd)
16
16
  */
17
17
  static getChangedFiles(baseRef, headRef, workDir = null) {
@@ -23,10 +23,14 @@ export class GitUtils {
23
23
  throw new Error(`Directory does not exist: ${cwd}`);
24
24
  }
25
25
 
26
- const diffCommand = `git diff --name-status ${baseRef}...${headRef}`;
26
+ // If headRef is empty, compare baseRef with working directory
27
+ const diffCommand = headRef
28
+ ? `git diff --name-status ${baseRef}...${headRef}`
29
+ : `git diff --name-status ${baseRef}`;
30
+
27
31
  const diffOutput = execSync(diffCommand, {
28
32
  encoding: 'utf-8',
29
- cwd: cwd // FIXED: Execute git command in the source directory
33
+ cwd: cwd
30
34
  });
31
35
 
32
36
  const changedFiles = [];
@@ -48,7 +52,7 @@ export class GitUtils {
48
52
  console.error('Error getting changed files:', error.message);
49
53
  console.error(' Working directory:', workDir || process.cwd());
50
54
  console.error(' Base ref:', baseRef);
51
- console.error(' Head ref:', headRef);
55
+ console.error(' Head ref:', headRef || '(working directory)');
52
56
  return [];
53
57
  }
54
58
  }
@@ -77,7 +81,7 @@ export class GitUtils {
77
81
  * Get diff between two versions of a file
78
82
  * @param {string} filePath - File path relative to git root (e.g., 'src/modules/file.ts')
79
83
  * @param {string} baseRef - Base git reference
80
- * @param {string} headRef - Head git reference
84
+ * @param {string} headRef - Head git reference (empty = working directory)
81
85
  * @param {string} workDir - Working directory to run git from (optional)
82
86
  */
83
87
  static getFileDiff(filePath, baseRef, headRef, workDir = null) {
@@ -93,9 +97,10 @@ export class GitUtils {
93
97
  return '';
94
98
  }
95
99
 
96
- // filePath is already relative to git root (from git diff --name-status)
97
- // Execute git diff from git root
98
- const diffCommand = `git diff ${baseRef}...${headRef} -- ${filePath}`;
100
+ // If headRef is empty, compare with working directory
101
+ const diffCommand = headRef
102
+ ? `git diff ${baseRef}...${headRef} -- ${filePath}`
103
+ : `git diff ${baseRef} -- ${filePath}`;
99
104
 
100
105
  const result = execSync(diffCommand, {
101
106
  encoding: 'utf-8',
@@ -108,7 +113,7 @@ export class GitUtils {
108
113
  console.error('Error getting file diff:', error.message);
109
114
  console.error(' File:', filePath);
110
115
  console.error(' Base:', baseRef);
111
- console.error(' Head:', headRef);
116
+ console.error(' Head:', headRef || '(working directory)');
112
117
  console.error(' Working dir:', workDir);
113
118
  return '';
114
119
  }
@@ -704,6 +704,7 @@ export class MethodCallGraph {
704
704
  affectedBy: changedMethod,
705
705
  callChain: callChain,
706
706
  layers: this.getCallChainLayers(callChain),
707
+ impactLevel: this.calculateImpactLevel(callChain),
707
708
  });
708
709
  }
709
710
  }
@@ -721,6 +722,7 @@ export class MethodCallGraph {
721
722
  affectedBy: changedMethod,
722
723
  callChain: [changedMethod],
723
724
  layers: [startLayer],
725
+ impactLevel: 'high', // Direct endpoint change is always high impact
724
726
  });
725
727
  }
726
728
 
@@ -793,6 +795,7 @@ export class MethodCallGraph {
793
795
  layers: [this.getMethodLayer(changedMethod), 'Command', this.getMethodLayer(endpointMethod)],
794
796
  viaCommand: commandName,
795
797
  endpointMethod: endpointMethod,
798
+ impactLevel: this.calculateImpactLevel([changedMethod, `Command: '${commandName}'`, endpointMethod]),
796
799
  });
797
800
  }
798
801
  }
@@ -924,4 +927,21 @@ export class MethodCallGraph {
924
927
  .reduce((sum, callers) => sum + callers.length, 0),
925
928
  };
926
929
  }
930
+
931
+ /**
932
+ * Calculate impact level based on call chain length
933
+ * Shorter chain = higher impact (closer to endpoint)
934
+ */
935
+ calculateImpactLevel(callChain) {
936
+ const chainLength = callChain.length;
937
+
938
+ // Direct endpoint change or very short chain
939
+ if (chainLength <= 1) return 'high';
940
+
941
+ // Short chain (2-3 hops)
942
+ if (chainLength <= 3) return 'medium';
943
+
944
+ // Longer chain
945
+ return 'low';
946
+ }
927
947
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sun-asterisk/impact-analyzer",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Automated impact analysis for TypeScript/JavaScript projects",
5
5
  "main": "index.js",
6
6
  "type": "module",