Skip to content

Commit 456a846

Browse files
Alex Holmbergclaude
authored andcommitted
fix(deploy-status): check actual service readiness for Cloud Runner
The Backstage task can show "completed" (100%) when infrastructure is provisioned, but Cloud Runner actual deployment (build + deploy) takes longer. Added optional project_id and service_name params that when provided: - Also check list_deployments for actual service status - Look for public_url which indicates service is truly ready - Return service_ready: true only when URL is available - Show helpful note when task is 100% but service still deploying Now the agent can accurately report when a Cloud Runner service is actually ready to serve traffic, not just when infrastructure is ready. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0c9f957 commit 456a846

1 file changed

Lines changed: 79 additions & 15 deletions

File tree

src/agent/tools/platform/get_deployment_status.rs

Lines changed: 79 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ use crate::platform::api::{PlatformApiClient, PlatformApiError};
1515
pub struct GetDeploymentStatusArgs {
1616
/// The task ID to check status for
1717
pub task_id: String,
18+
/// Optional project ID to check actual deployment status (for public_url)
19+
pub project_id: Option<String>,
20+
/// Optional service name to find the specific deployment
21+
pub service_name: Option<String>,
1822
}
1923

2024
/// Error type for get deployment status operations
@@ -46,22 +50,28 @@ impl Tool for GetDeploymentStatusTool {
4650
async fn definition(&self, _prompt: String) -> ToolDefinition {
4751
ToolDefinition {
4852
name: Self::NAME.to_string(),
49-
description: r#"Get the status of a deployment task.
53+
description: r#"Get the status of a deployment task and optionally check the actual service status.
5054
5155
Returns the current status of a deployment, including progress percentage,
52-
current step, and overall status.
56+
current step, overall status, and optionally the public URL if the service is ready.
57+
58+
**IMPORTANT for Cloud Runner:**
59+
The task may show "completed" when infrastructure is provisioned, but the actual
60+
service build and deployment takes longer. Pass project_id and service_name to
61+
also check if the service has a public URL (meaning it's actually ready).
5362
5463
**Status Values:**
5564
- Task status: "processing", "completed", "failed"
5665
- Overall status: "generating", "building", "deploying", "healthy", "failed"
66+
- Service ready: Only when public_url is available
5767
5868
**Prerequisites:**
5969
- User must be authenticated via `sync-ctl auth login`
6070
- A deployment must have been triggered (use trigger_deployment first)
6171
6272
**Use Cases:**
6373
- Monitor deployment progress after triggering
64-
- Check if a deployment has completed
74+
- Check if a deployment has completed AND is actually serving traffic
6575
- Get error details if deployment failed"#
6676
.to_string(),
6777
parameters: json!({
@@ -70,6 +80,14 @@ current step, and overall status.
7080
"task_id": {
7181
"type": "string",
7282
"description": "The deployment task ID (from trigger_deployment response)"
83+
},
84+
"project_id": {
85+
"type": "string",
86+
"description": "Optional: Project ID to check actual service status and public URL"
87+
},
88+
"service_name": {
89+
"type": "string",
90+
"description": "Optional: Service name to find the specific deployment"
7391
}
7492
},
7593
"required": ["task_id"]
@@ -99,46 +117,92 @@ current step, and overall status.
99117
}
100118
};
101119

102-
// Get the deployment status
120+
// Get the deployment status (Backstage task)
103121
match client.get_deployment_status(&args.task_id).await {
104122
Ok(status) => {
105-
let is_complete = status.status == "completed";
123+
let task_complete = status.status == "completed";
106124
let is_failed = status.status == "failed" || status.overall_status == "failed";
107125
let is_healthy = status.overall_status == "healthy";
108126

127+
// Also check actual deployment if project_id and service_name provided
128+
// This is crucial for Cloud Runner where task completes but service takes longer
129+
let (service_status, public_url, service_ready) = if let (Some(project_id), Some(service_name)) = (&args.project_id, &args.service_name) {
130+
match client.list_deployments(project_id, Some(10)).await {
131+
Ok(paginated) => {
132+
// Find the deployment for this service
133+
let deployment = paginated.data.iter()
134+
.find(|d| d.service_name.eq_ignore_ascii_case(service_name));
135+
136+
match deployment {
137+
Some(d) => (
138+
Some(d.status.clone()),
139+
d.public_url.clone(),
140+
d.public_url.is_some() && d.status == "running"
141+
),
142+
None => (None, None, false)
143+
}
144+
}
145+
Err(_) => (None, None, false)
146+
}
147+
} else {
148+
(None, None, false)
149+
};
150+
151+
// True completion = task done AND (service has URL or no service check requested)
152+
let truly_ready = if args.project_id.is_some() {
153+
service_ready
154+
} else {
155+
is_healthy
156+
};
157+
109158
let mut result = json!({
110159
"success": true,
111160
"task_id": args.task_id,
112-
"status": status.status,
113-
"progress": status.progress,
161+
"task_status": status.status,
162+
"task_progress": status.progress,
114163
"current_step": status.current_step,
115164
"overall_status": status.overall_status,
116165
"overall_message": status.overall_message,
117-
"is_complete": is_complete,
166+
"task_complete": task_complete,
118167
"is_failed": is_failed,
119-
"is_healthy": is_healthy
168+
"service_ready": truly_ready
120169
});
121170

171+
// Add service-specific info if we checked
172+
if let Some(svc_status) = service_status {
173+
result["service_status"] = json!(svc_status);
174+
}
175+
if let Some(url) = &public_url {
176+
result["public_url"] = json!(url);
177+
}
178+
122179
// Add error details if failed
123180
if let Some(error) = &status.error {
124181
result["error"] = json!(error);
125182
}
126183

127-
// Add next steps based on status
184+
// Add next steps based on actual status
128185
if is_failed {
129186
result["next_steps"] = json!([
130187
"Review the error message for details",
131188
"Check the deployment configuration",
132189
"Verify the code builds successfully locally",
133190
"Try triggering a new deployment after fixing the issue"
134191
]);
135-
} else if is_healthy {
192+
} else if truly_ready && public_url.is_some() {
193+
result["next_steps"] = json!([
194+
format!("Service is live at: {}", public_url.as_ref().unwrap()),
195+
"Deployment completed successfully!",
196+
"Use get_service_logs to view container logs"
197+
]);
198+
} else if task_complete && !truly_ready {
136199
result["next_steps"] = json!([
137-
"Deployment completed successfully",
138-
"Use list_deployments to see the deployed service details",
139-
"Check the public_url to access the deployed service"
200+
"Infrastructure task completed, but service is still deploying",
201+
"Cloud Runner is building and deploying your container",
202+
"Call get_deployment_status again in 30-60 seconds to check for public_url"
140203
]);
141-
} else if !is_complete {
204+
result["note"] = json!("Task shows 100% but service is still being built/deployed. This is normal for Cloud Runner.");
205+
} else if !task_complete {
142206
result["next_steps"] = json!([
143207
format!("Deployment is {} ({}% complete)", status.overall_status, status.progress),
144208
"Call get_deployment_status again to check progress"

0 commit comments

Comments
 (0)