@@ -270,4 +270,197 @@ def find_existing_bot_comment(repo_owner, repo_name, pr_number, bot_comment_base
270270            return  comment ['id' ]
271271
272272    print ("No existing bot comment found" )
273-     return  None 
273+     return  None 
274+ 
275+ def  create_commit_with_marker_for_suggestion (repo_owner , repo_name , pr_number , xml_file , line_number , github_token ):
276+     """Create a minimal commit that adds the XML file to PR changes to enable suggestions""" 
277+     print (f"Creating minimal commit to enable suggestions on { xml_file }  )
278+     
279+     headers  =  {
280+         'Accept' : 'application/vnd.github+json' ,
281+         'Authorization' : f'token { github_token }  
282+     }
283+     
284+     # Get PR info to get the branch 
285+     pr_info  =  get_pr_info (repo_owner , repo_name , pr_number , github_token )
286+     if  not  pr_info :
287+         return  False 
288+         
289+     branch_name  =  pr_info ['head' ]['ref' ]
290+     head_sha  =  pr_info ['head' ]['sha' ]
291+     
292+     print (f"Target branch: { branch_name }  )
293+     print (f"Current head: { head_sha }  )
294+     
295+     # Get current file content 
296+     file_content  =  get_file_content (repo_owner , repo_name , xml_file , head_sha , github_token )
297+     if  not  file_content :
298+         print (f"❌ Could not get content for { xml_file }  )
299+         return  False 
300+     
301+     # Get the current file SHA (required for updates) 
302+     file_url  =  f"https://api.github.com/repos/{ repo_owner } { repo_name } { xml_file } { head_sha }  
303+     response  =  requests .get (file_url , headers = headers )
304+     
305+     if  response .status_code  !=  200 :
306+         print (f"❌ Could not get file SHA: { response .status_code }  )
307+         return  False 
308+         
309+     file_sha  =  response .json ().get ('sha' )
310+     
311+     # Add a minimal comment to the line that will be suggested 
312+     lines  =  file_content .split ('\n ' )
313+     if  line_number  <=  len (lines ):
314+         # Add a comment at the end of the target line 
315+         target_line  =  lines [line_number  -  1 ]  # Convert to 0-based index 
316+         
317+         # Check if comment already exists 
318+         if  '<!-- calibration-update-marker -->'  not  in target_line :
319+             lines [line_number  -  1 ] =  target_line  +  ' <!-- calibration-update-marker -->' 
320+             updated_content  =  '\n ' .join (lines )
321+             
322+             print (f"Adding marker comment to line { line_number }  )
323+             
324+             # Create the commit 
325+             commit_data  =  {
326+                 'message' : '[skip ci] Add calibration update marker\n \n Minimal change to enable calibration suggestions.' ,
327+                 'content' : base64 .b64encode (updated_content .encode ()).decode (),
328+                 'sha' : file_sha ,
329+                 'branch' : branch_name 
330+             }
331+             
332+             commit_url  =  f"https://api.github.com/repos/{ repo_owner } { repo_name } { xml_file }  
333+             response  =  requests .put (commit_url , headers = headers , json = commit_data )
334+             
335+             if  response .status_code  in  [200 , 201 ]:
336+                 print ("✅ Minimal commit created successfully" )
337+                 return  True 
338+             else :
339+                 print (f"❌ Failed to create minimal commit: { response .status_code }  )
340+                 print (f"   Response: { response .text }  )
341+                 return  False 
342+         else :
343+             print ("ℹ️ Marker comment already exists" )
344+             return  True 
345+     else :
346+         print (f"❌ Line number { line_number }  )
347+         return  False 
348+ 
349+ def  create_pr_suggestion_with_prep (repo_owner , repo_name , pr_number , calibration_file , xml_file , new_url , github_token ):
350+     """Create PR suggestion with preparation if needed""" 
351+     print (f"Creating PR suggestion with preparation for #{ pr_number }  )
352+     
353+     # Get current PR info 
354+     pr_info  =  get_pr_info (repo_owner , repo_name , pr_number , github_token )
355+     if  not  pr_info :
356+         return  False 
357+     
358+     head_sha  =  pr_info ['head' ]['sha' ]
359+     
360+     # Get file content and find the line to update 
361+     file_content  =  get_file_content (repo_owner , repo_name , xml_file , head_sha , github_token )
362+     if  not  file_content :
363+         return  False 
364+     
365+     line_number , suggested_line  =  find_and_update_epic_fileloader_url (file_content , calibration_file , new_url )
366+     if  not  line_number  or  not  suggested_line :
367+         print (f"❌ Could not find calibration line to update in { xml_file }  )
368+         return  False 
369+     
370+     # Check if XML file is already in the PR changes 
371+     headers  =  {
372+         'Accept' : 'application/vnd.github+json' ,
373+         'Authorization' : f'token { github_token }  
374+     }
375+     
376+     files_url  =  f"https://api.github.com/repos/{ repo_owner } { repo_name } { pr_number }  
377+     response  =  requests .get (files_url , headers = headers )
378+     
379+     if  response .status_code  ==  200 :
380+         changed_files  =  response .json ()
381+         file_paths  =  [f ['filename' ] for  f  in  changed_files ]
382+         
383+         if  xml_file  not  in file_paths :
384+             print (f"📝 { xml_file }  )
385+             
386+             # Create minimal commit to add file to PR 
387+             success  =  create_commit_with_marker_for_suggestion (repo_owner , repo_name , pr_number , xml_file , line_number , github_token )
388+             
389+             if  not  success :
390+                 print ("❌ Failed to create minimal commit, falling back to regular comment" )
391+                 return  create_pr_comment_fallback (repo_owner , repo_name , pr_number , calibration_file , new_url , github_token )
392+             
393+             # Wait a moment for GitHub to process the commit 
394+             import  time 
395+             time .sleep (3 )
396+             
397+             # Get updated PR info with new head SHA 
398+             pr_info  =  get_pr_info (repo_owner , repo_name , pr_number , github_token )
399+             if  not  pr_info :
400+                 return  False 
401+                 
402+             head_sha  =  pr_info ['head' ]['sha' ]
403+             
404+             # Get updated file content (now with the marker comment) 
405+             file_content  =  get_file_content (repo_owner , repo_name , xml_file , head_sha , github_token )
406+             if  not  file_content :
407+                 return  False 
408+             
409+             # Re-find the line (it should be the same, but content is slightly different) 
410+             line_number , suggested_line  =  find_and_update_epic_fileloader_url (file_content , calibration_file , new_url )
411+             if  not  line_number  or  not  suggested_line :
412+                 print (f"❌ Could not find calibration line after minimal commit" )
413+                 return  False 
414+             
415+             # Remove the marker comment from the suggested line 
416+             suggested_line  =  suggested_line .replace (' <!-- calibration-update-marker -->' , '' )
417+             
418+             print (f"✅ XML file now in PR changes, proceeding with suggestion" )
419+         else :
420+             print (f"✅ { xml_file }  )
421+     else :
422+         print (f"❌ Could not get PR files: { response .status_code }  )
423+         return  False 
424+     
425+     # Now create the proper code suggestion 
426+     return  create_pr_suggestion (repo_owner , repo_name , pr_number , calibration_file ,
427+                               xml_file , line_number , suggested_line , head_sha , github_token )
428+ 
429+ def  create_pr_comment_fallback (repo_owner , repo_name , pr_number , calibration_file , new_url , github_token ):
430+     """Fallback: Create a regular PR comment when suggestions aren't possible""" 
431+     print (f"Creating fallback PR comment..." )
432+     
433+     headers  =  {
434+         'Accept' : 'application/vnd.github+json' ,
435+         'Authorization' : f'token { github_token }  
436+     }
437+     
438+     timestamp  =  datetime .now (timezone .utc ).strftime ("%Y-%m-%d %H:%M:%S UTC" )
439+     
440+     comment_body  =  f"""🤖 **Automated Calibration `{ calibration_file }  
441+ 
442+ A new calibration has been generated and is ready for use. 
443+ 
444+ **New URL:** `{ new_url }  
445+ **Last updated:** { timestamp }  
446+ 
447+ **Manual Update Required:** 
448+ Please update the XML configuration to use the new calibration URL. 
449+ 
450+ ```xml 
451+ url:{ new_url }  
452+ ``` 
453+ 
454+ Look for the existing `{ Path (calibration_file ).name }  
455+     
456+     comment_url  =  f"https://api.github.com/repos/{ repo_owner } { repo_name } { pr_number }  
457+     comment_data  =  {'body' : comment_body }
458+     
459+     response  =  requests .post (comment_url , headers = headers , json = comment_data )
460+     
461+     if  response .status_code  ==  201 :
462+         print ("✅ Fallback PR comment created successfully" )
463+         return  response .json ()
464+     else :
465+         print (f"❌ Failed to create fallback comment: { response .status_code }  )
466+         return  None 
0 commit comments