From f1d232e1fcd48add766c34286f9aba3fc82fef65 Mon Sep 17 00:00:00 2001 From: Brad Heller Date: Wed, 20 May 2026 12:21:02 +0100 Subject: [PATCH] fix: honor TOWER_API_KEY in deploy upload and log stream paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hand-rolled reqwest calls for the package upload (util/deploy.rs) and the run log SSE stream (api.rs) only attached Authorization: Bearer when bearer_access_token was set, and ignored the API key. With TOWER_API_KEY set, make_api_configuration populates api_key and never sets bearer_access_token, so these requests went out unauthenticated and the API rejected them — surfacing as "you are not logged into Tower" on tower deploy. Mirror the generated client and fall back to X-API-Key when bearer auth is absent. TOW-2120 --- crates/tower-cmd/src/api.rs | 8 ++++++++ crates/tower-cmd/src/util/deploy.rs | 10 +++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/tower-cmd/src/api.rs b/crates/tower-cmd/src/api.rs index 7accd413..54454477 100644 --- a/crates/tower-cmd/src/api.rs +++ b/crates/tower-cmd/src/api.rs @@ -673,8 +673,16 @@ pub async fn stream_run_logs( builder = builder.header(reqwest::header::USER_AGENT, user_agent.clone()); } + // Mirrors the generated tower-api client: prefer a bearer token (interactive session), + // otherwise fall back to the API key header set when TOWER_API_KEY is configured. if let Some(ref token) = api_config.bearer_access_token { builder = builder.bearer_auth(token.to_owned()); + } else if let Some(ref apikey) = api_config.api_key { + let value = match &apikey.prefix { + Some(prefix) => format!("{} {}", prefix, apikey.key), + None => apikey.key.clone(), + }; + builder = builder.header("X-API-Key", value); }; // Now let's try to open the event source with the server. diff --git a/crates/tower-cmd/src/util/deploy.rs b/crates/tower-cmd/src/util/deploy.rs index 23c56a3c..cc19fcb9 100644 --- a/crates/tower-cmd/src/util/deploy.rs +++ b/crates/tower-cmd/src/util/deploy.rs @@ -57,9 +57,17 @@ pub async fn upload_file_with_progress( .header("Content-Encoding", "gzip") .body(Body::wrap_stream(progress_stream)); - // Add authorization if available + // Add authorization if available. Mirrors the generated tower-api client: prefer a + // bearer token (interactive session), otherwise fall back to the API key header set + // when TOWER_API_KEY is configured. if let Some(token) = &api_config.bearer_access_token { req = req.header("Authorization", format!("Bearer {}", token)); + } else if let Some(apikey) = &api_config.api_key { + let value = match &apikey.prefix { + Some(prefix) => format!("{} {}", prefix, apikey.key), + None => apikey.key.clone(), + }; + req = req.header("X-API-Key", value); } // Send the request