@@ -536,24 +536,26 @@ def _render_scopes(scopes: list[ScopeResult], include_docs: bool) -> list[str]:
536536 value = _scope_value (scope )
537537 lines .append (f" ✔ { scope .label } { f' ({ value } )' if value else '' } " )
538538 continue
539- if scope .status == "warn" :
540- # Reported like a failure — same detail lines — but never a ✖:
541- # a warned rule ran and found something, it just does not fail
542- # the workflow, and the marker says so at a glance.
543- warnings = scope .warnings
544- count = f" ({ len (warnings )} warning{ 's' if len (warnings ) != 1 else '' } )"
545- lines .append (f" ⚠ { scope .label } { count } " )
546- lines .extend (_render_findings (warnings , include_docs ))
547- continue
548539 if scope .raw_text and not scope .checks :
549540 # Defensive fallback: commit-check produced unexpected output.
550541 lines .append (f" ✖ { scope .label } " )
551542 lines .extend (f" { ln } " for ln in scope .raw_text .strip ().splitlines ())
552543 continue
544+ # A scope's status names its worst outcome (fail beats warn), but the
545+ # two are not exclusive: CC2xx covers both branch and merge_base, so
546+ # one can fail while the other only warns. Render whichever of the
547+ # two lists is non-empty, rather than only the one the status names —
548+ # a warning on an otherwise-failing scope is still a finding to fix.
553549 failures = scope .failures
554- count = f" ({ len (failures )} failure{ 's' if len (failures ) != 1 else '' } )"
555- lines .append (f" ✖ { scope .label } { count } " )
556- lines .extend (_render_findings (failures , include_docs ))
550+ if failures :
551+ count = f" ({ len (failures )} failure{ 's' if len (failures ) != 1 else '' } )"
552+ lines .append (f" ✖ { scope .label } { count } " )
553+ lines .extend (_render_findings (failures , include_docs ))
554+ warnings = scope .warnings
555+ if warnings :
556+ count = f" ({ len (warnings )} warning{ 's' if len (warnings ) != 1 else '' } )"
557+ lines .append (f" ⚠ { scope .label } { count } " )
558+ lines .extend (_render_findings (warnings , include_docs ))
557559 return lines
558560
559561
@@ -697,40 +699,48 @@ def _skip_count(results: list[ScopeResult]) -> int:
697699
698700
699701def _warn_count (results : list [ScopeResult ]) -> int :
700- """Number of scopes reported as warnings .
702+ """Number of scopes that carry at least one warning .
701703
702- Reported separately from the pass count, the same way skips are, so the
703- headline can say how many findings were surfaced without claiming they
704- failed anything.
704+ Counts by ``scope.warnings``, not ``scope.status == "warn"``: a scope
705+ whose overall status is "fail" (CC2xx covers both ``branch`` and
706+ ``merge_base``, so one can fail while the other only warns) still has
707+ warnings to report, and this is the count the verdict and the table use
708+ to decide whether to show them.
705709 """
706- return sum (1 for scope in results if scope .status == "warn" )
710+ return sum (1 for scope in results if scope .warnings )
707711
708712
709713def _markdown_table (
710714 results : list [ScopeResult ], status : str = "fail" , header : str = "Failed checks"
711715) -> str :
712716 """Render the failure or warning table shared by summary and PR comment.
713717
714- Only scopes of the given status appear, so a per-row result column would
715- read the same symbol on every row and carry no information; the pass/fail
716- picture for everything else lives in the details block.
718+ A scope appears when it has an entry of the requested kind \u2014 checked via
719+ ``scope.failures`` / ``scope.warnings``, not ``scope.status`` \u2014 so a scope
720+ that both failed and warned gets a row in both tables. Filtering on the
721+ scope's single overall status would silently drop its warnings once a
722+ failure in the same scope outranked them.
717723 """
718724 rows = [
719725 f"| Scope | Checked value | { header } |" ,
720726 "|---|---|---|" ,
721727 ]
728+ is_raw_only_failure = (
729+ status == "fail"
730+ ) # a raw-text scope has no checks to warn about
722731 for scope in results :
723- # A skipped scope has no failed checks and no checked value, so it
724- # contributed an entirely blank row \u2014 an empty accusation in a table
725- # headed "Failed checks" \u2014 before this filter existed.
726- if scope .status != status :
732+ entries = scope .failures if status == "fail" else scope .warnings
733+ raw_failure = is_raw_only_failure and scope .raw_text and not scope .checks
734+ # A skipped or clean-passing scope has no matching entries and is not
735+ # a raw-text failure, so it contributes no row \u2014 an empty accusation
736+ # in a table headed "Failed checks" or "Warnings" otherwise.
737+ if not entries and not raw_failure :
727738 continue
728739 value = _scope_value (scope )
729740 value_display = f"`{ value } `" if value else "\u2014 "
730- if scope . raw_text and not scope . checks :
741+ if raw_failure :
731742 links = "_output could not be parsed \u2014 see details_"
732743 else :
733- entries = scope .failures if status == "fail" else scope .warnings
734744 links = " \u00b7 " .join (_rule_markdown_link (check ) for check in entries )
735745 rows .append (f"| { scope .label } | { value_display } | { links } |" )
736746 return "\n " .join (rows )
0 commit comments