@@ -3,24 +3,32 @@ use std::time::Duration;
3
3
4
4
use anyhow:: Context ;
5
5
use chrono:: { DateTime , Utc } ;
6
+ use futures:: FutureExt ;
7
+ use futures:: future:: join_all;
6
8
7
9
use crate :: bors:: Comment ;
8
10
use crate :: bors:: RepositoryState ;
9
11
use crate :: bors:: handlers:: trybuild:: cancel_build_workflows;
12
+ use crate :: bors:: mergeable_queue:: MergeableQueueSender ;
10
13
use crate :: database:: BuildStatus ;
11
14
use crate :: { PgDbClient , TeamApiClient } ;
12
15
13
16
pub async fn refresh_repository (
14
17
repo : Arc < RepositoryState > ,
15
18
db : Arc < PgDbClient > ,
16
19
team_api_client : & TeamApiClient ,
20
+ mergeable_queue_tx : MergeableQueueSender ,
17
21
) -> anyhow:: Result < ( ) > {
18
22
let repo = repo. as_ref ( ) ;
19
- if let ( Ok ( _) , _, Ok ( _) ) = tokio:: join!(
20
- cancel_timed_out_builds( repo, db. as_ref( ) ) ,
21
- reload_permission( repo, team_api_client) ,
22
- reload_config( repo)
23
- ) {
23
+ let results = join_all ( [
24
+ cancel_timed_out_builds ( repo, db. as_ref ( ) ) . boxed ( ) ,
25
+ reload_permission ( repo, team_api_client) . boxed ( ) ,
26
+ reload_config ( repo) . boxed ( ) ,
27
+ reload_unknown_mergeable_prs ( repo, db. as_ref ( ) , mergeable_queue_tx) . boxed ( ) ,
28
+ ] )
29
+ . await ;
30
+
31
+ if results. iter ( ) . all ( |result| result. is_ok ( ) ) {
24
32
Ok ( ( ) )
25
33
} else {
26
34
tracing:: error!( "Failed to refresh repository" ) ;
@@ -79,6 +87,27 @@ async fn reload_permission(
79
87
Ok ( ( ) )
80
88
}
81
89
90
+ async fn reload_unknown_mergeable_prs (
91
+ repo : & RepositoryState ,
92
+ db : & PgDbClient ,
93
+ mergeable_queue : MergeableQueueSender ,
94
+ ) -> anyhow:: Result < ( ) > {
95
+ let prs = db
96
+ . get_prs_with_unknown_mergeable_state ( repo. repository ( ) )
97
+ . await ?;
98
+
99
+ tracing:: info!(
100
+ "Refreshing {} PR(s) with unknown mergeable state" ,
101
+ prs. len( )
102
+ ) ;
103
+
104
+ for pr in prs {
105
+ mergeable_queue. enqueue ( repo. repository ( ) . clone ( ) , pr. number ) ;
106
+ }
107
+
108
+ Ok ( ( ) )
109
+ }
110
+
82
111
async fn reload_config ( repo : & RepositoryState ) -> anyhow:: Result < ( ) > {
83
112
let config = repo. client . load_config ( ) . await ?;
84
113
repo. config . store ( Arc :: new ( config) ) ;
@@ -109,8 +138,9 @@ fn elapsed_time(date: DateTime<Utc>) -> Duration {
109
138
mod tests {
110
139
use crate :: bors:: handlers:: WAIT_FOR_WORKFLOW_STARTED ;
111
140
use crate :: bors:: handlers:: refresh:: MOCK_TIME ;
141
+ use crate :: database:: { MergeableState , OctocrabMergeableState } ;
112
142
use crate :: tests:: mocks:: {
113
- BorsBuilder , GitHubState , WorkflowEvent , default_repo_name, run_test,
143
+ BorsBuilder , GitHubState , WorkflowEvent , default_pr_number , default_repo_name, run_test,
114
144
} ;
115
145
use chrono:: Utc ;
116
146
use std:: future:: Future ;
@@ -133,6 +163,7 @@ timeout = 3600
133
163
"# ,
134
164
)
135
165
}
166
+
136
167
#[ sqlx:: test]
137
168
async fn refresh_do_nothing_before_timeout ( pool : sqlx:: PgPool ) {
138
169
BorsBuilder :: new ( pool)
@@ -207,6 +238,51 @@ timeout = 3600
207
238
gh. check_cancelled_workflows ( default_repo_name ( ) , & [ 1 ] ) ;
208
239
}
209
240
241
+ #[ sqlx:: test]
242
+ async fn refresh_enqueues_unknown_mergeable_prs ( pool : sqlx:: PgPool ) {
243
+ run_test ( pool, |mut tester| async {
244
+ tester
245
+ . edit_pr ( default_repo_name ( ) , default_pr_number ( ) , |pr| {
246
+ pr. mergeable_state = OctocrabMergeableState :: Unknown
247
+ } )
248
+ . await ?;
249
+ tester
250
+ . wait_for_default_pr ( |pr| pr. mergeable_state == MergeableState :: Unknown )
251
+ . await ?;
252
+ tester
253
+ . default_repo ( )
254
+ . lock ( )
255
+ . get_pr_mut ( default_pr_number ( ) )
256
+ . mergeable_state = OctocrabMergeableState :: Dirty ;
257
+ tester. refresh ( ) . await ;
258
+ tester
259
+ . wait_for_default_pr ( |pr| pr. mergeable_state == MergeableState :: HasConflicts )
260
+ . await ?;
261
+ Ok ( tester)
262
+ } )
263
+ . await ;
264
+ }
265
+
266
+ #[ sqlx:: test]
267
+ async fn refresh_enqueues_no_known_mergeable_prs ( pool : sqlx:: PgPool ) {
268
+ run_test ( pool, |mut tester| async {
269
+ tester
270
+ . edit_pr ( default_repo_name ( ) , default_pr_number ( ) , |pr| {
271
+ pr. mergeable_state = OctocrabMergeableState :: Clean
272
+ } )
273
+ . await ?;
274
+ tester
275
+ . wait_for_default_pr ( |pr| pr. mergeable_state == MergeableState :: Mergeable )
276
+ . await ?;
277
+ tester. refresh ( ) . await ;
278
+ tester
279
+ . wait_for_default_pr ( |pr| pr. mergeable_state == MergeableState :: Mergeable )
280
+ . await ?;
281
+ Ok ( tester)
282
+ } )
283
+ . await ;
284
+ }
285
+
210
286
async fn with_mocked_time < Fut : Future < Output = ( ) > > ( in_future : Duration , future : Fut ) {
211
287
// It is important to use this function only with a single threaded runtime,
212
288
// otherwise the `MOCK_TIME` variable might get mixed up between different threads.
0 commit comments