diff --git a/lib/crates/fabro-sandbox/src/sandbox_spec.rs b/lib/crates/fabro-sandbox/src/sandbox_spec.rs index 644b0f5d3..6c56daf77 100644 --- a/lib/crates/fabro-sandbox/src/sandbox_spec.rs +++ b/lib/crates/fabro-sandbox/src/sandbox_spec.rs @@ -36,7 +36,7 @@ pub enum SandboxSpec { }, #[cfg(feature = "daytona")] Daytona { - config: DaytonaConfig, + config: Box, github_app: Option, run_id: Option, clone_origin_url: Option, @@ -169,7 +169,7 @@ impl SandboxSpec { api_key, } => { let mut sandbox = DaytonaSandbox::new( - config.clone(), + config.as_ref().clone(), github_app.clone(), *run_id, clone_origin_url.clone(), diff --git a/lib/crates/fabro-sandbox/tests/daytona_streaming_live.rs b/lib/crates/fabro-sandbox/tests/daytona_streaming_live.rs index d85ee7fdd..10c385ae9 100644 --- a/lib/crates/fabro-sandbox/tests/daytona_streaming_live.rs +++ b/lib/crates/fabro-sandbox/tests/daytona_streaming_live.rs @@ -6,6 +6,7 @@ mod daytona_streaming_live { use anyhow::{Context, Result, ensure}; use fabro_sandbox::daytona::{DaytonaConfig, DaytonaSandbox}; use fabro_sandbox::{CommandOutputCallback, ExecStreamingResult, Sandbox}; + use fabro_static::EnvVars; use fabro_types::{CommandOutputStream, CommandTermination}; use tokio::sync::Mutex; use tokio::time::{Instant, sleep}; @@ -21,7 +22,7 @@ mod daytona_streaming_live { #[ignore = "requires live Daytona credentials and provisions a sandbox"] async fn daytona_streaming_live_smoke() -> Result<()> { ensure!( - std::env::var_os("DAYTONA_API_KEY").is_some(), + daytona_api_key_present(), "DAYTONA_API_KEY must be set to run this live smoke test" ); @@ -99,8 +100,8 @@ mod daytona_streaming_live { "expected Daytona command logs to separate stdout and stderr" ); ensure_eq( - live_result.result.termination, - CommandTermination::Cancelled, + &live_result.result.termination, + &CommandTermination::Cancelled, "cancelled command should preserve cancellation termination", )?; ensure_contains( @@ -122,13 +123,13 @@ mod daytona_streaming_live { ) .await?; ensure_eq( - nonzero.result.exit_code, - Some(7), + &nonzero.result.exit_code, + &Some(7), "nonzero command should preserve the Daytona exit code", )?; ensure_eq( - nonzero.result.termination, - CommandTermination::Exited, + &nonzero.result.termination, + &CommandTermination::Exited, "nonzero command should be represented as a completed process", )?; ensure_contains( @@ -158,8 +159,8 @@ mod daytona_streaming_live { ) .await?; ensure_eq( - timed_out.result.termination, - CommandTermination::TimedOut, + &timed_out.result.termination, + &CommandTermination::TimedOut, "timed-out command should preserve timeout termination", )?; ensure_contains( @@ -205,6 +206,14 @@ mod daytona_streaming_live { }) } + #[expect( + clippy::disallowed_methods, + reason = "live smoke tests need a direct process-env preflight before provisioning Daytona" + )] + fn daytona_api_key_present() -> bool { + std::env::var_os(EnvVars::DAYTONA_API_KEY).is_some() + } + async fn wait_for_chunks( chunks: &Arc>>, timeout_after: Duration, @@ -238,7 +247,7 @@ mod daytona_streaming_live { Ok(()) } - fn ensure_eq(actual: T, expected: T, message: &str) -> Result<()> + fn ensure_eq(actual: &T, expected: &T, message: &str) -> Result<()> where T: std::fmt::Debug + PartialEq, { diff --git a/lib/crates/fabro-server/src/run_manifest.rs b/lib/crates/fabro-server/src/run_manifest.rs index 044e3a576..abd50c9b2 100644 --- a/lib/crates/fabro-server/src/run_manifest.rs +++ b/lib/crates/fabro-server/src/run_manifest.rs @@ -813,7 +813,7 @@ fn preflight_sandbox_spec( let mut config = resolve_daytona_config(resolved_run).unwrap_or_default(); config.skip_clone = true; SandboxSpec::Daytona { - config, + config: Box::new(config), github_app, run_id: None, clone_origin_url, diff --git a/lib/crates/fabro-workflow/src/operations/start.rs b/lib/crates/fabro-workflow/src/operations/start.rs index 366810e10..afe46a02f 100644 --- a/lib/crates/fabro-workflow/src/operations/start.rs +++ b/lib/crates/fabro-workflow/src/operations/start.rs @@ -373,7 +373,7 @@ impl RunSession { None => None, }; SandboxSpec::Daytona { - config: resolve_daytona_config(resolved).unwrap_or_default(), + config: Box::new(resolve_daytona_config(resolved).unwrap_or_default()), github_app: services.github_app.clone(), run_id: Some(record.run_id), clone_origin_url: record.repo_origin_url().map(str::to_string),