@@ -49,11 +49,12 @@ async def run_triage(
4949 config : StarTriageConfig ,
5050 opts : TaskFilterOptions ,
5151 output_cfg : OutputConfig ,
52- ) -> list [tuple [str , TriageResult ]]:
52+ ) -> tuple [ list [tuple [str , TriageResult ]], bool ]:
5353 """Daily triage: fetch all sources concurrently, print sections in order as they complete.
5454
55- Returns the ``(source_name, result)`` pairs that were fetched successfully so
56- callers (e.g. ``triage --ai``) can reuse them without re-fetching.
55+ Returns a tuple of the ``(source_name, result)`` pairs that were fetched
56+ successfully (so callers such as ``triage --ai`` can reuse them without
57+ re-fetching) and a ``had_errors`` flag indicating whether any source failed.
5758 """
5859
5960 range = triage_task_note = ""
@@ -99,7 +100,7 @@ async def run_triage(
99100 for source in opts .sources :
100101 fetch_tasks [source .name ] = asyncio .create_task (source .find (config , opts , FetchMode .triage ))
101102
102- results = await _output_results (output_cfg , fetch_tasks )
103+ results , had_errors = await _output_results (output_cfg , fetch_tasks )
103104
104105 # create markdown template
105106 if output_cfg .markdown_path :
@@ -126,20 +127,22 @@ async def run_triage(
126127
127128 logging .info ("Markdown written to %s" , output_cfg .markdown_path )
128129
129- return results
130+ return results , had_errors
130131
131132
132133async def run_todo (
133134 config : StarTriageConfig ,
134135 filter : TaskFilterOptions ,
135136 output_cfg : OutputConfig ,
136137 subscribed : bool = False ,
137- ) -> None :
138+ ) -> bool :
138139 """Todo / housekeeping triage: tag-filtered bugs, no date filter.
139140
140141 All sources in *filter.sources* are optional — pass a subset to fetch only
141142 that source. *subscribed* only controls LP fetch mode (subscription list
142143 vs. todo tag); GitHub is filtered by label regardless.
144+
145+ Returns ``had_errors``, ``True`` if any source failed to fetch.
143146 """
144147 mode = FetchMode .subscribed if subscribed else FetchMode .todo
145148
@@ -150,17 +153,20 @@ async def run_todo(
150153 for source in filter .sources :
151154 fetch_tasks [source .name ] = asyncio .create_task (source .find (config , filter , mode ))
152155
156+ had_errors = False
153157 if output_cfg .bug_persistor is not None :
154- results = await _output_results (output_cfg , fetch_tasks )
158+ results , had_errors = await _output_results (output_cfg , fetch_tasks )
155159 for _ , result in results :
156160 await result .record (output_cfg .bug_persistor )
157161
158162 output_cfg .bug_persistor .save ()
159163
164+ return had_errors
165+
160166
161167async def _output_results (
162168 output_cfg : OutputConfig , fetch_tasks : dict [str , asyncio .Task [TriageResult ]]
163- ) -> list [tuple [str , TriageResult ]]:
169+ ) -> tuple [ list [tuple [str , TriageResult ]], bool ]:
164170 async with Spinner (set (fetch_tasks .keys ())) as spinner :
165171 gathered : list [tuple [str , TriageResult | Exception ]] = await asyncio .gather (
166172 * [_await_and_print (output_cfg , source , task , spinner ) for source , task in fetch_tasks .items ()]
@@ -172,7 +178,8 @@ async def _output_results(
172178 print (f"\n Error fetching { source !r} :" , file = sys .stderr )
173179 traceback .print_exception (exc , file = sys .stderr )
174180
175- return [(s , r ) for s , r in gathered if not isinstance (r , Exception )]
181+ results = [(s , r ) for s , r in gathered if not isinstance (r , Exception )]
182+ return results , bool (errors )
176183
177184
178185# Print sections in canonical order as each completes
0 commit comments