Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cargo-shuttle): log reconnects and improved error messages #853

Merged
merged 9 commits into from
May 14, 2023
2 changes: 1 addition & 1 deletion cargo-shuttle/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ pub struct LoginArgs {
pub api_key: Option<String>,
}

#[derive(Parser)]
#[derive(Parser, Clone)]
iamwacko marked this conversation as resolved.
Show resolved Hide resolved
pub struct DeployArgs {
/// Allow deployment with uncommited files
#[arg(long)]
Expand Down
1 change: 1 addition & 0 deletions cargo-shuttle/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use tokio_tungstenite::{connect_async, MaybeTlsStream, WebSocketStream};
use tracing::error;
use uuid::Uuid;

#[derive(Clone)]
iamwacko marked this conversation as resolved.
Show resolved Hide resolved
pub struct Client {
api_url: ApiUrl,
api_key: Option<ApiKey>,
Expand Down
98 changes: 71 additions & 27 deletions cargo-shuttle/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,33 +902,55 @@ impl Shuttle {
.get_logs_ws(self.ctx.project_name(), &deployment.id)
.await?;

while let Some(Ok(msg)) = stream.next().await {
if let tokio_tungstenite::tungstenite::Message::Text(line) = msg {
let log_item: shuttle_common::LogItem =
serde_json::from_str(&line).expect("to parse log line");

match log_item.state {
shuttle_common::deployment::State::Queued
| shuttle_common::deployment::State::Building
| shuttle_common::deployment::State::Built
| shuttle_common::deployment::State::Loading => {
println!("{log_item}");
}
shuttle_common::deployment::State::Crashed => {
println!();
println!("{}", "Deployment crashed".red());
println!("Run the following for more details");
println!();
print!("cargo shuttle logs {}", deployment.id);
println!();

return Ok(CommandOutcome::DeploymentFailure);
}
shuttle_common::deployment::State::Running
| shuttle_common::deployment::State::Completed
| shuttle_common::deployment::State::Stopped
| shuttle_common::deployment::State::Unknown => break,
let mut last_state: shuttle_common::deployment::State =
shuttle_common::deployment::State::Unknown;
iamwacko marked this conversation as resolved.
Show resolved Hide resolved

loop {
let mesg = stream.next().await;
if let Some(Ok(msg)) = mesg {
iamwacko marked this conversation as resolved.
Show resolved Hide resolved
if let tokio_tungstenite::tungstenite::Message::Text(line) = msg {
let log_item: shuttle_common::LogItem =
serde_json::from_str(&line).expect("to parse log line");

match log_item.state.clone() {
iulianbarbu marked this conversation as resolved.
Show resolved Hide resolved
shuttle_common::deployment::State::Queued
| shuttle_common::deployment::State::Building
| shuttle_common::deployment::State::Built
| shuttle_common::deployment::State::Loading => {
last_state = log_item.state.clone();
println!("{log_item}");
}
shuttle_common::deployment::State::Crashed => {
println!();
println!("{}", "Deployment crashed".red());
println!();
println!("Run the following for more details");
println!();
print!("cargo shuttle logs {}", &deployment.id);
println!();
if last_state == shuttle_common::deployment::State::Unknown {
println!("Note: Deploy failed immediately");
};

return Ok(CommandOutcome::DeploymentFailure);
}
shuttle_common::deployment::State::Running
| shuttle_common::deployment::State::Completed
| shuttle_common::deployment::State::Stopped
| shuttle_common::deployment::State::Unknown => {
last_state = log_item.state;
break;
}
};
}
} else {
println!("Reconnecting websockets logging");
// A wait time short enough for not much state to have changed, long enough that
// the terminal isn't completely spammed
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
stream = client
.get_logs_ws(self.ctx.project_name(), &deployment.id)
.await?;
}
}

Expand All @@ -952,7 +974,29 @@ impl Shuttle {
_ => CommandOutcome::Ok,
})
} else {
println!("Deployment has not entered the running state");
println!("{}", "Deployment has not entered the running state".red());
println!();
match last_state {
shuttle_common::deployment::State::Stopped => {
println!("This may be because the deployment is stopped")
}
shuttle_common::deployment::State::Completed => {
println!("This may be because the deployment is completed")
}
shuttle_common::deployment::State::Unknown => {
println!("This may be because deployment was in an unknown state")
}
shuttle_common::deployment::State::Running => {
println!("Deployment was running, check the logs for details")
}
iamwacko marked this conversation as resolved.
Show resolved Hide resolved
_ => println!("This should not be possible"),
iamwacko marked this conversation as resolved.
Show resolved Hide resolved
}

println!();
println!("Run the following for more details");
println!();
println!("cargo shuttle logs {}", &deployment.id);
println!();

Ok(CommandOutcome::DeploymentFailure)
}
Expand Down
2 changes: 1 addition & 1 deletion common/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use strum::Display;
#[cfg(feature = "openapi")]
use utoipa::ToSchema;

#[derive(Clone, Debug, Deserialize, Display, Serialize)]
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Display, Serialize)]
oddgrd marked this conversation as resolved.
Show resolved Hide resolved
#[serde(rename_all = "lowercase")]
#[strum(serialize_all = "lowercase")]
#[cfg_attr(feature = "openapi", derive(ToSchema))]
Expand Down