@@ -129,19 +129,43 @@ var _ = ginkgo.Describe("Ad Hoc Test Images", ginkgo.Ordered, ginkgo.ContinueOnF
129129 }
130130 }
131131
132- if len (allFailures ) > 0 && viper . GetBool ( config . LogAnalysis . EnableAnalysis ) {
132+ if len (allFailures ) > 0 {
133133 combinedErr := fmt .Errorf ("failures in %s: %s" , testImage , strings .Join (allFailures , "; " ))
134- runLogAnalysisForAdHocTestImage (ctx , logger , testSuite , combinedErr , exeConfig .OutputDir )
134+ var analysisContent string
135+ if viper .GetBool (config .LogAnalysis .EnableAnalysis ) {
136+ analysisContent = runLogAnalysisForAdHocTestImage (ctx , logger , testSuite , combinedErr , exeConfig .OutputDir )
137+ }
138+ queueNotification (testSuite , analysisContent )
135139 }
136140 },
137141 testImageEntries )
138142})
139143
140- // runLogAnalysisForAdHocTestImage runs AI analysis and queues the result for
141- // deferred Slack delivery. The engine runs without sending notifications because
142- // S3 artifacts have not been uploaded yet at this point. The queued result is
143- // later sent by Report after S3 upload populates presigned URLs.
144- func runLogAnalysisForAdHocTestImage (ctx context.Context , logger logr.Logger , testSuite config.TestSuite , err error , artifactsDir string ) {
144+ // queueNotification adds a PendingNotification for deferred Slack delivery.
145+ // Called directly when log analysis is disabled so notifications are still sent.
146+ func queueNotification (testSuite config.TestSuite , analysisContent string ) {
147+ clusterInfo := & analysisengine.ClusterInfo {
148+ ID : viper .GetString (config .Cluster .ID ),
149+ Name : viper .GetString (config .Cluster .Name ),
150+ Provider : viper .GetString (config .Provider ),
151+ Region : viper .GetString (config .CloudProvider .Region ),
152+ CloudProvider : viper .GetString (config .CloudProvider .CloudProviderID ),
153+ Version : viper .GetString (config .Cluster .Version ),
154+ }
155+ pendingMu .Lock ()
156+ pendingNotifications = append (pendingNotifications , PendingNotification {
157+ AnalysisContent : analysisContent ,
158+ TestSuite : testSuite ,
159+ ClusterInfo : clusterInfo ,
160+ Env : viper .GetString (ocmprovider .Env ),
161+ })
162+ pendingMu .Unlock ()
163+ }
164+
165+ // runLogAnalysisForAdHocTestImage runs AI analysis and returns the result content.
166+ // Returns an empty string if analysis fails. The caller is responsible for
167+ // queuing the notification via queueNotification.
168+ func runLogAnalysisForAdHocTestImage (ctx context.Context , logger logr.Logger , testSuite config.TestSuite , err error , artifactsDir string ) string {
145169 logger .Info ("Running Log analysis for test image" , "image" , testSuite .Image , "slackChannel" , testSuite .SlackChannel )
146170
147171 clusterInfo := & analysisengine.ClusterInfo {
@@ -166,24 +190,17 @@ func runLogAnalysisForAdHocTestImage(ctx context.Context, logger logr.Logger, te
166190 engine , err := analysisengine .New (ctx , engineConfig )
167191 if err != nil {
168192 logger .Error (err , "Unable to create analysis engine for image" , "image" , testSuite .Image )
169- return
193+ return ""
170194 }
171195
172196 result , runErr := engine .Run (ctx )
173197 if runErr != nil {
174198 logger .Error (runErr , "Log analysis failed for image" , "image" , testSuite .Image )
175- return
199+ return ""
176200 }
177201
178202 logger .Info ("Log analysis completed successfully" , "image" , testSuite .Image , "resultsDir" , fmt .Sprintf ("%s/%s/" , artifactsDir , analysisengine .AnalysisDirName ))
179203 log .Printf ("=== Log Analysis Result for %s ===\n %s" , testSuite .Image , result .Content )
180204
181- pendingMu .Lock ()
182- pendingNotifications = append (pendingNotifications , PendingNotification {
183- AnalysisContent : result .Content ,
184- TestSuite : testSuite ,
185- ClusterInfo : clusterInfo ,
186- Env : viper .GetString (ocmprovider .Env ),
187- })
188- pendingMu .Unlock ()
205+ return result .Content
189206}
0 commit comments