diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f718de1..b5003924 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,7 +76,7 @@ jobs: # Since we ran the tests with sudo, the build artifacts will have root ownership - name: Clean up - run: sudo chown -R $USER:$USER . + run: sudo chown -R $USER:$USER . ~/.cargo benchmarks: runs-on: ubuntu-latest diff --git a/crates/memtrack/src/allocators/static_linked.rs b/crates/memtrack/src/allocators/static_linked.rs index 45df99d8..092b9e7e 100644 --- a/crates/memtrack/src/allocators/static_linked.rs +++ b/crates/memtrack/src/allocators/static_linked.rs @@ -4,35 +4,64 @@ use std::path::{Path, PathBuf}; use crate::allocators::{AllocatorKind, AllocatorLib}; -/// Walk upward from current directory to find build directories. +/// Walk upward and downward from current directory to find build directories. /// Returns all found build directories in order of preference. fn find_build_dirs() -> Vec { let mut dirs = Vec::new(); - let Ok(mut current_dir) = std::env::current_dir() else { + let Ok(current_dir) = std::env::current_dir() else { return dirs; }; - loop { - // Check for Cargo/Rust build directory - let cargo_analysis = current_dir.join("target").join("codspeed").join("analysis"); - if cargo_analysis.is_dir() { - dirs.push(cargo_analysis); + let patterns = ["target/codspeed/analysis", "bazel-bin", "build"]; + let mut check_patterns = |dir: &Path| { + for pattern in &patterns { + let path = dir.join(pattern); + if path.is_dir() { + dirs.push(path); + } } + }; - // Check for Bazel build directory - let bazel_bin = current_dir.join("bazel-bin"); - if bazel_bin.is_dir() { - dirs.push(bazel_bin); - } + // Walk upward from parent directories + // Note: We skip current_dir here since the downward walk (below) already checks it + let mut current = current_dir.clone(); + while current.pop() { + check_patterns(¤t); + } - // Check for CMake build directory - let cmake_build = current_dir.join("build"); - if cmake_build.is_dir() { - dirs.push(cmake_build); - } + // Walk downward from current directory + let mut stack = vec![current_dir]; + while let Some(dir) = stack.pop() { + check_patterns(&dir); + + // Read subdirectories + let Ok(entries) = fs::read_dir(&dir) else { + continue; + }; + + for entry in entries.filter_map(Result::ok) { + let path = entry.path(); + + let Some(name) = path.file_name().and_then(|n| n.to_str()) else { + continue; + }; + + // Skip hidden dirs and common excludes + if name.starts_with('.') || matches!(name, "node_modules" | "vendor" | "venv") { + continue; + } + + // Don't recursive into dirs that we want to match. + // This can happen with `target` as it contains build dirs for statically linked crates. + if matches!(name, "target" | "bazel-bin" | "build") { + continue; + } + + if path.is_file() { + continue; + } - if !current_dir.pop() { - break; + stack.push(path); } } diff --git a/src/executor/memory/executor.rs b/src/executor/memory/executor.rs index 48802771..8c8b44b6 100644 --- a/src/executor/memory/executor.rs +++ b/src/executor/memory/executor.rs @@ -20,6 +20,7 @@ use runner_shared::artifacts::{ArtifactExt, ExecutionTimestamps}; use runner_shared::fifo::Command as FifoCommand; use runner_shared::fifo::IntegrationMode; use semver::Version; +use std::fs::canonicalize; use std::path::Path; use std::rc::Rc; use tempfile::NamedTempFile; @@ -48,6 +49,12 @@ impl MemoryExecutor { cmd_builder.arg(server_name); cmd_builder.arg(get_bench_command(&execution_context.config)?); + // Set working directory if specified + if let Some(cwd) = &execution_context.config.working_directory { + let abs_cwd = canonicalize(cwd)?; + cmd_builder.current_dir(abs_cwd); + } + // Wrap command with environment forwarding let extra_env = get_base_injected_env( RunnerMode::Memory,