@@ -154,6 +154,12 @@ class PaperInfo:
154154 First version of LLVM in which this paper/issue was resolved.
155155 """
156156
157+ github_issue : Optional [str ]
158+ """
159+ Optional number of the Github issue tracking the implementation status of this paper.
160+ This is used to cross-reference rows in the status pages with Github issues.
161+ """
162+
157163 notes : Optional [str ]
158164 """
159165 Optional plain text string representing notes to associate to the paper.
@@ -170,23 +176,26 @@ def __init__(self, paper_number: str, paper_name: str,
170176 status : PaperStatus ,
171177 meeting : Optional [str ] = None ,
172178 first_released_version : Optional [str ] = None ,
179+ github_issue : Optional [str ] = None ,
173180 notes : Optional [str ] = None ,
174181 original : Optional [object ] = None ):
175182 self .paper_number = paper_number
176183 self .paper_name = paper_name
177184 self .status = status
178185 self .meeting = meeting
179186 self .first_released_version = first_released_version
187+ self .github_issue = github_issue
180188 self .notes = notes
181189 self .original = original
182190
183- def for_printing (self ) -> Tuple [str , str , str , str , str , str ]:
191+ def for_printing (self ) -> Tuple [str , str , str , str , str , str , str ]:
184192 return (
185193 f'`{ self .paper_number } <https://wg21.link/{ self .paper_number } >`__' ,
186194 self .paper_name ,
187195 self .meeting if self .meeting is not None else '' ,
188196 self .status .to_csv_entry (),
189197 self .first_released_version if self .first_released_version is not None else '' ,
198+ f'`#{ self .github_issue } <https://github.com/llvm/llvm-project/issues/{ self .github_issue } >`__' if self .github_issue is not None else '' ,
190199 self .notes if self .notes is not None else '' ,
191200 )
192201
@@ -203,13 +212,19 @@ def from_csv_row(row: Tuple[str, str, str, str, str, str]):# -> PaperInfo:
203212 if match is None :
204213 raise RuntimeError (f"Can't parse paper/issue number out of row: { row } " )
205214
215+ # Match the issue number if present
216+ github_issue = re .search (r'#([0-9]+)' , row [5 ])
217+ if github_issue :
218+ github_issue = github_issue .group (1 )
219+
206220 return PaperInfo (
207221 paper_number = match .group (1 ),
208222 paper_name = row [1 ],
209223 status = PaperStatus .from_csv_entry (row [3 ]),
210224 meeting = row [2 ] or None ,
211225 first_released_version = row [4 ] or None ,
212- notes = row [5 ] or None ,
226+ github_issue = github_issue ,
227+ notes = row [6 ] or None ,
213228 original = row ,
214229 )
215230
@@ -235,6 +250,7 @@ def from_github_issue(issue: Dict):# -> PaperInfo:
235250 status = PaperStatus .from_github_issue (issue ),
236251 meeting = issue .get ('meeting Voted' , None ),
237252 first_released_version = None , # TODO
253+ github_issue = str (issue ['content' ]['number' ]),
238254 notes = notes ,
239255 original = issue ,
240256 )
@@ -252,19 +268,24 @@ def merge(paper: PaperInfo, gh: PaperInfo) -> PaperInfo:
252268 is not useful.
253269
254270 In case we don't update the CSV row's status, we still take any updated notes coming
255- from the Github issue.
271+ from the Github issue and we add a link to the Github issue if it was previously missing .
256272 """
273+ took_gh_in_full = False # Whether we updated the entire PaperInfo from the Github version
257274 if paper .status == PaperStatus (PaperStatus .TODO ) and gh .status == PaperStatus (PaperStatus .IN_PROGRESS ):
258275 result = copy .deepcopy (paper )
259- result .notes = gh .notes
260276 elif paper .status < gh .status :
261277 result = copy .deepcopy (gh )
278+ took_gh_in_full = True
262279 elif paper .status == gh .status :
263280 result = copy .deepcopy (paper )
264- result .notes = gh .notes
265281 else :
266282 print (f"We found a CSV row and a Github issue with different statuses:\n row: { paper } \n Github issue: { gh } " )
267283 result = copy .deepcopy (paper )
284+
285+ # If we didn't take the Github issue in full, make sure to update the notes, the link and anything else.
286+ if not took_gh_in_full :
287+ result .github_issue = gh .github_issue
288+ result .notes = gh .notes
268289 return result
269290
270291def load_csv (file : pathlib .Path ) -> List [Tuple ]:
@@ -285,6 +306,8 @@ def create_github_issue(paper: PaperInfo, labels: List[str]) -> None:
285306 """
286307 Create a new Github issue representing the given PaperInfo.
287308 """
309+ assert paper .github_issue is None , "Trying to create a Github issue for a paper that is already tracked"
310+
288311 paper_name = paper .paper_name .replace ('``' , '`' ).replace ('\\ ' , '' )
289312
290313 create_cli = ['gh' , 'issue' , 'create' , '--repo' , 'llvm/llvm-project' ,
@@ -363,6 +386,17 @@ def sync_csv(rows: List[Tuple], from_github: List[PaperInfo], create_new: bool,
363386 results .append (row )
364387 continue
365388
389+ # Validate the Github issue associated to the CSV row, if any
390+ if paper .github_issue is not None :
391+ if len (tracking ) == 0 :
392+ print (f"Found row claiming to have a tracking issue, but failed to find a tracking issue on Github: { row } " )
393+ results .append (row )
394+ continue
395+ if len (tracking ) == 1 and paper .github_issue != tracking [0 ].github_issue :
396+ print (f"Found row with incorrect tracking issue: { row } \n tracked by: { tracking [0 ]} " )
397+ results .append (row )
398+ continue
399+
366400 # If there is no tracking issue for that row and we are creating new issues, do that.
367401 # Otherwise just log that we're missing an issue.
368402 if len (tracking ) == 0 :
0 commit comments