mz_deploy/cli/commands/
describe.rs1use crate::cli::CliError;
13use crate::client::{Client, DeploymentDetails, DeploymentKind};
14use crate::config::Settings;
15use crate::log;
16use crate::project::ir::object_id::ObjectId;
17use chrono::{DateTime, Local};
18use owo_colors::{OwoColorize, Stream, Style};
19use std::collections::BTreeMap;
20use std::fmt;
21
22#[derive(serde::Serialize)]
23struct DescribeOutput {
24 deploy_id: String,
25 details: DeploymentDetails,
26 objects: BTreeMap<ObjectId, String>,
27}
28
29impl fmt::Display for DescribeOutput {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 let deployment_style = Style::new().yellow().bold();
32 writeln!(
33 f,
34 "{} {} [{}]",
35 "deployment".if_supports_color(Stream::Stderr, |t| deployment_style.style(t)),
36 self.deploy_id
37 .if_supports_color(Stream::Stderr, |t| t.cyan()),
38 self.details
39 .kind
40 .to_string()
41 .if_supports_color(Stream::Stderr, |t| t.dimmed()),
42 )?;
43
44 if let Some(commit_sha) = &self.details.git_commit {
45 writeln!(
46 f,
47 "{}: {}",
48 "Commit".if_supports_color(Stream::Stderr, |t| t.dimmed()),
49 commit_sha
50 )?;
51 }
52
53 writeln!(
54 f,
55 "{}: {}",
56 "Deployed by".if_supports_color(Stream::Stderr, |t| t.dimmed()),
57 self.details
58 .deployed_by
59 .if_supports_color(Stream::Stderr, |t| t.yellow())
60 )?;
61
62 let deployed_datetime: DateTime<Local> = self.details.deployed_at.with_timezone(&Local);
63 let deployed_str = deployed_datetime
64 .format("%a %b %d %H:%M:%S %Y %z")
65 .to_string();
66 writeln!(
67 f,
68 "{}: {}",
69 "Deployed at".if_supports_color(Stream::Stderr, |t| t.dimmed()),
70 deployed_str
71 )?;
72
73 if let Some(promoted) = self.details.promoted_at {
74 if self.details.kind == DeploymentKind::Objects {
75 let promoted_datetime: DateTime<Local> = promoted.with_timezone(&Local);
76 let promoted_str = promoted_datetime
77 .format("%a %b %d %H:%M:%S %Y %z")
78 .to_string();
79 writeln!(
80 f,
81 "{}: {}",
82 "Promoted at".if_supports_color(Stream::Stderr, |t| t.dimmed()),
83 promoted_str
84 )?;
85 }
86 } else {
87 writeln!(
88 f,
89 "{}: {}",
90 "Status".if_supports_color(Stream::Stderr, |t| t.dimmed()),
91 "staging".if_supports_color(Stream::Stderr, |t| t.yellow())
92 )?;
93 }
94
95 writeln!(f)?;
96
97 writeln!(
99 f,
100 "{} ({}):",
101 "Schemas".if_supports_color(Stream::Stderr, |t| t.bold()),
102 self.details.schemas.len()
103 )?;
104 for sq in &self.details.schemas {
105 writeln!(
106 f,
107 " {}.{}",
108 sq.database
109 .if_supports_color(Stream::Stderr, |t| t.dimmed()),
110 sq.schema
111 )?;
112 }
113 writeln!(f)?;
114
115 writeln!(
117 f,
118 "{} ({}):",
119 "Objects".if_supports_color(Stream::Stderr, |t| t.bold()),
120 self.objects.len()
121 )?;
122 for (object_id, hash) in &self.objects {
123 let short_hash = &hash[..hash.len().min(12)];
124 writeln!(
125 f,
126 " {} {}",
127 object_id
128 .to_string()
129 .if_supports_color(Stream::Stderr, |t| t.dimmed()),
130 short_hash.if_supports_color(Stream::Stderr, |t| t.dimmed())
131 )?;
132 }
133
134 Ok(())
135 }
136}
137
138pub async fn run(settings: &Settings, deploy_id: &str) -> Result<(), CliError> {
158 let profile = settings.connection();
159 let client = Client::connect_with_profile(profile.clone())
160 .await
161 .map_err(CliError::Connection)?;
162
163 super::setup::verify(&client, settings.emulator()).await?;
164 super::setup::validate_connection(&client, settings.emulator()).await?;
165
166 let details = client
168 .deployments()
169 .get_deployment_details(deploy_id)
170 .await?;
171 let Some(details) = details else {
172 return Err(CliError::Message(format!(
173 "Deployment '{}' not found",
174 deploy_id
175 )));
176 };
177
178 let snapshot = client
180 .deployments()
181 .get_deployment_objects(Some(deploy_id))
182 .await?;
183
184 let output = DescribeOutput {
185 deploy_id: deploy_id.to_string(),
186 details,
187 objects: snapshot.objects,
188 };
189 log::output(&output);
190
191 Ok(())
192}