5151 "human-intervention-logs" ,
5252 "forge/human-intervention-logs" ,
5353)
54+ MAX_PR_BODY_CHARS : int = 60_000
55+ MAX_INLINE_TEST_DIFF_CHARS : int = 12_000
56+ PR_BODY_REQUIRED_TAIL_CHARS : int = 12_000
5457
5558
5659def _publication_resume_marker (repo_path : str ) -> ContinuationMarker | None :
@@ -260,8 +263,14 @@ def _copy_git_files_under(repo_path: str, source_dir: str, destination_dir: str)
260263 shutil .copy2 (source_file , destination_file )
261264
262265
263- def generate_diff_text (group : str , artifact : str , current_version : str , new_version : str , repo_path : str ) -> str :
264- """Build a diff text between the current and new test directories for a library version."""
266+ def _generate_test_diff_outputs (
267+ group : str ,
268+ artifact : str ,
269+ current_version : str ,
270+ new_version : str ,
271+ repo_path : str ,
272+ ) -> tuple [str , str ]:
273+ """Build full and stat test diffs for bounded PR descriptions (§GIT-pr-body)."""
265274 old_dir = os .path .join (repo_path , "tests" , "src" , group , artifact , current_version )
266275 new_dir = os .path .join (repo_path , "tests" , "src" , group , artifact , new_version )
267276 old_display_dir = os .path .relpath (old_dir , repo_path ).replace (os .sep , "/" )
@@ -277,23 +286,83 @@ def generate_diff_text(group: str, artifact: str, current_version: str, new_vers
277286 _copy_git_files_under (repo_path , old_dir , tmp_old )
278287 _copy_git_files_under (repo_path , new_dir , tmp_new )
279288
280- # Compute diff text using: git diff --no-index --find-renames tmp_old tmp_new
289+ diff_args = [ " git" , " diff" , " --no-index" , " --find-renames" ]
281290 res = subprocess .run (
282- ["git" , "diff" , "--no-index" , "--find-renames" , tmp_old , tmp_new ],
291+ [* diff_args , tmp_old , tmp_new ],
283292 capture_output = True ,
284293 text = True ,
285294 )
286295 if res .returncode in (0 , 1 ):
287296 diff_text = res .stdout
297+ stat_res = subprocess .run (
298+ [* diff_args , "--stat" , tmp_old , tmp_new ],
299+ capture_output = True ,
300+ text = True ,
301+ )
302+ if stat_res .returncode not in (0 , 1 ):
303+ raise RuntimeError (
304+ f"Subprocess failed with return code: { stat_res .returncode } . "
305+ f"Error output:\n { stat_res .stderr .strip ()} "
306+ )
288307
289308 diff_text = diff_text .replace (tmp_old .replace (os .sep , "/" ), old_diff_display_dir )
290309 diff_text = diff_text .replace (tmp_new .replace (os .sep , "/" ), new_diff_display_dir )
291310 diff_text = diff_text .replace (tmp_old , old_diff_display_dir )
292311 diff_text = diff_text .replace (tmp_new , new_diff_display_dir )
293- return diff_text
312+ return diff_text , stat_res . stdout
294313
295314 error_message = (
296315 f"Subprocess failed with return code: { res .returncode } . "
297316 f"Error output:\n { res .stderr .strip ()} "
298317 )
299318 raise RuntimeError (error_message )
319+
320+
321+ def generate_diff_text (group : str , artifact : str , current_version : str , new_version : str , repo_path : str ) -> str :
322+ """Build the complete test diff for callers that need it."""
323+ diff_text , _diff_stat = _generate_test_diff_outputs (
324+ group , artifact , current_version , new_version , repo_path ,
325+ )
326+ return diff_text
327+
328+
329+ def format_bounded_test_diff_section (
330+ group : str ,
331+ artifact : str ,
332+ current_version : str ,
333+ new_version : str ,
334+ repo_path : str ,
335+ ) -> str :
336+ """Format a reviewable test diff excerpt that cannot exhaust a PR body (§GIT-pr-body)."""
337+ diff_text , diff_stat = _generate_test_diff_outputs (
338+ group , artifact , current_version , new_version , repo_path ,
339+ )
340+ excerpt = diff_text [:MAX_INLINE_TEST_DIFF_CHARS ]
341+ truncation_note = ""
342+ if len (diff_text ) > MAX_INLINE_TEST_DIFF_CHARS :
343+ truncation_note = (
344+ "\n \n The complete test diff is available in this pull request's "
345+ "**Files changed** tab."
346+ )
347+ return (
348+ "**Test-source comparison**\n \n "
349+ "```text\n "
350+ f"{ diff_stat .strip ()} \n "
351+ "```\n \n "
352+ "```diff\n "
353+ f"{ excerpt } \n "
354+ "```"
355+ f"{ truncation_note } "
356+ )
357+
358+
359+ def bound_pr_body (body : str ) -> str :
360+ """Keep all publisher PR bodies below GitHub's limit (§GIT-pr-body)."""
361+ if len (body ) <= MAX_PR_BODY_CHARS :
362+ return body
363+ truncation_notice = (
364+ "\n \n ---\n \n Additional generated detail was omitted to keep this pull request "
365+ "description within GitHub's size limit."
366+ )
367+ head_chars = MAX_PR_BODY_CHARS - len (truncation_notice ) - PR_BODY_REQUIRED_TAIL_CHARS
368+ return body [:head_chars ].rstrip () + truncation_notice + body [- PR_BODY_REQUIRED_TAIL_CHARS :]
0 commit comments