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