From fcb473411e95fb23899e27f90757b177e4e7589d Mon Sep 17 00:00:00 2001 From: qcai-godaddy <86305984+qcai-godaddy@users.noreply.github.com> Date: Mon, 20 Jul 2026 12:26:28 -0700 Subject: [PATCH 1/2] [DEVEX-709] fix(application update): restore --status ACTIVE|INACTIVE --- rust/src/application/commands/mod.rs | 51 ++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/rust/src/application/commands/mod.rs b/rust/src/application/commands/mod.rs index d5bc141..07e38c4 100644 --- a/rust/src/application/commands/mod.rs +++ b/rust/src/application/commands/mod.rs @@ -455,9 +455,10 @@ fn update_command() -> RuntimeCommandSpec { RuntimeCommandSpec::new_with_context( CommandSpec::new("update", "Update an application") .with_long( - "Update the label or description of a GoDaddy developer-platform application \ - by its ID. At least one of --label or --description must be provided. \ - Use `application info --name ` to retrieve the application ID.", + "Update the label, description, or status of a GoDaddy developer-platform \ + application by its ID. At least one of --label, --description, or --status \ + must be provided. Use `application info --name ` to retrieve the \ + application ID.", ) .with_system("applications") .with_tier(Tier::Mutate) @@ -481,6 +482,13 @@ fn update_command() -> RuntimeCommandSpec { .long("description") .value_name("TEXT") .help("New description"), + ) + .with_arg( + clap::Arg::new("status") + .long("status") + .value_name("STATUS") + .value_parser(["ACTIVE", "INACTIVE"]) + .help("Application status (ACTIVE or INACTIVE)"), ), |ctx| async move { let id = arg_str(&ctx, "id").to_owned(); @@ -491,6 +499,14 @@ fn update_command() -> RuntimeCommandSpec { if let Some(desc) = ctx.args.get("description").and_then(|v| v.as_str()) { input.insert("description".to_owned(), json!(desc)); } + if let Some(status) = ctx.args.get("status").and_then(|v| v.as_str()) { + input.insert("status".to_owned(), json!(status)); + } + if input.is_empty() { + return Err(cli_engine::CliCoreError::message( + "Provide one of: --label, --description, --status", + )); + } let client = make_client(&ctx).await?; let data = client .update_application(&id, json!(input)) @@ -1504,6 +1520,35 @@ pub fn add_extension_group() -> RuntimeGroupSpec { mod tests { use cli_engine::{Cli, CliConfig, Stage}; + use super::update_command; + + fn update_clap_command() -> clap::Command { + clap::Command::new("update").args(update_command().spec.args) + } + + #[test] + fn status_rejects_values_outside_active_inactive() { + for bad in ["active", "DISABLED", "PENDING"] { + let err = update_clap_command() + .try_get_matches_from(["update", "--id", "app-1", "--status", bad]) + .expect_err("invalid --status should be rejected"); + assert_eq!( + err.kind(), + clap::error::ErrorKind::InvalidValue, + "--status {bad:?} should fail possible-value validation, got: {err}" + ); + } + } + + #[test] + fn status_accepts_active_and_inactive() { + for good in ["ACTIVE", "INACTIVE"] { + update_clap_command() + .try_get_matches_from(["update", "--id", "app-1", "--status", good]) + .expect("ACTIVE|INACTIVE --status should be accepted"); + } + } + /// API commands must stay fail-closed: `application list` calls the backend, /// so it must require authentication. Built with **no auth provider /// registered**, the engine's default `AuthRequirement::Required` must reject From fe7493beb98e4b002ba324fe37eabedc871ce9ea Mon Sep 17 00:00:00 2001 From: qcai-godaddy <86305984+qcai-godaddy@users.noreply.github.com> Date: Mon, 20 Jul 2026 12:46:18 -0700 Subject: [PATCH 2/2] address Copilot comments --- rust/src/application/commands/mod.rs | 53 ++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/rust/src/application/commands/mod.rs b/rust/src/application/commands/mod.rs index 07e38c4..8f22ca2 100644 --- a/rust/src/application/commands/mod.rs +++ b/rust/src/application/commands/mod.rs @@ -475,12 +475,15 @@ fn update_command() -> RuntimeCommandSpec { clap::Arg::new("label") .long("label") .value_name("LABEL") + // CommandSpec has no ArgGroup; this enforces "at least one" at parse time. + .required_unless_present_any(["description", "status"]) .help("New label"), ) .with_arg( clap::Arg::new("description") .long("description") .value_name("TEXT") + .required_unless_present_any(["label", "status"]) .help("New description"), ) .with_arg( @@ -488,6 +491,7 @@ fn update_command() -> RuntimeCommandSpec { .long("status") .value_name("STATUS") .value_parser(["ACTIVE", "INACTIVE"]) + .required_unless_present_any(["label", "description"]) .help("Application status (ACTIVE or INACTIVE)"), ), |ctx| async move { @@ -502,11 +506,6 @@ fn update_command() -> RuntimeCommandSpec { if let Some(status) = ctx.args.get("status").and_then(|v| v.as_str()) { input.insert("status".to_owned(), json!(status)); } - if input.is_empty() { - return Err(cli_engine::CliCoreError::message( - "Provide one of: --label, --description, --status", - )); - } let client = make_client(&ctx).await?; let data = client .update_application(&id, json!(input)) @@ -1523,7 +1522,7 @@ mod tests { use super::update_command; fn update_clap_command() -> clap::Command { - clap::Command::new("update").args(update_command().spec.args) + update_command().spec.clap_command() } #[test] @@ -1549,6 +1548,48 @@ mod tests { } } + #[test] + fn update_requires_at_least_one_field() { + let err = update_clap_command() + .try_get_matches_from(["update", "--id", "app-1"]) + .expect_err("update with only --id should be rejected at parse time"); + assert_eq!( + err.kind(), + clap::error::ErrorKind::MissingRequiredArgument, + "expected MissingRequiredArgument, got: {err}" + ); + } + + #[test] + fn update_accepts_any_single_field() { + update_clap_command() + .try_get_matches_from(["update", "--id", "app-1", "--label", "New"]) + .expect("--label alone should be accepted"); + update_clap_command() + .try_get_matches_from(["update", "--id", "app-1", "--description", "Desc"]) + .expect("--description alone should be accepted"); + update_clap_command() + .try_get_matches_from(["update", "--id", "app-1", "--status", "ACTIVE"]) + .expect("--status alone should be accepted"); + } + + #[test] + fn update_accepts_multiple_fields() { + update_clap_command() + .try_get_matches_from([ + "update", + "--id", + "app-1", + "--label", + "New", + "--description", + "Desc", + "--status", + "INACTIVE", + ]) + .expect("multiple update fields should be allowed together"); + } + /// API commands must stay fail-closed: `application list` calls the backend, /// so it must require authentication. Built with **no auth provider /// registered**, the engine's default `AuthRequirement::Required` must reject