@@ -4,14 +4,15 @@ use std::{
4
4
fmt:: Display ,
5
5
path:: { Path , PathBuf } ,
6
6
process:: Command ,
7
+ time:: Duration ,
7
8
} ;
8
9
9
10
use anyhow:: Context ;
10
11
use regex:: Regex ;
11
12
use serde:: { Deserialize , Serialize } ;
12
13
13
14
use crate :: {
14
- goal:: { self , GoalDocument , ParsedOwners , PlanItem } ,
15
+ goal:: { self , GoalDocument , ParsedOwners , PlanItem , Status } ,
15
16
team:: { get_person_data, TeamName } ,
16
17
} ;
17
18
@@ -97,10 +98,17 @@ pub fn generate_rfc(path: &Path) -> anyhow::Result<()> {
97
98
Ok ( ( ) )
98
99
}
99
100
100
- pub fn generate_issues ( repository : & str , path : & Path , commit : bool ) -> anyhow:: Result < ( ) > {
101
+ pub fn generate_issues (
102
+ repository : & str ,
103
+ path : & Path ,
104
+ commit : bool ,
105
+ sleep : u64 ,
106
+ ) -> anyhow:: Result < ( ) > {
101
107
let timeframe = validate_path ( path) ?;
102
108
103
- let goal_documents = goal:: goals_in_dir ( path) ?;
109
+ let mut goal_documents = goal:: goals_in_dir ( path) ?;
110
+ goal_documents. retain ( |gd| gd. is_not_not_accepted ( ) ) ;
111
+
104
112
let teams_with_asks = teams_with_asks ( & goal_documents) ;
105
113
let mut actions = initialize_labels ( repository, & teams_with_asks) ?;
106
114
actions. extend ( initialize_issues ( repository, & timeframe, & goal_documents) ?) ;
@@ -110,16 +118,31 @@ pub fn generate_issues(repository: &str, path: &Path, commit: bool) -> anyhow::R
110
118
return Ok ( ( ) ) ;
111
119
}
112
120
113
- eprintln ! ( "Actions to be executed:" ) ;
114
- for action in & actions {
115
- eprintln ! ( "* {action}" ) ;
116
- }
117
-
118
121
if commit {
122
+ progress_bar:: init_progress_bar ( actions. len ( ) ) ;
123
+ progress_bar:: set_progress_bar_action (
124
+ "Executing" ,
125
+ progress_bar:: Color :: Blue ,
126
+ progress_bar:: Style :: Bold ,
127
+ ) ;
119
128
for action in actions. into_iter ( ) {
129
+ progress_bar:: print_progress_bar_info (
130
+ "Action" ,
131
+ & format ! ( "{}" , action) ,
132
+ progress_bar:: Color :: Green ,
133
+ progress_bar:: Style :: Bold ,
134
+ ) ;
120
135
action. execute ( repository, & timeframe) ?;
136
+ progress_bar:: inc_progress_bar ( ) ;
137
+
138
+ std:: thread:: sleep ( Duration :: from_millis ( sleep) ) ;
121
139
}
140
+ progress_bar:: finalize_progress_bar ( ) ;
122
141
} else {
142
+ eprintln ! ( "Actions to be executed:" ) ;
143
+ for action in & actions {
144
+ eprintln ! ( "* {action}" ) ;
145
+ }
123
146
eprintln ! ( "" ) ;
124
147
eprintln ! ( "Use `--commit` to execute the actions." ) ;
125
148
}
@@ -132,7 +155,7 @@ pub struct GithubIssue {
132
155
pub title : String ,
133
156
pub assignees : Vec < String > ,
134
157
pub body : String ,
135
- pub teams : BTreeSet < & ' static TeamName > ,
158
+ pub labels : Vec < String > ,
136
159
}
137
160
138
161
#[ derive( Debug , PartialEq , Eq , PartialOrd , Ord ) ]
@@ -147,6 +170,11 @@ struct GhLabel {
147
170
color : String ,
148
171
}
149
172
173
+ #[ derive( Debug , Serialize , Deserialize , PartialEq , Eq , PartialOrd , Ord ) ]
174
+ struct ExistingGithubIssue {
175
+ title : String ,
176
+ }
177
+
150
178
fn list_labels ( repository : & str ) -> anyhow:: Result < Vec < GhLabel > > {
151
179
let output = Command :: new ( "gh" )
152
180
. arg ( "-R" )
@@ -162,6 +190,25 @@ fn list_labels(repository: &str) -> anyhow::Result<Vec<GhLabel>> {
162
190
Ok ( labels)
163
191
}
164
192
193
+ fn list_issue_titles_in_milestone (
194
+ repository : & str ,
195
+ timeframe : & str ,
196
+ ) -> anyhow:: Result < BTreeSet < String > > {
197
+ let output = Command :: new ( "gh" )
198
+ . arg ( "-R" )
199
+ . arg ( repository)
200
+ . arg ( "issue" )
201
+ . arg ( "list" )
202
+ . arg ( "-m" )
203
+ . arg ( timeframe)
204
+ . arg ( "--json" )
205
+ . arg ( "title" )
206
+ . output ( ) ?;
207
+
208
+ let existing_issues: Vec < ExistingGithubIssue > = serde_json:: from_slice ( & output. stdout ) ?;
209
+
210
+ Ok ( existing_issues. into_iter ( ) . map ( |e_i| e_i. title ) . collect ( ) )
211
+ }
165
212
/// Initializes the required `T-<team>` labels on the repository.
166
213
/// Warns if the labels are found with wrong color.
167
214
fn initialize_labels (
@@ -187,6 +234,11 @@ fn initialize_labels(
187
234
color : "f5f1fd" . to_string ( ) ,
188
235
} ) ;
189
236
237
+ desired_labels. insert ( GhLabel {
238
+ name : "Flagship Goal" . to_string ( ) ,
239
+ color : "5319E7" . to_string ( ) ,
240
+ } ) ;
241
+
190
242
for existing_label in list_labels ( repository) ? {
191
243
desired_labels. remove ( & existing_label) ;
192
244
}
@@ -200,18 +252,24 @@ fn initialize_labels(
200
252
/// Initializes the required `T-<team>` labels on the repository.
201
253
/// Warns if the labels are found with wrong color.
202
254
fn initialize_issues (
203
- _repository : & str ,
255
+ repository : & str ,
204
256
timeframe : & str ,
205
257
goal_documents : & [ GoalDocument ] ,
206
258
) -> anyhow:: Result < BTreeSet < GithubAction > > {
207
- goal_documents
259
+ // the set of issues we want to exist
260
+ let mut desired_issues: BTreeSet < GithubIssue > = goal_documents
208
261
. iter ( )
209
- . map ( |goal_document| {
210
- Ok ( GithubAction :: CreateIssue {
211
- issue : issue ( timeframe, goal_document) ?,
212
- } )
213
- } )
214
- . collect ( )
262
+ . map ( |goal_document| issue ( timeframe, goal_document) )
263
+ . collect :: < anyhow:: Result < _ > > ( ) ?;
264
+
265
+ // remove any existings that already exist
266
+ let existing_issues = list_issue_titles_in_milestone ( repository, timeframe) ?;
267
+ desired_issues. retain ( |i| !existing_issues. contains ( & i. title ) ) ;
268
+
269
+ Ok ( desired_issues
270
+ . into_iter ( )
271
+ . map ( |issue| GithubAction :: CreateIssue { issue } )
272
+ . collect ( ) )
215
273
}
216
274
217
275
fn issue ( timeframe : & str , document : & GoalDocument ) -> anyhow:: Result < GithubIssue > {
@@ -222,11 +280,19 @@ fn issue(timeframe: &str, document: &GoalDocument) -> anyhow::Result<GithubIssue
222
280
}
223
281
}
224
282
283
+ let mut labels = vec ! [ "C-tracking-issue" . to_string( ) ] ;
284
+ if let Status :: Flagship = document. metadata . status {
285
+ labels. push ( "Flagship Goal" . to_string ( ) ) ;
286
+ }
287
+ for team in document. teams_with_asks ( ) {
288
+ labels. push ( team. gh_label ( ) ) ;
289
+ }
290
+
225
291
Ok ( GithubIssue {
226
292
title : document. metadata . title . clone ( ) ,
227
293
assignees,
228
- body : issue_text ( timeframe, document) ?. replace ( "@" , "%" ) , // HACK to avoid pings
229
- teams : document . teams_with_asks ( ) ,
294
+ body : issue_text ( timeframe, document) ?,
295
+ labels ,
230
296
} )
231
297
}
232
298
@@ -321,7 +387,7 @@ impl Display for GithubAction {
321
387
write ! ( f, "create label `{}` with color `{}`" , name, color)
322
388
}
323
389
GithubAction :: CreateIssue { issue } => {
324
- write ! ( f, "create issue `{}` " , issue. title)
390
+ write ! ( f, "create issue \" {} \" " , issue. title)
325
391
}
326
392
}
327
393
}
@@ -361,7 +427,7 @@ impl GithubAction {
361
427
title,
362
428
assignees,
363
429
body,
364
- teams ,
430
+ labels ,
365
431
} ,
366
432
} => {
367
433
let output = Command :: new ( "gh" )
@@ -374,16 +440,9 @@ impl GithubAction {
374
440
. arg ( "-t" )
375
441
. arg ( & title)
376
442
. arg ( "-l" )
377
- . arg ( format ! (
378
- "C-tracking-issue,{}" ,
379
- teams
380
- . iter( )
381
- . map( |t| t. gh_label( ) )
382
- . collect:: <Vec <_>>( )
383
- . join( "," )
384
- ) )
385
- // .arg("-a")
386
- // .arg(assignees.join(","))
443
+ . arg ( labels. join ( "," ) )
444
+ . arg ( "-a" )
445
+ . arg ( assignees. join ( "," ) )
387
446
. arg ( "-m" )
388
447
. arg ( & timeframe)
389
448
. output ( ) ?;
0 commit comments