@@ -7,10 +7,10 @@ use std::collections::HashMap;
7
7
use std:: io:: { stdin, stdout, Write } ;
8
8
9
9
use clap:: { ArgMatches , Clap , FromArgMatches } ;
10
- use futures_util:: future:: { join_all, try_join_all } ;
11
- use tokio:: try_join ;
10
+ use futures_util:: future:: join_all;
11
+ use tokio:: join ;
12
12
13
- use crate as deploy;
13
+ use crate :: { self as deploy, CmdOverrides , DeployDefs } ;
14
14
use crate :: push:: { PushProfileData , PushProfileError } ;
15
15
16
16
use self :: deploy:: { DeployFlake , ParseFlakeError } ;
@@ -600,25 +600,111 @@ async fn run_deploy(
600
600
}
601
601
} ) ;
602
602
603
- try_join ! (
603
+ async fn deploy_profiles_to_host < ' a > ( ( host, profiles) : ( & str , Vec < & ' a PushProfileData < ' a > > ) ) -> Result < ( ) , ( String , String , PushProfileError ) > {
604
+ for profile in & profiles {
605
+ deploy:: push:: build_profile ( profile) . await . map_err ( |e| ( host. to_string ( ) , profile. deploy_data . profile_name . to_string ( ) , e) ) ?;
606
+ } ;
607
+ Ok ( ( ) )
608
+ }
609
+
610
+ let ( remote_results, local_results) = join ! (
611
+ // remote builds can be run asynchronously (per host)
612
+ join_all( remote_build_map. into_iter( ) . map( deploy_profiles_to_host) ) ,
613
+
604
614
// remote builds can be run asynchronously (per host)
605
- try_join_all( remote_build_map. into_iter( ) . map( deploy_profiles_to_host) ) ,
606
- async {
615
+ async move {
616
+ let mut build_results = Vec :: new( ) ;
617
+ let mut push_futures = Vec :: new( ) ;
618
+
607
619
// run local builds synchronously to prevent hardware deadlocks
608
- for data in & local_builds {
609
- deploy:: push:: build_profile( data) . await . unwrap( ) ;
620
+ for data in local_builds {
621
+ let res = deploy:: push:: build_profile( & data) . await ;
622
+ if res. is_ok( ) {
623
+ // unfortunately, all of this is necessary to please the borrow checker
624
+ // since deploy_data is a nested struct of references, the spawned process
625
+ // could outlive the scope of this function where the references' values are
626
+ // defined
627
+ let node_name = data. deploy_data. node_name. to_string( ) ;
628
+ let node = data. deploy_data. node. clone( ) ;
629
+ let profile_name = data. deploy_data. profile_name. to_string( ) ;
630
+ let profile = data. deploy_data. profile. clone( ) ;
631
+ let cmd_overrides = data. deploy_data. cmd_overrides. clone( ) ;
632
+ let merged_settings = data. deploy_data. merged_settings. clone( ) ;
633
+ let debug_logs = data. deploy_data. debug_logs. clone( ) ;
634
+ let log_dir = data. deploy_data. log_dir. map( |x| x. to_string( ) ) ;
635
+ let extra_build_args: Vec <String > = data. extra_build_args. iter( ) . cloned( ) . collect( ) ;
636
+ let result_path = data. result_path. map( |x| x. to_string( ) ) ;
637
+ let keep_result = data. keep_result. clone( ) ;
638
+ let deploy_defs = data. deploy_defs. clone( ) ;
639
+ let repo = data. repo. to_string( ) ;
640
+ let check_sigs = data. check_sigs. clone( ) ;
641
+
642
+ let handle = tokio:: spawn( async move {
643
+ let deploy_data = deploy:: DeployData {
644
+ node_name: & node_name,
645
+ node: & node,
646
+ profile_name: & profile_name,
647
+ profile: & profile,
648
+ cmd_overrides: & cmd_overrides,
649
+ merged_settings,
650
+ debug_logs,
651
+ log_dir: log_dir. as_deref( )
652
+ } ;
653
+
654
+ let data = PushProfileData {
655
+ check_sigs,
656
+ repo: & repo,
657
+ deploy_data: & deploy_data,
658
+ deploy_defs: & deploy_defs,
659
+ keep_result,
660
+ result_path: result_path. as_deref( ) ,
661
+ extra_build_args: & extra_build_args,
662
+ supports_flakes: true ,
663
+ } ;
664
+
665
+ deploy:: push:: push_profile( & data) . await
666
+ } ) ;
667
+ push_futures. push( handle) ;
668
+ }
669
+ build_results. push( res) ;
610
670
}
611
671
612
- // push all profiles asynchronously
613
- join_all( local_builds. into_iter( ) . map( |data| async {
614
- let data = data;
615
- deploy:: push:: push_profile( & data) . await
616
- } ) ) . await ;
672
+ let push_results = join_all( push_futures) . await ;
617
673
618
- Ok ( ( ) )
674
+ ( build_results , push_results )
619
675
}
620
- ) ? ;
676
+ ) ;
621
677
678
+ for result in local_results. 0 {
679
+ match result {
680
+ Err ( e) => {
681
+ error ! ( "failed building profile locally: {:?}" , e) ;
682
+ return Err ( RunDeployError :: PushProfile ( e) ) ;
683
+ } ,
684
+ _ => ( ) ,
685
+ }
686
+ }
687
+
688
+ for result in local_results. 1 {
689
+ match result {
690
+ Err ( e) => panic ! ( "failed to join future: {}, please open a bug report" , e) ,
691
+ Ok ( Err ( e) ) => {
692
+ error ! ( "failed pushing profile: {:?}" , e) ;
693
+ return Err ( RunDeployError :: PushProfile ( e) ) ;
694
+ } ,
695
+ _ => ( ) ,
696
+ }
697
+ }
698
+
699
+ for result in remote_results {
700
+ match result {
701
+ Err ( ( host, profile, e) ) => {
702
+ error ! ( "failed building profile {} on host {}: {:?}" , profile, host, e) ;
703
+ return Err ( RunDeployError :: PushProfile ( e) ) ;
704
+ } ,
705
+ _ => ( ) ,
706
+ }
707
+ }
622
708
623
709
let mut succeeded: Vec < ( & deploy:: DeployData , & deploy:: DeployDefs ) > = vec ! [ ] ;
624
710
@@ -750,9 +836,3 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> {
750
836
Ok ( ( ) )
751
837
}
752
838
753
- async fn deploy_profiles_to_host < ' a > ( ( _host, profiles) : ( & str , Vec < & ' a PushProfileData < ' a > > ) ) -> Result < ( ) , PushProfileError > {
754
- for profile in & profiles {
755
- deploy:: push:: build_profile ( profile) . await ?;
756
- } ;
757
- Ok ( ( ) )
758
- }
0 commit comments