@@ -96,62 +96,84 @@ export async function saveOSPSBaselineInsightsToDB(
9696 const CATALOG_ID = 'osps-baseline-2026-02'
9797 const redisCache = new RedisCache ( `osps-baseline-insights` , svc . redis , svc . log )
9898 const result = await redisCache . get ( key )
99+ if ( ! result ) {
100+ throw new Error ( `No cached privateer result found for key: ${ key } ` )
101+ }
99102 const parsedResult : ISecurityInsightsPrivateerResult = JSON . parse ( result )
100- const evaluationSuite = parsedResult . evaluation_suites . find ( ( s ) => s . catalog_id === CATALOG_ID )
103+ const evaluationSuite = parsedResult [ 'evaluation-suites' ] ?. find (
104+ ( s ) => s [ 'catalog-id' ] === CATALOG_ID ,
105+ )
106+ if ( ! evaluationSuite ) {
107+ throw new Error (
108+ `No evaluation suite found for catalog '${ CATALOG_ID } ' in privateer output for repo ${ repo . repoUrl } ` ,
109+ )
110+ }
101111
102112 const qx = pgpQx ( svc . postgres . writer . connection ( ) )
103113
104114 await addEvaluationSuite ( qx , {
105115 repo : repo . repoUrl ,
106116 insightsProjectId : repo . insightsProjectId ,
107117 insightsProjectSlug : repo . insightsProjectSlug ,
108- catalogId : evaluationSuite . catalog_id ,
118+ catalogId : evaluationSuite [ 'catalog-id' ] ,
109119 name : evaluationSuite . name ,
110120 result : evaluationSuite . result ,
111- corruptedState : evaluationSuite . corrupted_state ,
121+ corruptedState : evaluationSuite [ 'corrupted-state' ] ,
112122 } )
113123
114- const suite = await findEvaluationSuite ( qx , repo . repoUrl , evaluationSuite . catalog_id )
124+ const suite = await findEvaluationSuite ( qx , repo . repoUrl , evaluationSuite [ 'catalog-id' ] )
125+ if ( ! suite ) {
126+ throw new Error (
127+ `Evaluation suite not found after insert for repo ${ repo . repoUrl } , catalog ${ evaluationSuite [ 'catalog-id' ] } ` ,
128+ )
129+ }
115130
116- for ( const evaluation of evaluationSuite . control_evaluations ) {
131+ for ( const evaluation of evaluationSuite [ 'control-evaluations' ] . evaluations ) {
132+ const controlId = evaluation . control [ 'entry-id' ]
117133 await addSuiteControlEvaluation ( qx , {
118- controlId : evaluation [ 'control-id' ] ,
134+ controlId,
119135 name : evaluation . name ,
120- corruptedState : evaluation [ 'corrupted-state' ] ,
136+ corruptedState : false ,
121137 message : evaluation . message ,
122138 repo : repo . repoUrl ,
123139 insightsProjectId : repo . insightsProjectId ,
124140 insightsProjectSlug : repo . insightsProjectSlug ,
125- remediationGuide : evaluation [ 'remediation-guide' ] || '' ,
141+ remediationGuide : '' ,
126142 result : evaluation . result ,
127143 securityInsightsEvaluationSuiteId : suite . id ,
128144 } )
129145
130146 const controlEvaluation = await findSuiteControlEvaluation (
131147 qx ,
132148 repo . repoUrl ,
133- evaluation [ 'control-id' ] ,
149+ controlId ,
134150 suite . id ,
135151 )
136- for ( const assessment of evaluation . assessments ) {
152+ if ( ! controlEvaluation ) {
153+ throw new Error (
154+ `Control evaluation not found after insert for repo ${ repo . repoUrl } , controlId ${ controlId } , suiteId ${ suite . id } ` ,
155+ )
156+ }
157+ for ( const assessment of evaluation [ 'assessment-logs' ] ) {
158+ const runDuration = computeRunDuration ( assessment . start , assessment . end )
137159 await addControlEvaluationAssessment ( qx , {
138160 applicability : assessment . applicability ,
139161 description : assessment . description ,
140162 message : assessment . message ,
141163 repo : repo . repoUrl ,
142164 insightsProjectId : repo . insightsProjectId ,
143165 insightsProjectSlug : repo . insightsProjectSlug ,
144- requirementId : assessment [ 'requirement -id'] ,
166+ requirementId : assessment . requirement [ 'entry -id'] ,
145167 result : assessment . result ,
146- runDuration : assessment [ 'run-duration' ] || '' ,
168+ runDuration,
147169 steps : assessment . steps ,
148170 stepsExecuted : assessment [ 'steps-executed' ] || 0 ,
149171 securityInsightsEvaluationId : controlEvaluation . id ,
150172 recommendation : assessment . recommendation ,
151173 start : assessment . start ,
152174 end : assessment . end ,
153- value : assessment . value ,
154- changes : assessment . changes ,
175+ value : null ,
176+ changes : null ,
155177 } )
156178 }
157179 }
@@ -174,6 +196,14 @@ export async function saveOSPSBaselineInsightsToRedis(
174196 await redisCache . set ( key , JSON . stringify ( insights ) , 60 * 60 * 24 ) // 1 day
175197}
176198
199+ function computeRunDuration ( start : string | undefined , end : string | undefined ) : string {
200+ if ( ! start || ! end ) return ''
201+ const startMs = new Date ( start ) . getTime ( )
202+ const endMs = new Date ( end ) . getTime ( )
203+ if ( isNaN ( startMs ) || isNaN ( endMs ) || endMs < startMs ) return ''
204+ return `${ endMs - startMs } ms`
205+ }
206+
177207async function cleanupFiles ( repoName : string ) : Promise < void > {
178208 // Delete the file
179209 try {
@@ -221,11 +251,22 @@ async function runBinary(
221251 } )
222252
223253 proc . on ( 'close' , ( code ) => {
224- if ( code === 0 ) {
225- svc . log . info ( `Binary completed successfully` )
254+ // exit code 0 = all tests passed, 1 = some tests failed — both mean the
255+ // evaluation ran to completion and wrote its output file
256+ if ( code === 0 || code === 1 ) {
257+ svc . log . info ( `Binary completed with exit code ${ code } ` )
226258 resolve ( { stdout, stderr } )
227259 } else {
228- reject ( new Error ( `Binary exited with code ${ code } \nStderr:\n${ stderr } Stdout:\n${ stdout } ` ) )
260+ const truncated = ( s : string ) => ( s . length > 500 ? s . slice ( 0 , 500 ) + '…' : s )
261+ const truncStdout = truncated ( stdout )
262+ const truncStderr = truncated ( stderr )
263+ const err = Object . assign (
264+ new Error (
265+ `Binary exited with code ${ code } \nStderr:\n${ truncStderr } \nStdout:\n${ truncStdout } ` ,
266+ ) ,
267+ { stdout : truncStdout , stderr : truncStderr } ,
268+ )
269+ reject ( err )
229270 }
230271 } )
231272 } )
0 commit comments