@@ -37,24 +37,31 @@ impl Generator {
37
37
38
38
self . fcps ( String :: from ( "T-libs-api" ) ) ?;
39
39
40
- IssueQuery :: new ( "Nominated" )
40
+ GithubQuery :: new ( "Nominated" )
41
41
. labels ( & [ "T-libs-api" , "I-nominated" ] )
42
42
. repo ( "rust-lang/libs-team" )
43
43
. repo ( "rust-lang/rust" )
44
44
. repo ( "rust-lang/rfcs" )
45
45
. write ( & mut self ) ?;
46
46
47
- IssueQuery :: new ( "Waiting on team" )
47
+ GithubQuery :: new ( "Waiting on team" )
48
48
. labels ( & [ "T-libs-api" , "S-waiting-on-team" ] )
49
49
. repo ( "rust-lang/rust" )
50
50
. repo ( "rust-lang/rfcs" )
51
51
. write ( & mut self ) ?;
52
52
53
- IssueQuery :: new ( "Needs decision" )
53
+ GithubQuery :: new ( "Needs decision" )
54
54
. labels ( & [ "T-libs-api" , "I-needs-decision" ] )
55
55
. repo ( "rust-lang/rust" )
56
56
. write ( & mut self ) ?;
57
57
58
+ GithubQuery :: new ( "Stalled Tracking Issues" )
59
+ . labels ( & [ "T-libs-api" , "C-tracking-issue" ] )
60
+ . repo ( "rust-lang/rust" )
61
+ . sort ( Sort :: LeastRecentlyUpdated )
62
+ . take ( 5 )
63
+ . write ( & mut self ) ?;
64
+
58
65
writeln ! ( & mut self . agenda,
59
66
"## Actions
60
67
@@ -91,41 +98,38 @@ impl Generator {
91
98
92
99
self . fcps ( String :: from ( "T-libs" ) ) ?;
93
100
94
- IssueQuery :: new ( "Critical" )
101
+ GithubQuery :: new ( "Critical" )
95
102
. labels ( & [ "T-libs" , "P-critical" ] )
96
103
. labels ( & [ "T-libs-api" , "P-critical" ] )
97
104
. repo ( "rust-lang/rust" )
98
105
. repo ( "rust-lang/rfcs" )
99
106
. write ( & mut self ) ?;
100
107
101
- IssueQuery :: new ( "Prioritization Requested" )
108
+ GithubQuery :: new ( "Prioritization Requested" )
102
109
. labels ( & [ "T-libs" , "I-prioritize" ] )
103
110
. labels ( & [ "T-libs-api" , "I-prioritize" ] )
104
111
. repo ( "rust-lang/rust" )
105
112
. repo ( "rust-lang/rfcs" )
106
113
. write ( & mut self ) ?;
107
114
108
- IssueQuery :: new ( "Nominated" )
115
+ GithubQuery :: new ( "Nominated" )
109
116
. labels ( & [ "T-libs" , "I-nominated" ] )
110
117
. repo ( "rust-lang/rust" )
111
118
. repo ( "rust-lang/rfcs" )
112
119
. repo ( "rust-lang/libs-team" )
113
120
. write ( & mut self ) ?;
114
121
115
- IssueQuery :: new ( "Backports" )
122
+ GithubQuery :: new ( "Backports" )
116
123
. labels ( & [ "T-libs" , "stable-nominated" ] )
117
124
. labels ( & [ "T-libs-api" , "stable-nominated" ] )
118
- . labels ( & [ "T-libs" , "stable-accepted" ] )
119
- . labels ( & [ "T-libs-api" , "stable-accepted" ] )
120
125
. labels ( & [ "T-libs" , "beta-nominated" ] )
121
126
. labels ( & [ "T-libs-api" , "beta-nominated" ] )
122
- . labels ( & [ "T-libs" , "beta-accepted" ] )
123
- . labels ( & [ "T-libs-api" , "beta-accepted" ] )
127
+ . state ( State :: Any )
124
128
. repo ( "rust-lang/rust" )
125
129
. repo ( "rust-lang/rfcs" )
126
130
. write ( & mut self ) ?;
127
131
128
- IssueQuery :: new ( "Regressions" )
132
+ GithubQuery :: new ( "Regressions" )
129
133
. labels ( & [ "T-libs" , "regression-untriaged" ] )
130
134
. labels ( & [ "T-libs-api" , "regression-untriaged" ] )
131
135
. labels ( & [ "T-libs" , "regression-from-stable-to-stable" ] )
@@ -150,24 +154,24 @@ impl Generator {
150
154
}
151
155
152
156
pub fn error_handling_pg_agenda ( mut self ) -> Result < String > {
153
- IssueQuery :: new ( "Nominated" )
157
+ GithubQuery :: new ( "Nominated" )
154
158
. labels ( & [ "PG-error-handling" , "I-nominated" ] )
155
159
. repo ( "rust-lang/rust" )
156
160
. repo ( "rust-lang/project-error-handling" )
157
161
. write ( & mut self ) ?;
158
162
159
- IssueQuery :: new ( "PG Error Handling" )
163
+ GithubQuery :: new ( "PG Error Handling" )
160
164
. labels ( & [ "PG-error-handling" ] )
161
165
. repo ( "rust-lang/rust" )
162
166
. repo ( "rust-lang/project-error-handling" )
163
167
. write ( & mut self ) ?;
164
168
165
- IssueQuery :: new ( "Area Error Handling" )
169
+ GithubQuery :: new ( "Area Error Handling" )
166
170
. labels ( & [ "A-error-handling" ] )
167
171
. repo ( "rust-lang/rust" )
168
172
. write ( & mut self ) ?;
169
173
170
- IssueQuery :: new ( "PG Error Handling" )
174
+ GithubQuery :: new ( "PG Error Handling" )
171
175
. repo ( "rust-lang/project-error-handling" )
172
176
. write ( & mut self ) ?;
173
177
@@ -342,24 +346,89 @@ impl Generator {
342
346
Ok ( ( ) )
343
347
}
344
348
345
- fn dedup ( & mut self , mut issues : Vec < Issue > ) -> Vec < Issue > {
346
- issues. retain ( |issue| self . seen . insert ( issue. html_url . clone ( ) ) ) ;
347
- issues
349
+ fn dedup ( & mut self , issues : Vec < Issue > ) -> impl Iterator < Item = Issue > + ' _ {
350
+ issues. into_iter ( ) . filter ( move |issue| self . seen . insert ( issue. html_url . clone ( ) ) )
351
+ }
352
+ }
353
+
354
+ #[ derive( Clone , Copy ) ]
355
+ #[ allow( dead_code) ]
356
+ enum Sort {
357
+ Newest ,
358
+ Oldest ,
359
+ MostCommented ,
360
+ LeastCommented ,
361
+ MostRecentlyUpdated ,
362
+ LeastRecentlyUpdated ,
363
+ }
364
+
365
+ impl Sort {
366
+ fn api_str ( & self ) -> & ' static str {
367
+ match self {
368
+ Sort :: Newest => "&sort=created&direction=desc" ,
369
+ Sort :: Oldest => "&sort=created&direction=asc" ,
370
+ Sort :: MostCommented => "&sort=comments&direction=asc" ,
371
+ Sort :: LeastCommented => "&sort=comments&direction=desc" ,
372
+ Sort :: MostRecentlyUpdated => "&sort=updated&direction=desc" ,
373
+ Sort :: LeastRecentlyUpdated => "&sort=updated&direction=asc" ,
374
+ }
375
+ }
376
+
377
+ fn web_ui_str ( & self ) -> & ' static str {
378
+ match self {
379
+ Sort :: Newest => "+sort:created-desc" ,
380
+ Sort :: Oldest => "+sort:created-asc" ,
381
+ Sort :: MostCommented => "+sort:comments-desc" ,
382
+ Sort :: LeastCommented => "+sort:comments-asc" ,
383
+ Sort :: MostRecentlyUpdated => "+sort:updated-desc" ,
384
+ Sort :: LeastRecentlyUpdated => "+sort:updated-asc" ,
385
+ }
348
386
}
349
387
}
350
388
351
- struct IssueQuery {
389
+ struct GithubQuery {
352
390
name : & ' static str ,
353
391
labels : Vec < & ' static [ & ' static str ] > ,
354
392
repos : Vec < & ' static str > ,
393
+ sort : Option < Sort > ,
394
+ count : Option < usize > ,
395
+ state : State ,
396
+ }
397
+
398
+ #[ allow( dead_code) ]
399
+ enum State {
400
+ Open ,
401
+ Closed ,
402
+ Any ,
403
+ }
404
+
405
+ impl State {
406
+ fn api_str ( & self ) -> & ' static str {
407
+ match self {
408
+ State :: Open => "&state=open" ,
409
+ State :: Closed => "&state=closed" ,
410
+ State :: Any => "&state=all" ,
411
+ }
412
+ }
413
+
414
+ fn web_ui_str ( & self ) -> & ' static str {
415
+ match self {
416
+ State :: Open => "+is:open" ,
417
+ State :: Closed => "+is:closed" ,
418
+ State :: Any => "" ,
419
+ }
420
+ }
355
421
}
356
422
357
- impl IssueQuery {
423
+ impl GithubQuery {
358
424
fn new ( name : & ' static str ) -> Self {
359
425
Self {
360
426
name,
361
427
labels : vec ! [ ] ,
362
428
repos : vec ! [ ] ,
429
+ sort : None ,
430
+ count : None ,
431
+ state : State :: Open ,
363
432
}
364
433
}
365
434
@@ -373,6 +442,21 @@ impl IssueQuery {
373
442
self
374
443
}
375
444
445
+ fn sort ( & mut self , sort : Sort ) -> & mut Self {
446
+ self . sort = Some ( sort) ;
447
+ self
448
+ }
449
+
450
+ fn take ( & mut self , count : usize ) -> & mut Self {
451
+ self . count = Some ( count) ;
452
+ self
453
+ }
454
+
455
+ fn state ( & mut self , state : State ) -> & mut Self {
456
+ self . state = state;
457
+ self
458
+ }
459
+
376
460
fn write ( & mut self , generator : & mut Generator ) -> Result < ( ) > {
377
461
writeln ! ( generator. agenda, "### {}" , self . name) ?;
378
462
writeln ! ( generator. agenda, ) ?;
@@ -382,8 +466,21 @@ impl IssueQuery {
382
466
for repo in & self . repos {
383
467
for labels in & self . labels {
384
468
let cs_labels = labels. join ( "," ) ;
385
- let endpoint = format ! ( "repos/{}/issues?labels={}" , repo, cs_labels) ;
386
- let issues = generator. dedup ( github_api ( & endpoint) ?) ;
469
+ let mut endpoint = format ! ( "repos/{}/issues?labels={}" , repo, cs_labels) ;
470
+
471
+ endpoint += self . state . api_str ( ) ;
472
+
473
+ if let Some ( sort) = self . sort {
474
+ endpoint += sort. api_str ( ) ;
475
+ }
476
+
477
+ let issues = github_api ( & endpoint) ?;
478
+ let issues = generator. dedup ( issues) ;
479
+ let issues: Vec < _ > = if let Some ( count) = self . count {
480
+ issues. take ( count) . collect ( )
481
+ } else {
482
+ issues. collect ( )
483
+ } ;
387
484
388
485
if issues. is_empty ( ) {
389
486
continue ;
@@ -393,13 +490,23 @@ impl IssueQuery {
393
490
. iter ( )
394
491
. map ( |label| format ! ( "label:{}" , label) )
395
492
. join ( "+" ) ;
493
+
494
+ let mut url = format ! ( "https://github.com/{}/issues?q={}" , repo, url_labels) ;
495
+
496
+ url += self . state . web_ui_str ( ) ;
497
+
498
+ if let Some ( sort) = self . sort {
499
+ url += sort. web_ui_str ( ) ;
500
+ }
501
+
502
+
396
503
writeln ! (
397
504
generator. agenda,
398
- "- [{} `{repo}` `{labels}` items](https://github.com/{repo}/issues?q=is:open+{url_labels })" ,
505
+ "- [{} `{repo}` `{labels}` items]({url })" ,
399
506
issues. len( ) ,
400
507
repo = repo,
401
508
labels = labels. join( "` `" ) ,
402
- url_labels = url_labels ,
509
+ url = url ,
403
510
) ?;
404
511
generator. write_issues ( & issues) ?;
405
512
@@ -450,8 +557,9 @@ fn escape(v: &str) -> String {
450
557
}
451
558
452
559
fn github_api < T : DeserializeOwned > ( endpoint : & str ) -> Result < T > {
560
+ let url = format ! ( "https://api.github.com/{}" , endpoint) ;
453
561
let mut client = reqwest:: blocking:: Client :: new ( )
454
- . get ( & format ! ( "https://api.github.com/{}" , endpoint ) )
562
+ . get ( & url )
455
563
. header ( USER_AGENT , "rust-lang libs agenda maker" ) ;
456
564
if let Ok ( token) = std:: env:: var ( "GITHUB_TOKEN" ) {
457
565
client = client. header ( AUTHORIZATION , format ! ( "token {}" , token) ) ;
0 commit comments