Skip to content

Commit 1d1dd64

Browse files
Fix stage-5 analyzer migration and dedupe duplicate issues
1 parent b7c9588 commit 1d1dd64

4 files changed

Lines changed: 626 additions & 15 deletions

File tree

pipeline/workers/process-module.ts

Lines changed: 90 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { rename, rm } from "node:fs/promises";
44
import { buildModuleAnalysisCacheKey } from "../../scripts/shared/module-analysis-cache.ts";
55
import { createDeterministicImageName } from "../../scripts/shared/deterministic-output.ts";
66
import { createLogger } from "../../scripts/shared/logger.ts";
7+
import { analyzeModule as performModuleAnalysis } from "../../scripts/check-modules/module-analyzer.ts";
78
import fs from "node:fs";
89
import normalizeData from "normalize-package-data";
910
import path from "node:path";
@@ -129,6 +130,28 @@ function getErrorMessage(error: unknown): string {
129130
return error instanceof Error ? error.message : String(error);
130131
}
131132

133+
function normalizeIssueList(issues: unknown): string[] {
134+
if (Array.isArray(issues)) {
135+
return issues.filter((issue): issue is string => typeof issue === "string" && issue.length > 0);
136+
}
137+
138+
if (typeof issues === "string" && issues.length > 0) {
139+
return [issues];
140+
}
141+
142+
return [];
143+
}
144+
145+
function mergeUniqueIssues(target: string[], issues: unknown): void {
146+
const existing = new Set(target);
147+
for (const issue of normalizeIssueList(issues)) {
148+
if (!existing.has(issue)) {
149+
target.push(issue);
150+
existing.add(issue);
151+
}
152+
}
153+
}
154+
132155
/**
133156
* @typedef {Object} ModuleInput
134157
* @property {string} name
@@ -786,16 +809,66 @@ async function enrichModule(module: ModuleInput, config: ProcessModuleConfig): P
786809
}
787810

788811
/**
789-
* Placeholder for future Stage 5 analysis integration
790-
* Will include checks like ESLint, npm-check-updates, dependency detection, etc.
812+
* Stage 5: Analyze module for code quality issues, deprecated patterns, and best practices.
813+
* Runs comprehensive checks including deprecated APIs, typos, package validation, and README structure.
791814
*
792815
* @returns {{analysisIssues: string[], recommendations: string[]}}
793816
*/
794-
function analyzeModule(_module?: ModuleInput, _config?: ProcessModuleConfig): AnalysisResult {
795-
return {
796-
analysisIssues: [],
797-
recommendations: []
798-
};
817+
async function analyzeModule(module: ModuleInput, config: ProcessModuleConfig): Promise<AnalysisResult> {
818+
const cloneDir = path.join(
819+
config.modulesDir,
820+
`${module.name}-----${module.maintainer}`
821+
);
822+
823+
try {
824+
// Get list of all files in the cloned directory, excluding .git and node_modules
825+
const getAllFiles = (dir: string, baseDir: string = dir, files: string[] = []): string[] => {
826+
try {
827+
const entries = fs.readdirSync(dir, { withFileTypes: true });
828+
for (const entry of entries) {
829+
const fullPath = path.join(dir, entry.name);
830+
const relativePath = path.relative(baseDir, fullPath);
831+
832+
if (!relativePath.includes(".git") && !relativePath.includes("node_modules")) {
833+
if (entry.isDirectory()) {
834+
getAllFiles(fullPath, baseDir, files);
835+
} else {
836+
files.push(fullPath);
837+
}
838+
}
839+
}
840+
} catch {
841+
// Silently ignore read errors
842+
}
843+
return files;
844+
};
845+
846+
const files = getAllFiles(cloneDir);
847+
if (files.length === 0) {
848+
return {
849+
analysisIssues: ["Error: Unable to read module files for analysis"],
850+
recommendations: []
851+
};
852+
}
853+
854+
const analysisResult = await performModuleAnalysis(
855+
cloneDir,
856+
module.name,
857+
module.url,
858+
files
859+
);
860+
861+
return {
862+
analysisIssues: analysisResult.issues,
863+
recommendations: analysisResult.recommendations
864+
};
865+
} catch (error) {
866+
const message = error instanceof Error ? error.message : String(error);
867+
return {
868+
analysisIssues: [`Analysis error: ${message}`],
869+
recommendations: []
870+
};
871+
}
799872
}
800873

801874
/**
@@ -810,7 +883,7 @@ function analyzeModule(_module?: ModuleInput, _config?: ProcessModuleConfig): An
810883
*/
811884
export async function processModule(module: ModuleInput, config: ProcessModuleConfig): Promise<ModuleResult> {
812885
const startTime = Date.now();
813-
const allIssues = [...(module.issues || [])];
886+
const allIssues = normalizeIssueList(module.issues);
814887
const cacheKey = config.cacheEnabled
815888
? buildModuleAnalysisCacheKey({
816889
module,
@@ -870,7 +943,7 @@ export async function processModule(module: ModuleInput, config: ProcessModuleCo
870943
let enrichResult;
871944
try {
872945
enrichResult = await enrichModule(module, config);
873-
allIssues.push(...enrichResult.enrichIssues);
946+
mergeUniqueIssues(allIssues, enrichResult.enrichIssues);
874947
}
875948
catch (error) {
876949
const message = error instanceof Error ? error.message : String(error);
@@ -903,20 +976,24 @@ export async function processModule(module: ModuleInput, config: ProcessModuleCo
903976
};
904977
}
905978

906-
// Stage 5: Analyze (placeholder)
979+
// Stage 5: Analyze
907980
let analysisResult;
908981
try {
909982
if (config.moduleLogger) {
910983
await config.moduleLogger.info("analyze", "Starting analysis stage");
911984
}
912985

913986
analysisResult = await analyzeModule(module, config);
914-
allIssues.push(...analysisResult.analysisIssues);
987+
// Merge analysis issues into the issues list
988+
mergeUniqueIssues(allIssues, analysisResult.analysisIssues);
989+
990+
// Add recommendations separately if any
991+
mergeUniqueIssues(allIssues, analysisResult.recommendations);
915992

916993
if (config.moduleLogger) {
917994
await config.moduleLogger.info("analyze", "Analysis complete", {
918-
issuesCount: analysisResult.analysisIssues.length,
919-
recommendationsCount: analysisResult.recommendations.length
995+
issuesCount: analysisResult.analysisIssues?.length || 0,
996+
recommendationsCount: analysisResult.recommendations?.length || 0
920997
});
921998
}
922999
}

0 commit comments

Comments
 (0)