diff --git a/src/commands/up.rs b/src/commands/up.rs index 42efd0f5f..14384f7b4 100644 --- a/src/commands/up.rs +++ b/src/commands/up.rs @@ -38,6 +38,10 @@ pub struct Args { /// Don't attach to the log stream detach: bool, + #[clap(short, long)] + /// Only stream build logs and exit after it's done + cicd: bool, + #[clap(short, long)] /// Service to deploy to (defaults to linked service) service: Option, @@ -61,6 +65,11 @@ pub struct UpErrorResponse { pub message: String, } +enum UpExitReason { + Deployed, + Failed, +} + pub async fn get_service_to_deploy( configs: &Configs, client: &Client, @@ -294,34 +303,45 @@ pub async fn command(args: Args, _json: bool) -> Result<()> { return Ok(()); } - // Stream both build and deploy logs let build_deployment_id = deployment_id.clone(); let deploy_deployment_id = deployment_id.clone(); - let tasks = vec![ - tokio::task::spawn(async move { - if let Err(e) = - stream_build_logs(build_deployment_id, |log| println!("{}", log.message)).await - { - eprintln!("Failed to stream build logs: {}", e); - } - }), - tokio::task::spawn(async move { + // Create vector of log streaming tasks + // Always stream build logs + let mut tasks = vec![tokio::task::spawn(async move { + if let Err(e) = + stream_build_logs(build_deployment_id, |log| println!("{}", log.message)).await + { + eprintln!("Failed to stream build logs: {}", e); + } + })]; + + // Stream deploy logs only if cicd flag is not set + if !args.cicd { + tasks.push(tokio::task::spawn(async move { if let Err(e) = stream_deploy_logs(deploy_deployment_id, |log| println!("{}", log.message)).await { eprintln!("Failed to stream deploy logs: {}", e); } - }), - ]; + })); + } // If the build fails, we want to terminate the process tokio::task::spawn(async move { - match wait_for_failure(deployment_id.clone()).await { - Ok(_) => { - println!("{}", "Build failed".red().bold()); - std::process::exit(1); - } + match wait_for_exit_reason(deployment_id.clone()).await { + Ok(reason) => match reason { + UpExitReason::Deployed => { + if args.cicd { + println!("{}", "Deploy complete".green().bold()); + std::process::exit(0); + } + } + _ => { + println!("{}", "Build failed".red().bold()); + std::process::exit(1); + } + }, Err(e) => { eprintln!("Failed to fetch deployment status: {}", e); } @@ -333,7 +353,7 @@ pub async fn command(args: Args, _json: bool) -> Result<()> { Ok(()) } -async fn wait_for_failure(deployment_id: String) -> Result<(), anyhow::Error> { +async fn wait_for_exit_reason(deployment_id: String) -> Result { let configs = Configs::new()?; let client = GQLClient::new_authorized(&configs)?; @@ -341,11 +361,11 @@ async fn wait_for_failure(deployment_id: String) -> Result<(), anyhow::Error> { tokio::time::sleep(Duration::from_secs(5)).await; if let Ok(deployment) = get_deployment(&client, &configs, deployment_id.clone()).await { - if deployment.status == DeploymentStatus::FAILED { - break; + match deployment.status { + DeploymentStatus::SUCCESS => return Ok(UpExitReason::Deployed), + DeploymentStatus::FAILED => return Ok(UpExitReason::Failed), + _ => {} } } } - - Ok(()) }