@@ -149,6 +149,14 @@ def notifyAnsibleStart(channels: list[str], taskName: str, instanceId: str | Non
149149 SlackUtil .buildSection (f"⏳ **{ taskName } ** - Started" )
150150 ]
151151 response = SlackUtil .postMessageBlocks (channelId , taskMessage , threadId )
152+
153+ # Save message timestamp in ConfigMap for later editing
154+ if response .data .get ("ok" , False ):
155+ messageTs = response .data .get ("ts" )
156+ if messageTs :
157+ # Store with task name as key
158+ SlackUtil .updateThreadConfigMap (namespace , instanceId , {f"task_{ taskName } " : messageTs })
159+
152160 if isinstance (response , list ):
153161 return all ([res .data .get ("ok" , False ) for res in response ])
154162 return response .data .get ("ok" , False )
@@ -166,24 +174,61 @@ def notifyAnsibleComplete(channels: list[str], rc: int, taskName: str, instanceI
166174 if threadInfo is None :
167175 print ("No thread found - creating pipeline start notification" )
168176 threadInfo = notifyPipelineStart (channels , instanceId , pipelineName )
169- # Send task completion message as thread reply
177+
170178 threadId = threadInfo .get ("threadId" )
171179 channelId = threadInfo .get ("channelId" )
180+
181+ # Get the message timestamp for this task
182+ taskMessageTs = threadInfo .get (f"task_{ taskName } " )
183+
184+ # Determine status
172185 if rc == 0 :
173186 emoji = "✅"
174187 status = "Success"
175188 else :
176189 emoji = "❌"
177190 status = "Failed"
191+
192+ # Calculate task duration if we have the message timestamp
193+ durationText = ""
194+ if taskMessageTs :
195+ from datetime import datetime
196+ try :
197+ # Message timestamp is in format "1234567890.123456"
198+ startTime = float (taskMessageTs )
199+ endTime = datetime .utcnow ().timestamp ()
200+ duration = int (endTime - startTime )
201+
202+ hours , remainder = divmod (duration , 3600 )
203+ minutes , seconds = divmod (remainder , 60 )
204+
205+ if hours > 0 :
206+ durationText = f" ({ hours } h { minutes } m { seconds } s)"
207+ elif minutes > 0 :
208+ durationText = f" ({ minutes } m { seconds } s)"
209+ else :
210+ durationText = f" ({ seconds } s)"
211+ except Exception as e :
212+ print (f"Failed to calculate duration: { e } " )
213+
214+ # Build the completion message
178215 taskMessage = [
179- SlackUtil .buildSection (f"{ emoji } **{ taskName } ** - { status } " )
216+ SlackUtil .buildSection (f"{ emoji } **{ taskName } ** - { status } { durationText } " )
180217 ]
181218 if rc != 0 :
182219 taskMessage .append (SlackUtil .buildSection (f"Return Code: `{ rc } `\n Check logs for details" ))
183- response = SlackUtil .postMessageBlocks (channelId , taskMessage , threadId )
184- if isinstance (response , list ):
185- return all ([res .data .get ("ok" , False ) for res in response ])
186- return response .data .get ("ok" , False )
220+
221+ # If we have the original message timestamp, update it; otherwise post new message
222+ if taskMessageTs :
223+ response = SlackUtil .updateMessageBlocks (channelId , taskMessageTs , taskMessage )
224+ return response .data .get ("ok" , False )
225+ else :
226+ # Fallback: post new message if task start message wasn't tracked
227+ print (f"No start message found for task { taskName } , posting new completion message" )
228+ response = SlackUtil .postMessageBlocks (channelId , taskMessage , threadId )
229+ if isinstance (response , list ):
230+ return all ([res .data .get ("ok" , False ) for res in response ])
231+ return response .data .get ("ok" , False )
187232
188233
189234def notifyPipelineComplete (channels : list [str ], rc : int , instanceId : str | None = None , pipelineName : str | None = None ) -> bool :
0 commit comments