1
1
use std:: sync:: Arc ;
2
2
use std:: { collections:: HashMap , time:: SystemTime } ;
3
3
4
+ use super :: user:: { GitHubUser , User } ;
4
5
use crate :: bors:: PullRequestStatus ;
5
- use base64:: Engine ;
6
- use chrono:: { DateTime , Utc } ;
7
- use octocrab:: models:: CheckSuiteId ;
8
- use octocrab:: models:: pulls:: MergeableState ;
9
- use octocrab:: models:: repos:: Object ;
10
- use octocrab:: models:: repos:: Object :: Commit ;
11
-
12
6
use crate :: database:: WorkflowStatus ;
13
7
use crate :: github:: { GithubRepoName , PullRequestNumber } ;
14
8
use crate :: permissions:: PermissionType ;
15
9
use crate :: tests:: mocks:: comment:: Comment ;
16
10
use crate :: tests:: mocks:: permissions:: Permissions ;
17
11
use crate :: tests:: mocks:: pull_request:: mock_pull_requests;
12
+ use crate :: tests:: mocks:: workflow:: WorkflowJob ;
18
13
use crate :: tests:: mocks:: { GitHubState , WorkflowRunData , default_pr_number, dynamic_mock_req} ;
14
+ use base64:: Engine ;
15
+ use chrono:: { DateTime , Utc } ;
16
+ use octocrab:: models:: pulls:: MergeableState ;
17
+ use octocrab:: models:: repos:: Object ;
18
+ use octocrab:: models:: repos:: Object :: Commit ;
19
+ use octocrab:: models:: workflows:: { Conclusion , Status , Step } ;
20
+ use octocrab:: models:: { CheckSuiteId , JobId , RunId } ;
19
21
use parking_lot:: Mutex ;
20
22
use serde:: Serialize ;
21
23
use tokio:: sync:: mpsc:: Sender ;
@@ -25,8 +27,6 @@ use wiremock::{
25
27
matchers:: { method, path} ,
26
28
} ;
27
29
28
- use super :: user:: { GitHubUser , User } ;
29
-
30
30
#[ derive( Clone , Debug ) ]
31
31
pub struct CheckRunData {
32
32
pub name : String ,
@@ -386,6 +386,7 @@ pub async fn mock_repo(
386
386
mock_cancel_workflow ( repo. clone ( ) , mock_server) . await ;
387
387
mock_check_runs ( repo. clone ( ) , mock_server) . await ;
388
388
mock_workflow_runs ( repo. clone ( ) , mock_server) . await ;
389
+ mock_workflow_jobs ( repo. clone ( ) , mock_server) . await ;
389
390
mock_config ( repo, mock_server) . await ;
390
391
}
391
392
@@ -580,8 +581,8 @@ async fn mock_workflow_runs(repo: Arc<Mutex<Repo>>, mock_server: &MockServer) {
580
581
#[ derive( serde:: Serialize , Debug ) ]
581
582
struct WorkflowRunResponse {
582
583
id : octocrab:: models:: RunId ,
583
- status : String ,
584
- conclusion : Option < String > ,
584
+ status : Status ,
585
+ conclusion : Option < Conclusion > ,
585
586
}
586
587
587
588
#[ derive( serde:: Serialize , Debug ) ]
@@ -607,25 +608,64 @@ async fn mock_workflow_runs(repo: Arc<Mutex<Repo>>, mock_server: &MockServer) {
607
608
let response = WorkflowRunsResponse {
608
609
workflow_runs : workflow_runs
609
610
. into_iter ( )
610
- . map ( |run| WorkflowRunResponse {
611
- id : run. workflow_run . run_id ,
612
- status : match run. status {
613
- WorkflowStatus :: Pending => "pending" ,
614
- WorkflowStatus :: Success | WorkflowStatus :: Failure => "completed" ,
611
+ . map ( |run| {
612
+ let ( status, conclusion) = status_to_gh ( run. status ) ;
613
+ WorkflowRunResponse {
614
+ id : run. workflow_run . run_id ,
615
+ status,
616
+ conclusion,
615
617
}
616
- . to_string ( ) ,
617
- conclusion : match run. status {
618
- WorkflowStatus :: Success => Some ( "success" . to_string ( ) ) ,
619
- WorkflowStatus :: Failure => Some ( "failure" . to_string ( ) ) ,
620
- _ => None ,
621
- } ,
622
618
} )
623
619
. collect ( ) ,
624
620
} ;
625
621
ResponseTemplate :: new ( 200 ) . set_body_json ( response)
626
622
} ,
627
623
"GET" ,
628
- format ! ( "^/repos/{repo_name}/actions/runs" ) ,
624
+ format ! ( "^/repos/{repo_name}/actions/runs$" ) ,
625
+ )
626
+ . mount ( mock_server)
627
+ . await ;
628
+ }
629
+
630
+ /// Returns (status, conclusion).
631
+ fn status_to_gh ( status : WorkflowStatus ) -> ( Status , Option < Conclusion > ) {
632
+ let conclusion = match status {
633
+ WorkflowStatus :: Success => Some ( Conclusion :: Success ) ,
634
+ WorkflowStatus :: Failure => Some ( Conclusion :: Failure ) ,
635
+ _ => None ,
636
+ } ;
637
+ let status = match status {
638
+ WorkflowStatus :: Pending => Status :: Pending ,
639
+ WorkflowStatus :: Success | WorkflowStatus :: Failure => Status :: Completed ,
640
+ } ;
641
+ ( status, conclusion)
642
+ }
643
+
644
+ async fn mock_workflow_jobs ( repo : Arc < Mutex < Repo > > , mock_server : & MockServer ) {
645
+ let repo_name = repo. lock ( ) . name . clone ( ) ;
646
+ dynamic_mock_req (
647
+ move |_req : & Request , [ run_id] : [ & str ; 1 ] | {
648
+ let repo = repo. lock ( ) ;
649
+ let run_id: RunId = run_id. parse :: < u64 > ( ) . expect ( "Non-integer run id" ) . into ( ) ;
650
+ let workflow_run = repo
651
+ . workflow_runs
652
+ . iter ( )
653
+ . find ( |w| w. workflow_run . run_id == run_id)
654
+ . unwrap_or_else ( || panic ! ( "Workflow run with ID {run_id} not found" ) ) ;
655
+
656
+ let response = GitHubWorkflowJobs {
657
+ total_count : workflow_run. workflow_run . jobs . len ( ) as u64 ,
658
+ jobs : workflow_run
659
+ . workflow_run
660
+ . jobs
661
+ . iter ( )
662
+ . map ( |job| workflow_job_to_gh ( job, run_id) )
663
+ . collect ( ) ,
664
+ } ;
665
+ ResponseTemplate :: new ( 200 ) . set_body_json ( response)
666
+ } ,
667
+ "GET" ,
668
+ format ! ( "^/repos/{repo_name}/actions/runs/(.*)/jobs" ) ,
629
669
)
630
670
. mount ( mock_server)
631
671
. await ;
@@ -923,3 +963,73 @@ struct GitHubRef {
923
963
url : Url ,
924
964
object : Object ,
925
965
}
966
+
967
+ #[ derive( Serialize ) ]
968
+ struct GitHubWorkflowJobs {
969
+ total_count : u64 ,
970
+ jobs : Vec < GitHubWorkflowJob > ,
971
+ }
972
+
973
+ #[ derive( Serialize ) ]
974
+ struct GitHubWorkflowJob {
975
+ id : JobId ,
976
+ run_id : RunId ,
977
+ workflow_name : String ,
978
+ head_branch : String ,
979
+ run_url : Url ,
980
+ run_attempt : u32 ,
981
+
982
+ node_id : String ,
983
+ head_sha : String ,
984
+ url : Url ,
985
+ html_url : Url ,
986
+ status : Status ,
987
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
988
+ conclusion : Option < Conclusion > ,
989
+ created_at : DateTime < Utc > ,
990
+ started_at : DateTime < Utc > ,
991
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
992
+ completed_at : Option < DateTime < Utc > > ,
993
+ name : String ,
994
+ steps : Vec < Step > ,
995
+ check_run_url : String ,
996
+ labels : Vec < String > ,
997
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
998
+ runner_id : Option < u32 > ,
999
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
1000
+ runner_name : Option < String > ,
1001
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
1002
+ runner_group_id : Option < u32 > ,
1003
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
1004
+ runner_group_name : Option < String > ,
1005
+ }
1006
+
1007
+ fn workflow_job_to_gh ( job : & WorkflowJob , run_id : RunId ) -> GitHubWorkflowJob {
1008
+ let WorkflowJob { id, status } = job;
1009
+ let ( status, conclusion) = status_to_gh ( * status) ;
1010
+ GitHubWorkflowJob {
1011
+ id : * id,
1012
+ run_id,
1013
+ workflow_name : "" . to_string ( ) ,
1014
+ head_branch : "" . to_string ( ) ,
1015
+ run_url : "https://test.com" . parse ( ) . unwrap ( ) ,
1016
+ run_attempt : 0 ,
1017
+ node_id : "" . to_string ( ) ,
1018
+ head_sha : "" . to_string ( ) ,
1019
+ url : "https://test.com" . parse ( ) . unwrap ( ) ,
1020
+ html_url : format ! ( "https://github.com/job-logs/{id}" ) . parse ( ) . unwrap ( ) ,
1021
+ status,
1022
+ conclusion,
1023
+ created_at : Default :: default ( ) ,
1024
+ started_at : Default :: default ( ) ,
1025
+ completed_at : None ,
1026
+ name : format ! ( "Job {id}" ) ,
1027
+ steps : vec ! [ ] ,
1028
+ check_run_url : "" . to_string ( ) ,
1029
+ labels : vec ! [ ] ,
1030
+ runner_id : None ,
1031
+ runner_name : None ,
1032
+ runner_group_id : None ,
1033
+ runner_group_name : None ,
1034
+ }
1035
+ }
0 commit comments