Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 12 additions & 37 deletions backend/src/build-system/__tests__/fullstack-gen.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { isIntegrationTest } from 'src/common/utils';
import { BuildSequence } from '../types';
import { executeBuildSequence } from './utils';
import { Logger } from '@nestjs/common';
import { ProjectInitHandler } from '../handlers/project-init';
import { PRDHandler } from '../handlers/product-manager/product-requirements-document/prd';
import { UXSMDHandler } from '../handlers/ux/sitemap-document';
Expand All @@ -14,6 +12,9 @@ import { FileFAHandler } from '../handlers/file-manager/file-arch';
import { BackendRequirementHandler } from '../handlers/backend/requirements-document';
import { BackendCodeHandler } from '../handlers/backend/code-generate';
import { BackendFileReviewHandler } from '../handlers/backend/file-review/file-review';
import { UXDMDHandler } from '../handlers/ux/datamap';
import { BuilderContext } from '../context';
import { FrontendCodeHandler } from '../handlers/frontend-code-generate';

(isIntegrationTest ? describe : describe.skip)('Build Sequence Test', () => {
it('should execute build sequence successfully', async () => {
Expand Down Expand Up @@ -42,22 +43,8 @@ import { BackendFileReviewHandler } from '../handlers/backend/file-review/file-r
// requires: ['op:UX:SMD'],
},
{
handler: DBRequirementHandler,
name: 'Database Requirements Node',
// requires: ['op:UX:DATAMAP:DOC'],
},
{
handler: FileStructureHandler,
name: 'File Structure Generation',
// requires: ['op:UX:SMD', 'op:UX:DATAMAP:DOC'],
options: {
projectPart: 'frontend',
},
},
{
handler: UXSMSPageByPageHandler,
name: 'Level 2 UX Sitemap Structure Node details',
// requires: ['op:UX:SMS'],
handler: UXDMDHandler,
name: 'UX DataMap Document Node',
},
{
handler: DBRequirementHandler,
Expand Down Expand Up @@ -95,30 +82,18 @@ import { BackendFileReviewHandler } from '../handlers/backend/file-review/file-r
{
handler: BackendCodeHandler,
name: 'Backend Code Generator Node',
// requires: [
// 'op:DATABASE:SCHEMAS',
// 'op:UX:DATAMAP:DOC',
// 'op:BACKEND:REQ',
// ],
},
// {
// handler:FrontendCodeHandler,
// id: 'op:FRONTEND:CODE',
// name: 'Frontend Code Generator Node',
// },
{
handler: BackendFileReviewHandler,
name: 'Backend File Review Node',
// requires: ['op:BACKEND:CODE', 'op:BACKEND:REQ'],
},
{
handler: FrontendCodeHandler,
name: 'Frontend Code Generator Node',
},
],
};

const result = await executeBuildSequence('fullstack-code-gen', sequence);

// Assertion: ensure the build sequence runs successfully
expect(result.success).toBe(true);
expect(result.metrics).toBeDefined();
Logger.log(`Logs saved to: ${result.logFolderPath}`);
}, 300000); // Set timeout to 5 minutes
const context = new BuilderContext(sequence, 'fullstack-code-gen');
await context.execute();
}, 300000);
});
115 changes: 6 additions & 109 deletions backend/src/build-system/__tests__/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Logger } from '@nestjs/common';
import * as fs from 'fs';
import * as path from 'path';
import { BuildSequence, BuildHandlerConstructor } from '../types';
import { BuildSequence } from '../types';
import { BuilderContext } from '../context';
import { BuildMonitor } from '../monitor';

Expand Down Expand Up @@ -87,115 +87,12 @@
fs.mkdirSync(logFolderPath, { recursive: true });

const context = new BuilderContext(sequence, 'test-env');
const monitor = BuildMonitor.getInstance();

Check warning on line 90 in backend/src/build-system/__tests__/utils.ts

View workflow job for this annotation

GitHub Actions / autofix

'monitor' is assigned a value but never used. Allowed unused vars must match /^_/u

try {
console.time('Total Execution Time');
await context.execute();
console.timeEnd('Total Execution Time');

const monitorReport = monitor.generateTextReport(sequence.id);
fs.writeFileSync(
path.join(logFolderPath, 'execution-metrics.txt'),
monitorReport,
'utf8',
);

const sequenceMetrics = monitor.getSequenceMetrics(sequence.id);
if (sequenceMetrics) {
const metricsJson = {
totalDuration: `${sequenceMetrics.duration}ms`,
successRate: `${sequenceMetrics.successRate.toFixed(2)}%`,
totalNodes: sequenceMetrics.totalNodes,
completedNodes: sequenceMetrics.completedNodes,
failedNodes: sequenceMetrics.failedNodes,
startTime: new Date(sequenceMetrics.startTime).toISOString(),
endTime: new Date(sequenceMetrics.endTime).toISOString(),
};

fs.writeFileSync(
path.join(logFolderPath, 'metrics.json'),
JSON.stringify(metricsJson, null, 2),
'utf8',
);

Logger.log('\nSequence Metrics:');
console.table(metricsJson);
}

// Log node results
for (const node of sequence.nodes) {
const handlerClass = node.handler as BuildHandlerConstructor;
const resultData = context.getNodeData(handlerClass);
const nodeMetrics = sequenceMetrics?.nodeMetrics.get(handlerClass.name);

if (resultData) {
const content =
typeof resultData === 'object'
? objectToMarkdown(resultData)
: resultData;
writeToFile(logFolderPath, node.name || handlerClass.name, content);
} else {
Logger.error(
`Error: Handler ${node.name || handlerClass.name} failed to produce result data`,
);
writeToFile(
logFolderPath,
`${node.name || handlerClass.name}-error`,
objectToMarkdown({
error: 'No result data',
metrics: nodeMetrics,
}),
);
}
}

const summary = {
timestamp: new Date().toISOString(),
sequenceId: sequence.id,
sequenceName: sequence.name,
totalExecutionTime: `${sequenceMetrics?.duration}ms`,
successRate: `${sequenceMetrics?.successRate.toFixed(2)}%`,
totalNodes: sequenceMetrics?.totalNodes,
completedNodes: sequenceMetrics?.completedNodes,
logFolder: logFolderPath,
};

fs.writeFileSync(
path.join(logFolderPath, 'execution-summary.json'),
JSON.stringify(summary, null, 2),
'utf8',
);

return {
success: true,
logFolderPath,
metrics: sequenceMetrics,
};
} catch (error) {
const errorReport = {
error: {
message: error.message,
stack: error.stack,
},
metrics: monitor.getSequenceMetrics(sequence.id),
timestamp: new Date().toISOString(),
};

fs.writeFileSync(
path.join(logFolderPath, 'error-with-metrics.json'),
JSON.stringify(errorReport, null, 2),
'utf8',
);
await context.execute();

Logger.error('\nError during sequence execution:');
Logger.error(error);

return {
success: false,
logFolderPath,
error: error as Error,
metrics: monitor.getSequenceMetrics(sequence.id),
};
}
return {
success: true,
logFolderPath: '',
};
}
Loading
Loading