1919"""
2020
2121import logging
22- from datetime import datetime
2322from typing import cast , Optional
2423
2524from github import Github
@@ -52,7 +51,9 @@ def __init__(self, github: Github) -> None:
5251 self .__registered_issues : set [str ] = set ()
5352 self .__sub_issue_parents : dict [str , str ] = {}
5453 self .__registered_commits : set [str ] = set ()
54+
5555 self .__external_sub_issues : list [SubIssue ] = []
56+ self .__local_sub_issues_checked : list [str ] = []
5657
5758 def generate (self , data : MinedData ) -> dict [str , Record ]:
5859 """
@@ -64,15 +65,38 @@ def generate(self, data: MinedData) -> dict[str, Record]:
6465 """
6566 logger .debug ("Creation of records started..." )
6667 # First register all issues with sub-issues
68+ issues_expansion : list [SubIssue ] = []
6769 for issue in data .issues :
6870 if self .get_id (issue ) in self .__registered_issues :
6971 continue
7072
71- self ._create_issue_record_using_sub_issues_existence (issue , data .since )
73+ issues_expansion .extend (self ._create_issue_record_using_sub_issues_existence (issue , data ))
74+
75+ data .issues .extend (issues_expansion )
76+
77+ # Second register all hierarchy issues from sub-issues
78+ registered_before = - 1
79+ while registered_before < len (self .__registered_issues ):
80+ registered_before = len (self .__registered_issues )
81+ logger .debug (f"Looking for hierarchical issue among sub-issues..." )
82+
83+ issues_expansion = []
84+ for issue in data .issues :
85+ iid = self .get_id (issue )
86+ if iid in self .__registered_issues :
87+ continue
7288
73- # Second register all external sub-issues
74- # TODO decide if added as issue or sub-issue
89+ if iid in self .__sub_issue_parents .keys () and iid not in self .__local_sub_issues_checked :
90+ issues_expansion .extend (self ._create_issue_record_using_sub_issues_existence (issue , data ))
91+ self .__local_sub_issues_checked .append (iid )
92+
93+ data .issues .extend (issues_expansion )
94+
95+ # Third register all external sub-issues
7596 for ext_sub_issue in self .__external_sub_issues :
97+ if self .get_id (ext_sub_issue ) in self .__registered_issues :
98+ continue
99+
76100 self ._create_record_for_sub_issue (ext_sub_issue )
77101
78102 # Now register all issues without sub-issues
@@ -132,7 +156,7 @@ def _register_pull_and_its_commits_to_issue(self, pull: PullRequest, data: Mined
132156 issue_number = int (issue_id .split ("#" )[1 ])
133157 parent_issue = self ._safe_call (data .repository .get_issue )(issue_number ) if data .repository else None
134158 if parent_issue is not None :
135- self ._create_issue_record_using_sub_issues_existence (parent_issue )
159+ self ._create_issue_record_using_sub_issues_existence (parent_issue , data )
136160
137161 if issue_id in self ._records and isinstance (
138162 self ._records [issue_id ], (SubIssueRecord , HierarchyIssueRecord , IssueRecord )
@@ -154,19 +178,22 @@ def _register_pull_and_its_commits_to_issue(self, pull: PullRequest, data: Mined
154178 self ._records [str (pull .number )] = pr_rec
155179 logger .debug ("Created record for PR %d: %s" , pull .number , pull .title )
156180
157- def _create_issue_record_using_sub_issues_existence (self , issue : Issue , since : Optional [ datetime ] = None ) -> None :
181+ def _create_issue_record_using_sub_issues_existence (self , issue : Issue , data : MinedData ) -> list [ SubIssue ] :
158182 # use presence of sub-issues as a hint for hierarchy issue or non hierarchy issue
159183 sub_issues = list (issue .get_sub_issues ())
184+ logger .debug (f"Found { len (sub_issues )} sub-issues for { issue .number } " )
185+ new_local_issues : list [SubIssue ] = []
160186
161187 if len (sub_issues ) > 0 :
162188 self ._create_record_for_hierarchy_issue (issue )
163189 for si in sub_issues :
190+ siid = self .get_id (si )
191+
164192 # check if sub-issue is from current repository
165193 if si .repository .full_name != issue .repository .full_name :
166194 # register sub-issue and its parent for later hierarchy building
167- self .__sub_issue_parents [self .get_id (si )] = self .get_id (
168- issue
169- ) # Note: GitHub now allows only 1 parent
195+ # Note: GitHub now allows only 1 parent
196+ self .__sub_issue_parents [siid ] = self .get_id (issue )
170197
171198 self .__external_sub_issues .append (si )
172199 logger .debug (
@@ -177,21 +204,33 @@ def _create_issue_record_using_sub_issues_existence(self, issue: Issue, since: O
177204 )
178205
179206 else :
180- self .__sub_issue_parents [self .get_id (si )] = self .get_id (
181- issue
182- ) # Note: GitHub now allows only 1 parent
183- if since and si .state == IssueRecord .ISSUE_STATE_CLOSED and si .closed_at and since > si .closed_at :
184- logger .debug ("Detected sub-issue %d closed in previous release - skipping" , si .number )
185- continue
186-
187- if si .state == IssueRecord .ISSUE_STATE_OPEN :
188- logger .debug ("Detected sub-issue %d is still open - skipping" , si .number )
189- continue
190-
191- if si .state == IssueRecord .ISSUE_STATE_CLOSED : # issue is valid
192- continue
193-
194- logger .warning ("Detected unexpected sub-issue %d with parent %d" , si .number , issue .number )
207+ use_issue = False
208+ if data .since and si .state == IssueRecord .ISSUE_STATE_CLOSED and si .closed_at and data .since > si .closed_at :
209+ logger .debug ("Detected sub-issue %d closed in previous release." , si .number )
210+ if len (list (si .get_sub_issues ())) > 0 :
211+ use_issue = True
212+ else :
213+ self .__registered_issues .add (siid )
214+
215+ elif si .state == IssueRecord .ISSUE_STATE_OPEN :
216+ logger .debug ("Detected sub-issue %d is still open." , si .number )
217+ if len (list (si .get_sub_issues ())) > 0 :
218+ use_issue = True
219+ else :
220+ self .__registered_issues .add (siid )
221+
222+ elif si .state == IssueRecord .ISSUE_STATE_CLOSED : # issue is valid
223+ use_issue = True
224+
225+ else :
226+ logger .warning ("Detected unexpected sub-issue %d with parent %d" , si .number , issue .number )
227+
228+ if use_issue :
229+ self .__sub_issue_parents [siid ] = self .get_id (issue )
230+ if si not in data .issues :
231+ new_local_issues .append (si )
232+
233+ return new_local_issues
195234
196235 def _create_issue_record_using_sub_issues_not_existence (self , issue : Issue ) -> None :
197236 # Expected to run after all issue with sub-issues are registered
@@ -249,6 +288,8 @@ def _create_record_for_sub_issue(self, issue: Issue, issue_labels: Optional[list
249288 self ._records [iid ] = SubIssueRecord (issue , issue_labels , skip_record )
250289
251290 def _re_register_hierarchy_issues (self ):
291+ logger .debug ("Re-registering hierarchy issues ..." )
292+
252293 sub_issues_ids : list [str ] = list (self .__sub_issue_parents .keys ())
253294
254295 made_progress = False
0 commit comments