2727from github import Github
2828from github .GitRelease import GitRelease
2929from github .Issue import Issue
30+ from github .PullRequest import PullRequest
3031from github .Repository import Repository
3132
3233from release_notes_generator .action_inputs import ActionInputs
@@ -83,19 +84,25 @@ def mine_data(self) -> MinedData:
8384
8485 return de_duplicated_data
8586
86- def mine_missing_sub_issues (self , data : MinedData ) -> dict [Issue , Repository ]:
87+ def mine_missing_sub_issues (self , data : MinedData ) -> tuple [ dict [Issue , Repository ], dict [ str , list [ PullRequest ]] ]:
8788 """
8889 Mines missing sub-issues from GitHub.
8990 Parameters:
9091 data (MinedData): The mined data containing origin sets of issues and pull requests.
9192 Returns:
9293 dict[Issue, Repository]: A dictionary mapping fetched issues to their repositories.
94+ dict[str, list[PullRequest]]: A dictionary mapping fetched cross-repo issue with its pull requests.
9395 """
9496 logger .info ("Mapping sub-issues..." )
9597 data .parents_sub_issues = self ._scan_sub_issues_for_parents ([get_id (i , r ) for i , r in data .issues .items ()])
9698
9799 logger .info ("Fetching missing issues..." )
98- return self ._fetch_missing_issues_and_prs (data )
100+ fetched_issues = self ._fetch_missing_issues (data )
101+
102+ logger .info ("Getting PRs and Commits for missing issues..." )
103+ prs_of_fetched_cross_repo_issues = self ._fetch_prs_for_fetched_cross_issues (fetched_issues )
104+
105+ return fetched_issues , prs_of_fetched_cross_repo_issues
99106
100107 def _scan_sub_issues_for_parents (self , parents_to_check : list [str ]) -> dict [str , list [str ]]:
101108 """
@@ -119,7 +126,7 @@ def _scan_sub_issues_for_parents(self, parents_to_check: list[str]) -> dict[str,
119126
120127 return parents_sub_issues
121128
122- def _fetch_missing_issues_and_prs (self , data : MinedData ) -> dict [Issue , Repository ]:
129+ def _fetch_missing_issues (self , data : MinedData ) -> dict [Issue , Repository ]:
123130 """
124131 Fetch missing issues.
125132
@@ -167,6 +174,8 @@ def _fetch_missing_issues_and_prs(self, data: MinedData) -> dict[Issue, Reposito
167174 else :
168175 logger .debug ("Skipping issue %s since it does not meet criteria." , parent_id )
169176 issues_for_remove .append (parent_id )
177+ else :
178+ logger .error ("Cannot get repository for issue %s. Skipping..." , parent_id )
170179
171180 # remove issue which does not meet criteria
172181 for iid in issues_for_remove :
@@ -350,3 +359,20 @@ def __filter_duplicated_issues(data: MinedData) -> "MinedData":
350359
351360 data .issues = filtered_issues
352361 return data
362+
363+ def _fetch_prs_for_fetched_cross_issues (self , issues : dict [Issue , Repository ]) -> dict [str , list [PullRequest ]]:
364+ prs_of_cross_repo_issues : dict [str , list [PullRequest ]] = {}
365+ for i , repo in issues .items ():
366+ prs_of_cross_repo_issues [iid := get_id (i , repo )] = []
367+ try :
368+ for ev in i .get_timeline (): # timeline includes cross-references
369+ if ev .event == "cross-referenced" and getattr (ev , "source" , None ):
370+ # <- this is a github.Issue.Issue
371+ src_issue = ev .source .issue # type: ignore[union-attr]
372+ if getattr (src_issue , "pull_request" , None ):
373+ pr = src_issue .as_pull_request () # github.PullRequest.PullRequest
374+ prs_of_cross_repo_issues [iid ].append (pr )
375+ except Exception as e :
376+ logger .warning ("Failed to fetch timeline events for issue %s: %s" , iid , str (e ))
377+
378+ return prs_of_cross_repo_issues
0 commit comments