@@ -112,7 +112,18 @@ pub fn generate_issues(
112
112
113
113
// Hacky but works: we loop because after creating the issue, we sometimes have additional sync to do,
114
114
// and it's easier this way.
115
+ let mut iteration_count = 0 ;
116
+ const MAX_ITERATIONS : usize = 10 ;
117
+
115
118
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
+ }
116
127
let timeframe = validate_path ( path) ?;
117
128
118
129
let mut goal_documents = goal:: goals_in_dir ( path) ?;
@@ -168,6 +179,9 @@ pub fn generate_issues(
168
179
eprintln ! ( "Use `--commit` to execute the actions." ) ;
169
180
return Ok ( ( ) ) ;
170
181
}
182
+
183
+ eprintln ! ( "Waiting for github commands to propagate." ) ;
184
+ std:: thread:: sleep ( Duration :: from_millis ( 1000 ) ) ;
171
185
}
172
186
}
173
187
@@ -221,11 +235,6 @@ enum GithubAction<'doc> {
221
235
LockIssue {
222
236
number : u64 ,
223
237
} ,
224
-
225
- LinkToTrackingIssue {
226
- goal_document : & ' doc GoalDocument ,
227
- issue_id : IssueId ,
228
- } ,
229
238
}
230
239
231
240
/// Initializes the required `T-<team>` labels on the repository.
@@ -281,6 +290,35 @@ fn initialize_issues<'doc>(
281
290
. map ( |goal_document| issue ( timeframe, goal_document) )
282
291
. collect :: < Result < _ > > ( ) ?;
283
292
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
+
284
322
// the list of existing issues in the target milestone
285
323
let milestone_issues = list_issues_in_milestone ( repository, timeframe) ?;
286
324
@@ -390,14 +428,6 @@ fn initialize_issues<'doc>(
390
428
body,
391
429
} ) ;
392
430
}
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
- }
401
431
}
402
432
403
433
None => {
@@ -534,7 +564,7 @@ impl Display for GithubAction<'_> {
534
564
write ! ( f, "create label `{}` with color `{}`" , name, color)
535
565
}
536
566
GithubAction :: CreateIssue { issue } => {
537
- write ! ( f, "create issue \" {}\" " , issue. title)
567
+ write ! ( f, "create issue \" {}\" " , issue. title, )
538
568
}
539
569
GithubAction :: ChangeMilestone { number, milestone } => {
540
570
write ! ( f, "update issue #{} milestone to \" {}\" " , number, milestone)
@@ -568,16 +598,6 @@ impl Display for GithubAction<'_> {
568
598
GithubAction :: LockIssue { number } => {
569
599
write ! ( f, "lock issue #{}" , number)
570
600
}
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
- }
581
601
}
582
602
}
583
603
}
@@ -598,12 +618,13 @@ impl GithubAction<'_> {
598
618
body,
599
619
labels,
600
620
tracking_issue : _,
601
- goal_document : _ ,
621
+ goal_document,
602
622
} ,
603
623
} => {
604
- create_issue ( repository, & body, & title, & labels, & assignees, timeframe) ?;
624
+ let issue_id =
625
+ create_issue ( repository, & body, & title, & labels, & assignees, timeframe) ?;
605
626
606
- // Note: the issue is not locked, but we will reloop around later.
627
+ goal_document . link_issue ( issue_id ) ? ;
607
628
608
629
Ok ( ( ) )
609
630
}
@@ -640,11 +661,6 @@ impl GithubAction<'_> {
640
661
}
641
662
642
663
GithubAction :: LockIssue { number } => lock_issue ( repository, number) ,
643
-
644
- GithubAction :: LinkToTrackingIssue {
645
- goal_document,
646
- issue_id : number,
647
- } => goal_document. link_issue ( number) ,
648
664
}
649
665
}
650
666
}
0 commit comments