@@ -112,7 +112,18 @@ pub fn generate_issues(
112112
113113 // Hacky but works: we loop because after creating the issue, we sometimes have additional sync to do,
114114 // and it's easier this way.
115+ let mut iteration_count = 0 ;
116+ const MAX_ITERATIONS : usize = 10 ;
117+
115118 loop {
119+ iteration_count += 1 ;
120+ if iteration_count > MAX_ITERATIONS {
121+ spanned:: bail_here!(
122+ "Fixed point iteration failed to converge after {} iterations. \
123+ This may indicate duplicate tracking issues assigned to multiple goals.",
124+ MAX_ITERATIONS
125+ ) ;
126+ }
116127 let timeframe = validate_path ( path) ?;
117128
118129 let mut goal_documents = goal:: goals_in_dir ( path) ?;
@@ -168,6 +179,9 @@ pub fn generate_issues(
168179 eprintln ! ( "Use `--commit` to execute the actions." ) ;
169180 return Ok ( ( ) ) ;
170181 }
182+
183+ eprintln ! ( "Waiting for github commands to propagate." ) ;
184+ std:: thread:: sleep ( Duration :: from_millis ( 1000 ) ) ;
171185 }
172186}
173187
@@ -221,11 +235,6 @@ enum GithubAction<'doc> {
221235 LockIssue {
222236 number : u64 ,
223237 } ,
224-
225- LinkToTrackingIssue {
226- goal_document : & ' doc GoalDocument ,
227- issue_id : IssueId ,
228- } ,
229238}
230239
231240/// Initializes the required `T-<team>` labels on the repository.
@@ -281,6 +290,35 @@ fn initialize_issues<'doc>(
281290 . map ( |goal_document| issue ( timeframe, goal_document) )
282291 . collect :: < Result < _ > > ( ) ?;
283292
293+ // Check for duplicate tracking issues
294+ let mut tracking_issue_counts = std:: collections:: HashMap :: new ( ) ;
295+ for issue in & desired_issues {
296+ if let Some ( tracking_issue) = issue. tracking_issue {
297+ let count = tracking_issue_counts
298+ . entry ( tracking_issue. number )
299+ . or_insert ( 0 ) ;
300+ * count += 1 ;
301+ }
302+ }
303+
304+ for ( issue_number, count) in tracking_issue_counts {
305+ if count > 1 {
306+ let goals_with_issue: Vec < _ > = desired_issues
307+ . iter ( )
308+ . filter ( |issue| issue. tracking_issue . map ( |ti| ti. number ) == Some ( issue_number) )
309+ . map ( |issue| issue. goal_document . path . display ( ) . to_string ( ) )
310+ . collect ( ) ;
311+
312+ spanned:: bail_here!(
313+ "Tracking issue #{} is assigned to {} goals: {}. \
314+ Each tracking issue can only be assigned to one goal.",
315+ issue_number,
316+ count,
317+ goals_with_issue. join( ", " )
318+ ) ;
319+ }
320+ }
321+
284322 // the list of existing issues in the target milestone
285323 let milestone_issues = list_issues_in_milestone ( repository, timeframe) ?;
286324
@@ -390,14 +428,6 @@ fn initialize_issues<'doc>(
390428 body,
391429 } ) ;
392430 }
393-
394- let issue_id = IssueId :: new ( repository. clone ( ) , existing_issue. number ) ;
395- if desired_issue. tracking_issue != Some ( & issue_id) {
396- actions. insert ( GithubAction :: LinkToTrackingIssue {
397- goal_document : desired_issue. goal_document ,
398- issue_id,
399- } ) ;
400- }
401431 }
402432
403433 None => {
@@ -534,7 +564,7 @@ impl Display for GithubAction<'_> {
534564 write ! ( f, "create label `{}` with color `{}`" , name, color)
535565 }
536566 GithubAction :: CreateIssue { issue } => {
537- write ! ( f, "create issue \" {}\" " , issue. title)
567+ write ! ( f, "create issue \" {}\" " , issue. title, )
538568 }
539569 GithubAction :: ChangeMilestone { number, milestone } => {
540570 write ! ( f, "update issue #{} milestone to \" {}\" " , number, milestone)
@@ -568,16 +598,6 @@ impl Display for GithubAction<'_> {
568598 GithubAction :: LockIssue { number } => {
569599 write ! ( f, "lock issue #{}" , number)
570600 }
571- GithubAction :: LinkToTrackingIssue {
572- goal_document,
573- issue_id,
574- } => {
575- write ! (
576- f,
577- "link issue {issue_id:?} to the markdown document at {}" ,
578- goal_document. path. display( )
579- )
580- }
581601 }
582602 }
583603}
@@ -598,12 +618,13 @@ impl GithubAction<'_> {
598618 body,
599619 labels,
600620 tracking_issue : _,
601- goal_document : _ ,
621+ goal_document,
602622 } ,
603623 } => {
604- create_issue ( repository, & body, & title, & labels, & assignees, timeframe) ?;
624+ let issue_id =
625+ create_issue ( repository, & body, & title, & labels, & assignees, timeframe) ?;
605626
606- // Note: the issue is not locked, but we will reloop around later.
627+ goal_document . link_issue ( issue_id ) ? ;
607628
608629 Ok ( ( ) )
609630 }
@@ -640,11 +661,6 @@ impl GithubAction<'_> {
640661 }
641662
642663 GithubAction :: LockIssue { number } => lock_issue ( repository, number) ,
643-
644- GithubAction :: LinkToTrackingIssue {
645- goal_document,
646- issue_id : number,
647- } => goal_document. link_issue ( number) ,
648664 }
649665 }
650666}
0 commit comments