From 6c7b66db024ac619d91f3cd87b6dc63a1614e3bb Mon Sep 17 00:00:00 2001 From: andrussal Date: Tue, 17 Feb 2026 10:28:50 +0100 Subject: [PATCH] fix(local-deployer): align keep-tempdir env and artifact persistence --- logos/examples/src/defaults.rs | 2 +- .../deployers/local/src/deployer.rs | 5 +- testing-framework/deployers/local/src/env.rs | 13 ++++- testing-framework/deployers/local/src/lib.rs | 12 ++++ .../deployers/local/src/manual/mod.rs | 7 ++- .../deployers/local/src/node_control/mod.rs | 6 +- .../deployers/local/src/process.rs | 55 ++++++++++++++----- 7 files changed, 79 insertions(+), 21 deletions(-) diff --git a/logos/examples/src/defaults.rs b/logos/examples/src/defaults.rs index 8cf25e7..6ab66f4 100644 --- a/logos/examples/src/defaults.rs +++ b/logos/examples/src/defaults.rs @@ -21,7 +21,7 @@ fn set_default_env(key: &str, value: &str) { } pub fn init_logging_defaults() { - set_default_env("LOGOS_BLOCKCHAIN_TESTS_KEEP_LOGS", "1"); + set_default_env("TF_KEEP_LOGS", "1"); set_default_env("LOGOS_BLOCKCHAIN_LOG_LEVEL", "info"); set_default_env("RUST_LOG", "info"); } diff --git a/testing-framework/deployers/local/src/deployer.rs b/testing-framework/deployers/local/src/deployer.rs index d0006c1..972769d 100644 --- a/testing-framework/deployers/local/src/deployer.rs +++ b/testing-framework/deployers/local/src/deployer.rs @@ -25,6 +25,7 @@ use tracing::{debug, info, warn}; use crate::{ env::{LocalDeployerEnv, Node, wait_local_http_readiness}, + keep_tempdir_from_env, manual::ManualCluster, node_control::{NodeManager, NodeManagerSeed}, }; @@ -395,8 +396,8 @@ const fn default_local_retry_policy() -> RetryPolicy { ) } -const fn keep_tempdir(policy: DeploymentPolicy) -> bool { - policy.cleanup_policy.preserve_artifacts +fn keep_tempdir(policy: DeploymentPolicy) -> bool { + policy.cleanup_policy.preserve_artifacts || keep_tempdir_from_env() } async fn spawn_feed_with( diff --git a/testing-framework/deployers/local/src/env.rs b/testing-framework/deployers/local/src/env.rs index 063c342..701cc23 100644 --- a/testing-framework/deployers/local/src/env.rs +++ b/testing-framework/deployers/local/src/env.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, path::Path}; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; use testing_framework_core::scenario::{ Application, DynError, HttpReadinessRequirement, ReadinessError, StartNodeOptions, @@ -36,6 +39,14 @@ where topology: &Self::Deployment, ) -> Result::NodeConfig>>, ProcessSpawnError>; + fn initial_persist_dir( + _topology: &Self::Deployment, + _node_name: &str, + _index: usize, + ) -> Option { + None + } + fn build_launch_spec( config: &::NodeConfig, dir: &Path, diff --git a/testing-framework/deployers/local/src/lib.rs b/testing-framework/deployers/local/src/lib.rs index 03be32e..df19be3 100644 --- a/testing-framework/deployers/local/src/lib.rs +++ b/testing-framework/deployers/local/src/lib.rs @@ -14,3 +14,15 @@ pub use process::{ LaunchEnvVar, LaunchFile, LaunchSpec, NodeEndpointPort, NodeEndpoints, ProcessNode, ProcessSpawnError, }; + +const KEEP_LOGS_ENV: &str = "TF_KEEP_LOGS"; + +pub(crate) fn keep_tempdir_from_env() -> bool { + env_enabled(KEEP_LOGS_ENV) +} + +fn env_enabled(key: &str) -> bool { + std::env::var(key).ok().is_some_and(|value| { + value == "1" || value.eq_ignore_ascii_case("true") || value.eq_ignore_ascii_case("yes") + }) +} diff --git a/testing-framework/deployers/local/src/manual/mod.rs b/testing-framework/deployers/local/src/manual/mod.rs index 7dbccaf..d34f284 100644 --- a/testing-framework/deployers/local/src/manual/mod.rs +++ b/testing-framework/deployers/local/src/manual/mod.rs @@ -6,7 +6,8 @@ use thiserror::Error; use crate::{ env::LocalDeployerEnv, - node_control::{NodeManager, NodeManagerError}, + keep_tempdir_from_env, + node_control::{NodeManager, NodeManagerError, NodeManagerSeed}, }; #[derive(Debug, Error)] @@ -22,9 +23,11 @@ pub struct ManualCluster { impl ManualCluster { pub fn from_topology(descriptors: E::Deployment) -> Self { - let nodes = NodeManager::new( + let nodes = NodeManager::new_with_seed( descriptors, testing_framework_core::scenario::NodeClients::default(), + keep_tempdir_from_env(), + NodeManagerSeed::default(), ); Self { nodes } diff --git a/testing-framework/deployers/local/src/node_control/mod.rs b/testing-framework/deployers/local/src/node_control/mod.rs index efa7d96..4aab046 100644 --- a/testing-framework/deployers/local/src/node_control/mod.rs +++ b/testing-framework/deployers/local/src/node_control/mod.rs @@ -75,13 +75,15 @@ impl NodeManager { ) -> Result>, ProcessSpawnError> { let configs = E::build_initial_node_configs(descriptors)?; let mut spawned = Vec::with_capacity(configs.len()); - for config_entry in configs { + + for (index, config_entry) in configs.into_iter().enumerate() { + let persist_dir = E::initial_persist_dir(descriptors, &config_entry.name, index); spawned.push( spawn_node_from_config::( config_entry.name, config_entry.config, keep_tempdir, - None, + persist_dir.as_deref(), ) .await?, ); diff --git a/testing-framework/deployers/local/src/process.rs b/testing-framework/deployers/local/src/process.rs index 612a338..12bb91c 100644 --- a/testing-framework/deployers/local/src/process.rs +++ b/testing-framework/deployers/local/src/process.rs @@ -1,6 +1,8 @@ use std::{ collections::HashMap, - fs, io, mem, + env, fs, + io::{self, Error, ErrorKind}, + mem, net::{Ipv4Addr, SocketAddr}, path::{Path, PathBuf}, process::Stdio, @@ -192,18 +194,8 @@ impl, client_from_endpoints: impl FnOnce(&NodeEndpoints) -> Client, ) -> Result { - let tempdir = match persist_dir { - Some(path) => { - std::fs::create_dir_all(path).map_err(|source| ProcessSpawnError::TempDir { - source: io::Error::new( - source.kind(), - format!("failed to create persist dir {}: {source}", path.display()), - ), - })?; - TempDir::new_in(path).map_err(|source| ProcessSpawnError::TempDir { source })? - } - None => TempDir::new().map_err(|source| ProcessSpawnError::TempDir { source })?, - }; + let tempdir = create_tempdir(persist_dir)?; + let launch = build_launch_spec(&config, tempdir.path(), label) .map_err(|source| ProcessSpawnError::Config { source })?; let endpoints = endpoints_from_config(&config); @@ -340,6 +332,43 @@ fn default_api_socket() -> SocketAddr { SocketAddr::from((Ipv4Addr::LOCALHOST, 0)) } +fn create_tempdir(persist_dir: Option<&Path>) -> Result { + match persist_dir { + Some(dir) => { + let final_dir_name = dir + .components() + .last() + .ok_or_else(|| ProcessSpawnError::TempDir { + source: Error::new(ErrorKind::Other, "invalid final directory"), + })? + .as_os_str() + .display() + .to_string() + + "_"; + let parent_dir = dir.parent().ok_or_else(|| ProcessSpawnError::TempDir { + source: Error::new(ErrorKind::Other, "invalid parent directory"), + })?; + + fs::create_dir_all(parent_dir).map_err(|source| ProcessSpawnError::TempDir { + source: Error::new( + source.kind(), + format!( + "failed to create parent dir for persist path {}: {source}", + dir.display() + ), + ), + })?; + + TempDir::with_prefix_in(final_dir_name, parent_dir) + .map_err(|source| ProcessSpawnError::TempDir { source }) + } + None => { + let cwd = env::current_dir().map_err(|source| ProcessSpawnError::TempDir { source })?; + TempDir::new_in(cwd).map_err(|source| ProcessSpawnError::TempDir { source }) + } + } +} + #[cfg(test)] mod tests { use super::{NodeEndpointPort, NodeEndpoints};