From 29dc3be821f422aa42cef289fa468e78d108d6d6 Mon Sep 17 00:00:00 2001 From: Lee Reinhardt Date: Wed, 25 Mar 2026 17:50:28 -0600 Subject: [PATCH] feat: add --publish flag to connect upload command --- src/commands/connect/client.rs | 35 ++++++++++++++++++++++++++++++++++ src/commands/connect/upload.rs | 32 ++++++++++++++++++++++++++++++- src/main.rs | 5 +++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/commands/connect/client.rs b/src/commands/connect/client.rs index 25aad1b..461a77b 100644 --- a/src/commands/connect/client.rs +++ b/src/commands/connect/client.rs @@ -1020,6 +1020,41 @@ impl ConnectClient { Ok(resp.data) } + /// Publish a draft runtime (draft → published). + pub async fn publish_runtime( + &self, + org: &str, + project_id: &str, + runtime_id: &str, + ) -> Result { + let url = format!( + "{}/api/orgs/{}/projects/{}/runtimes/{}", + self.api_url, org, project_id, runtime_id + ); + + let body = serde_json::json!({ + "runtime": { "status": "published" } + }); + + let res = self + .http + .put(&url) + .header("authorization", format!("Bearer {}", self.token)) + .json(&body) + .send() + .await + .context("Failed to publish runtime")?; + + let status = res.status(); + if !status.is_success() { + let body = res.text().await.unwrap_or_default(); + anyhow::bail!("Failed to publish runtime (HTTP {status}): {body}"); + } + + let resp: CompleteRuntimeResponse = res.json().await?; + Ok(resp.data) + } + /// Re-fetch presigned URLs for an artifact (crash recovery). #[allow(dead_code)] pub async fn get_upload_urls( diff --git a/src/commands/connect/upload.rs b/src/commands/connect/upload.rs index 4dacdfd..812d8c8 100644 --- a/src/commands/connect/upload.rs +++ b/src/commands/connect/upload.rs @@ -27,6 +27,7 @@ pub struct ConnectUploadCommand { pub target: Option, pub file: Option, pub profile: Option, + pub publish: bool, pub deploy_cohort: Option, pub deploy_name: Option, pub deploy_tags: Vec, @@ -164,6 +165,20 @@ impl ConnectUploadCommand { OutputLevel::Normal, ); + if self.publish { + print_info("Publishing runtime...", OutputLevel::Normal); + let published = connect + .publish_runtime(&self.org, &self.project, &runtime.id) + .await?; + print_success( + &format!( + "Runtime {} published (status: {})", + published.version, published.status + ), + OutputLevel::Normal, + ); + } + if let Some(ref cohort_id) = self.deploy_cohort { super::deploy::deploy_after_upload(&super::deploy::DeployAfterUploadParams { client: &connect, @@ -210,7 +225,22 @@ impl ConnectUploadCommand { OutputLevel::Normal, ); - // 10. Deploy after upload if --deploy-cohort was specified + // 10. Publish if --publish was specified + if self.publish { + print_info("Publishing runtime...", OutputLevel::Normal); + let published = connect + .publish_runtime(&self.org, &self.project, &runtime.id) + .await?; + print_success( + &format!( + "Runtime {} published (status: {})", + published.version, published.status + ), + OutputLevel::Normal, + ); + } + + // 11. Deploy after upload if --deploy-cohort was specified if let Some(ref cohort_id) = self.deploy_cohort { super::deploy::deploy_after_upload(&super::deploy::DeployAfterUploadParams { client: &connect, diff --git a/src/main.rs b/src/main.rs index b376b96..1c868b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -521,6 +521,9 @@ enum ConnectCommands { /// Profile name (defaults to the active default profile) #[arg(long)] profile: Option, + /// Publish the runtime immediately after upload (draft → published) + #[arg(long)] + publish: bool, /// Deploy after upload: cohort ID to target #[arg(long)] deploy_cohort: Option, @@ -2865,6 +2868,7 @@ async fn main() -> Result<()> { target, file, profile, + publish, deploy_cohort, deploy_name, deploy_tag, @@ -2886,6 +2890,7 @@ async fn main() -> Result<()> { target: target.or(cli.target), file, profile: profile.clone(), + publish, deploy_cohort, deploy_name, deploy_tags: deploy_tag,