diff --git a/src/functions/prompts-to-test-spec/src/index.ts b/src/functions/prompts-to-test-spec/src/index.ts index c5825da..538ec9a 100644 --- a/src/functions/prompts-to-test-spec/src/index.ts +++ b/src/functions/prompts-to-test-spec/src/index.ts @@ -1,6 +1,7 @@ import {CloudEvent, cloudEvent, http} from '@google-cloud/functions-framework'; import { ProcessorService } from './services/processor-service'; import { validateConfig, DRY_RUN_SKIP_GEMINI, DRY_RUN_SKIP_COMMITS } from './config'; +import { ProcessResult, HttpResponse, ProjectSummary } from './types'; // Validate configuration on startup try { @@ -29,8 +30,9 @@ if (isRunningDirectly) { const processor = new ProcessorService(); console.log('Processing projects...'); const results = await processor.processProjects(); + const formattedResults = formatHttpResponse(results); console.log('Processing completed successfully'); - console.log('Results:', JSON.stringify(results, null, 2)); + console.log('Results:', JSON.stringify(formattedResults, null, 2)); } catch (error) { console.error('Error processing projects:', error); process.exit(1); @@ -38,6 +40,47 @@ if (isRunningDirectly) { })(); } +/** + * Format process results into a concise HTTP response + * @param results Process results from the processor service + * @returns Formatted HTTP response + */ +export function formatHttpResponse(results: ProcessResult[]): HttpResponse { + // Count successful and failed projects + const projectsSucceeded = results.filter(r => !r.error).length; + const projectsFailed = results.filter(r => !!r.error).length; + + // Find main PR URL if any + const mainPullRequestUrl = results.find(r => r.pullRequestUrl)?.pullRequestUrl; + + // Format project summaries + const projects: ProjectSummary[] = results.map(result => { + // Count workitems + const workitemsProcessed = result.processedWorkitems.length; + const workitemsSkipped = result.processedWorkitems.filter(w => !w.workitem.isActive).length; + const workitemsUpdated = result.processedWorkitems.filter(w => w.success).length; + + return { + name: result.project.name, + success: !result.error, + error: result.error, + workitemsProcessed, + workitemsSkipped, + workitemsUpdated, + pullRequestUrl: result.pullRequestUrl + }; + }); + + return { + success: projectsFailed === 0, + projectsProcessed: results.length, + projectsSucceeded, + projectsFailed, + mainPullRequestUrl, + projects + }; +} + /** * HTTP endpoint for the prompts-to-test-spec function */ @@ -45,16 +88,19 @@ http('promptToTestSpecHttp', async (req, res): Promise => { try { const processor = new ProcessorService(); const results = await processor.processProjects(); + const response = formatHttpResponse(results); - res.status(200).json({ - success: true, - results - }); + res.status(200).json(response); } catch (error) { console.error('Error processing projects:', error); + const errorMessage = error instanceof Error ? error.message : String(error); res.status(500).json({ success: false, - error: error instanceof Error ? error.message : String(error) + projectsProcessed: 0, + projectsSucceeded: 0, + projectsFailed: 1, + projects: [], + error: errorMessage }); } }); diff --git a/src/functions/prompts-to-test-spec/src/services/__tests__/index.test.ts b/src/functions/prompts-to-test-spec/src/services/__tests__/index.test.ts new file mode 100644 index 0000000..81b8e44 --- /dev/null +++ b/src/functions/prompts-to-test-spec/src/services/__tests__/index.test.ts @@ -0,0 +1,137 @@ +import { formatHttpResponse } from '../../index'; +import { ProcessResult, HttpResponse } from '../../types'; + +describe('formatHttpResponse', () => { + it('should format process results into a concise HTTP response', () => { + // Create test data + const processResults: ProcessResult[] = [ + { + project: { + name: 'project1', + path: '/path/to/project1', + repoHost: 'https://github.com', + repoUrl: 'https://github.com/org/project1.git' + }, + processedWorkitems: [ + { + workitem: { + name: 'workitem1', + path: '/path/to/workitem1.md', + title: 'Workitem 1', + description: 'Description 1', + isActive: true + }, + success: true + }, + { + workitem: { + name: 'workitem2', + path: '/path/to/workitem2.md', + title: 'Workitem 2', + description: 'Description 2', + isActive: false + }, + success: true + } + ], + pullRequestUrl: 'https://github.com/org/project1/pull/123' + }, + { + project: { + name: 'project2', + path: '/path/to/project2', + repoHost: 'https://github.com', + repoUrl: 'https://github.com/org/project2.git' + }, + processedWorkitems: [ + { + workitem: { + name: 'workitem3', + path: '/path/to/workitem3.md', + title: 'Workitem 3', + description: 'Description 3', + isActive: true + }, + success: false, + error: 'Failed to process workitem' + } + ], + error: 'Failed to process project' + } + ]; + + // Call the function + const response = formatHttpResponse(processResults); + + // Verify the response + expect(response).toEqual({ + success: false, + projectsProcessed: 2, + projectsSucceeded: 1, + projectsFailed: 1, + mainPullRequestUrl: 'https://github.com/org/project1/pull/123', + projects: [ + { + name: 'project1', + success: true, + workitemsProcessed: 2, + workitemsSkipped: 1, + workitemsUpdated: 2, + pullRequestUrl: 'https://github.com/org/project1/pull/123' + }, + { + name: 'project2', + success: false, + error: 'Failed to process project', + workitemsProcessed: 1, + workitemsSkipped: 0, + workitemsUpdated: 0 + } + ] + }); + }); + + it('should handle empty results', () => { + const response = formatHttpResponse([]); + + expect(response).toEqual({ + success: true, + projectsProcessed: 0, + projectsSucceeded: 0, + projectsFailed: 0, + mainPullRequestUrl: undefined, + projects: [] + }); + }); + + it('should handle results with no pull request URLs', () => { + const processResults: ProcessResult[] = [ + { + project: { + name: 'project1', + path: '/path/to/project1' + }, + processedWorkitems: [] + } + ]; + + const response = formatHttpResponse(processResults); + + expect(response).toEqual({ + success: true, + projectsProcessed: 1, + projectsSucceeded: 1, + projectsFailed: 0, + mainPullRequestUrl: undefined, + projects: [ + { + name: 'project1', + success: true, + workitemsProcessed: 0, + workitemsSkipped: 0, + workitemsUpdated: 0 + } + ] + }); + }); +}); diff --git a/src/functions/prompts-to-test-spec/src/types.ts b/src/functions/prompts-to-test-spec/src/types.ts index 3dc69a2..1a23ce1 100644 --- a/src/functions/prompts-to-test-spec/src/types.ts +++ b/src/functions/prompts-to-test-spec/src/types.ts @@ -38,3 +38,29 @@ export interface ProcessResult { pullRequestUrl?: string; error?: string; } + +/** + * HTTP response format for the API + */ +export interface HttpResponse { + success: boolean; + projectsProcessed: number; + projectsSucceeded: number; + projectsFailed: number; + mainPullRequestUrl?: string; + projects: ProjectSummary[]; + error?: string; +} + +/** + * Summary of a project's processing results + */ +export interface ProjectSummary { + name: string; + success: boolean; + error?: string; + workitemsProcessed: number; + workitemsSkipped: number; + workitemsUpdated: number; + pullRequestUrl?: string; +}