Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions crates/alien-deploy-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ libc = "0.2"

[target.'cfg(windows)'.dependencies]
fs2 = "0.4"

[dev-dependencies]
httpmock = { workspace = true }
118 changes: 118 additions & 0 deletions crates/alien-deploy-cli/src/commands/up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ impl From<DeployConfigNetwork> for NetworkSettings {
mod tests {
use super::*;
use clap::Parser;
use httpmock::{Method::PATCH, MockServer};
use std::io::Write;

#[test]
Expand All @@ -295,6 +296,54 @@ mod tests {
assert!(!requires_install_context(Platform::Test));
}

#[tokio::test]
async fn hosted_compute_update_uses_deployment_token_and_exact_payload() {
let server = MockServer::start_async().await;
let mock = server
.mock_async(|when, then| {
when.method(PATCH)
.path("/v1/deployments/dep_example/compute")
.header("authorization", "Bearer deployment-secret")
.json_body(serde_json::json!({
"compute": {
"pools": {
"workers": {
"mode": "fixed",
"machines": 2,
"machine": "m7i.large"
}
}
}
}));
then.status(200).json_body(serde_json::json!({
"outcome": "accepted",
"operation": null
}));
})
.await;
let compute: ComputeSettings = serde_json::from_value(serde_json::json!({
"pools": {
"workers": {
"mode": "fixed",
"machines": 2,
"machine": "m7i.large"
}
}
}))
.expect("valid compute settings");

update_hosted_compute_settings(
&server.base_url(),
"deployment-secret",
"dep_example",
&compute,
)
.await
.expect("hosted update should succeed");

mock.assert_async().await;
}

#[test]
fn stable_channel_accepts_exact_semver_tag() {
assert_eq!(
Expand Down Expand Up @@ -1263,6 +1312,44 @@ pub async fn up_command(args: UpArgs, embedded_config: Option<&DeployCliConfig>)
})?
.into_inner();

let hosted_platform =
manager_url.trim_end_matches('/') != resolved.base_url.trim_end_matches('/');
if current_deployment.status == "running"
&& init.deployment_model == DeploymentModel::Push
&& hosted_platform
&& stack_settings.compute.is_some()
{
let current_stack_settings: StackSettings = current_deployment
.stack_settings
.clone()
.map(serde_json::from_value)
.transpose()
.into_alien_error()
.context(ErrorData::ConfigurationError {
message: "Failed to deserialize current stack settings".to_string(),
})?
.unwrap_or_default();
if current_stack_settings.compute != stack_settings.compute {
update_hosted_compute_settings(
&resolved.base_url,
&effective_token,
&deployment_id,
stack_settings.compute.as_ref().expect("checked above"),
)
.await?;
output::success(&format!(
"Deployment '{}' compute update was accepted by the hosted manager.",
name
));
return Ok(());
}
output::success(&format!(
"Deployment '{}' already has the requested compute settings.",
name
));
return Ok(());
Comment on lines +1344 to +1350

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Early return drops requested settings

When a running hosted push deployment is updated with compute plus other settings, both compute branches return before the remaining update flow, causing the command to report success without validating or applying settings such as public endpoints.

Knowledge Base Used: CLI and deployment workflows

Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/alien-deploy-cli/src/commands/up.rs
Line: 1344-1350

Comment:
**Early return drops requested settings**

When a running hosted push deployment is updated with compute plus other settings, both compute branches return before the remaining update flow, causing the command to report success without validating or applying settings such as public endpoints.

**Knowledge Base Used:** [CLI and deployment workflows](https://app.greptile.com/alien/-/custom-context/knowledge-base/alienplatform/alien/-/docs/cli-and-deployment.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

}

if let Some(public_endpoints) = public_endpoints.as_ref() {
let release_id = current_deployment
.desired_release_id
Expand Down Expand Up @@ -2596,6 +2683,37 @@ pub(crate) fn create_manager_http_client(token: &str) -> Result<reqwest::Client>
})
}

async fn update_hosted_compute_settings(
base_url: &str,
token: &str,
deployment_id: &str,
compute: &ComputeSettings,
) -> Result<()> {
let client = create_manager_http_client(token)?;
let url = format!(
"{}/v1/deployments/{}/compute",
base_url.trim_end_matches('/'),
urlencoding::encode(deployment_id)
);
let response = client
.patch(&url)
.json(&serde_json::json!({ "compute": compute }))
.send()
.await
.into_alien_error()
.context(ErrorData::ConfigurationError {
message: "Failed to update hosted deployment compute settings".to_string(),
})?;
if !response.status().is_success() {
let status = response.status();
let body = response.text().await.unwrap_or_default();
return Err(AlienError::new(ErrorData::ConfigurationError {
message: format!("Hosted compute update failed with HTTP {status}: {body}"),
}));
}
Ok(())
}

fn parse_deployment_status(raw_status: &str) -> Result<DeploymentStatus> {
match raw_status.to_ascii_lowercase().as_str() {
"pending" => Ok(DeploymentStatus::Pending),
Expand Down
Loading