@@ -501,6 +501,12 @@ def is_instrumentation_path(relative_path: str) -> bool:
501501# build summary of reverted/downgraded dependencies for PR descriptions
502502# path_filter restricts the summary to lockfiles whose relative path matches,
503503# so each PR (core vs instrumentation) only lists the dependencies it actually changes
504+ #
505+ # The summary is split into three on-screen sections, ordered by how urgently a human
506+ # must act on them:
507+ # 1. "Cannot verify age, reverted" — age could not be checked at all, needs manual resolution
508+ # 2. "<N>h cooldown, reverted" — too new and no older eligible version exists, so reverted to baseline
509+ # 3. "<N>h cooldown, updated to the previous version" — too new, downgraded to an older eligible version
504510def build_validation_summary (
505511 * ,
506512 violations_by_file : dict [str , list [tuple [str , str , int ]]],
@@ -509,34 +515,60 @@ def build_validation_summary(
509515 min_age_hours : int ,
510516 path_filter : Callable [[str ], bool ],
511517) -> str :
512- header = ["## Dependency age policy" , "" ]
513- lines = list (header )
518+ unverified : list [str ] = []
519+ cooldown_reverted : list [str ] = []
520+ cooldown_updated : list [str ] = []
514521 seen : set [str ] = set ()
522+
515523 for relative_path , replacements in replacements_by_file .items ():
516524 if not path_filter (relative_path ):
517525 continue
518526 baseline_coords = baseline_lockfiles .get (relative_path , set ())
519527 for old_gav , (new_gav , hours_remaining ) in replacements .items ():
520- if old_gav not in seen :
521- seen .add (old_gav )
522- if new_gav in baseline_coords :
523- lines .append (f"- `{ old_gav } ` is { hours_remaining } h away from meeting { min_age_hours } h cooldown, reverted" )
524- else :
525- new_version = new_gav .rsplit (":" , 1 )[1 ]
526- lines .append (f"- `{ old_gav } ` is { hours_remaining } h away from meeting { min_age_hours } h cooldown, updated to `{ new_version } `" )
528+ if old_gav in seen :
529+ continue
530+ seen .add (old_gav )
531+ if new_gav in baseline_coords :
532+ # the only eligible version was the baseline, so this is effectively a revert
533+ cooldown_reverted .append (f"- `{ old_gav } ` is { hours_remaining } h away from meeting cooldown" )
534+ else :
535+ new_version = new_gav .rsplit (":" , 1 )[1 ]
536+ cooldown_updated .append (f"- `{ old_gav } ` is { hours_remaining } h away from meeting cooldown, updated to `{ new_version } `" )
527537 for relative_path , entries in violations_by_file .items ():
528538 if not path_filter (relative_path ):
529539 continue
530540 for gav , kind , hours_remaining in entries :
531- if gav not in seen :
532- seen .add (gav )
533- if kind == "unverified" :
534- lines .append (f"- `{ gav } ` — cannot verify age, reverted" )
535- else :
536- lines .append (f"- `{ gav } ` is { hours_remaining } h away from meeting { min_age_hours } h cooldown, reverted" )
537- if len (lines ) == len (header ): # nothing matched the filter
541+ if gav in seen :
542+ continue
543+ seen .add (gav )
544+ if kind == "unverified" :
545+ unverified .append (f"- `{ gav } `" )
546+ else :
547+ cooldown_reverted .append (f"- `{ gav } ` is { hours_remaining } h away from meeting cooldown" )
548+
549+ blocks : list [str ] = []
550+ if unverified :
551+ blocks .append (
552+ "### :warning: Cannot verify age, reverted\n \n "
553+ "The age of these dependencies could not be verified, so the lockfiles were reverted. "
554+ "**This needs to be resolved manually.**\n \n "
555+ + "\n " .join (sorted (unverified ))
556+ )
557+ if cooldown_reverted :
558+ blocks .append (
559+ f"### { min_age_hours } h cooldown, reverted\n \n "
560+ "Too new and no older eligible version exists, so the lockfiles were reverted to the baseline.\n \n "
561+ + "\n " .join (sorted (cooldown_reverted ))
562+ )
563+ if cooldown_updated :
564+ blocks .append (
565+ f"### { min_age_hours } h cooldown, updated to the previous version\n \n "
566+ "Too new, so an older eligible version was used instead.\n \n "
567+ + "\n " .join (sorted (cooldown_updated ))
568+ )
569+ if not blocks : # nothing matched the filter
538570 return ""
539- return "\n " .join (lines )
571+ return "## Dependency age policy \n \n " + " \n \n " .join (blocks )
540572
541573
542574# replace specific coordinates in lockfiles (for version downgrades)
0 commit comments