From 99299b42db55eb7dbbf214723961bf1790cd88ab Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Thu, 16 Apr 2026 16:28:02 +0200 Subject: [PATCH 01/10] chore: make update-bindings.sh PWD agnostic --- .../instrument-hooks-bindings/src/update-bindings.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/instrument-hooks-bindings/src/update-bindings.sh b/crates/instrument-hooks-bindings/src/update-bindings.sh index ce2e001b..469ceb03 100755 --- a/crates/instrument-hooks-bindings/src/update-bindings.sh +++ b/crates/instrument-hooks-bindings/src/update-bindings.sh @@ -1,8 +1,12 @@ #!/usr/bin/env bash set -euo pipefail -bindgen ../instrument-hooks/includes/core.h \ - -o bindings.rs \ - --rust-target 1.74 \ +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +bindgen "$SCRIPT_DIR/../instrument-hooks/includes/core.h" \ + -o "$SCRIPT_DIR/bindings.rs" \ + --rust-edition 2024 \ + --rust-target 1.88 \ --allowlist-function "instrument_hooks_.*" \ - --allowlist-var "MARKER_TYPE_.*" + --allowlist-var "MARKER_TYPE_.*" \ + --allowlist-type "instrument_hooks_feature_t" From 0ccec054bf7439f728678f154f7adbafbc936901 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Fri, 10 Apr 2026 18:54:23 +0200 Subject: [PATCH 02/10] feat: add aarch64-apple-darwin to the release targets --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4d4c210e..a7d57992 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -129,6 +129,7 @@ lto = "thin" strip = true [package.metadata.dist] -targets = ["aarch64-unknown-linux-musl", "x86_64-unknown-linux-musl"] +targets = ["aarch64-apple-darwin", "aarch64-unknown-linux-musl", "x86_64-unknown-linux-musl"] +binaries.aarch64-apple-darwin = ["codspeed"] binaries.aarch64-unknown-linux-musl = ["codspeed"] binaries.x86_64-unknown-linux-musl = ["codspeed"] From 428b80cad41baec19b48a3df6e1fdc17c901bb63 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 14:27:39 +0200 Subject: [PATCH 03/10] chore(exec-harness): rerun exec harness build if instrument hooks sources change --- crates/exec-harness/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/exec-harness/build.rs b/crates/exec-harness/build.rs index 49c7cded..bf65ef7e 100644 --- a/crates/exec-harness/build.rs +++ b/crates/exec-harness/build.rs @@ -62,6 +62,7 @@ fn main() { core_c: instrument_hooks_dir.join("dist/core.c"), includes_dir: instrument_hooks_dir.join("includes"), }; + println!("cargo:rerun-if-changed={}", paths.core_c.display()); paths.check_sources_exist(); build_shared_library(&paths, &preload_constants); } From ed90646d97a19b1f5444b970b362a4d76d163753 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 14:28:15 +0200 Subject: [PATCH 04/10] fix: fix instropected_go's behavior on macos On macos a symlink breaks the existing test creating an infinite loop where `instropected_go` detects itself as the real `go` executable. Fixed by changing the behavior to what instrospected_node does. --- src/executor/helpers/introspected_golang/go.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/executor/helpers/introspected_golang/go.sh b/src/executor/helpers/introspected_golang/go.sh index 6aba393d..5601d136 100755 --- a/src/executor/helpers/introspected_golang/go.sh +++ b/src/executor/helpers/introspected_golang/go.sh @@ -18,8 +18,10 @@ if [ "${CODSPEED_RUNNER_MODE:-}" != "walltime" ]; then exit 1 fi -# Find the real go binary, so that we don't end up in infinite recursion -REAL_GO=$(which -a go | grep -v "$(realpath "$0")" | head -1) +# Find the real go binary by removing our directory from PATH (same approach as node.sh) +ORIGINAL_PATH=$(echo "$PATH" | tr ":" "\n" | grep -v "codspeed_introspected_go" | tr "\n" ":") +REAL_GO=$(env PATH="$ORIGINAL_PATH" which go 2>/dev/null || true) +debug_log "Real go path: $REAL_GO" if [ -z "$REAL_GO" ]; then echo "ERROR: Could not find real go binary" >&2 exit 1 From 19ea85c5c999d6e362a7e8f0f0b1638eda9550ef Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 14:30:42 +0200 Subject: [PATCH 05/10] chore: bump instrument-hooks submodule to include stubs improvement Fixes compilation warnings in exec-harness's build script. --- .../instrument-hooks | 2 +- .../instrument-hooks-bindings/src/bindings.rs | 30 +++++++++++++++++-- crates/instrument-hooks-bindings/src/lib.rs | 6 ++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/crates/instrument-hooks-bindings/instrument-hooks b/crates/instrument-hooks-bindings/instrument-hooks index 89fb72a0..ecdf31a3 160000 --- a/crates/instrument-hooks-bindings/instrument-hooks +++ b/crates/instrument-hooks-bindings/instrument-hooks @@ -1 +1 @@ -Subproject commit 89fb72a076ec71c9eca6eee9bca98bada4b4dfb4 +Subproject commit ecdf31a3afd0fb879823e40df65129ec823d374b diff --git a/crates/instrument-hooks-bindings/src/bindings.rs b/crates/instrument-hooks-bindings/src/bindings.rs index b7af600d..3adf72f9 100644 --- a/crates/instrument-hooks-bindings/src/bindings.rs +++ b/crates/instrument-hooks-bindings/src/bindings.rs @@ -4,7 +4,11 @@ pub const MARKER_TYPE_SAMPLE_START: u32 = 0; pub const MARKER_TYPE_SAMPLE_END: u32 = 1; pub const MARKER_TYPE_BENCHMARK_START: u32 = 2; pub const MARKER_TYPE_BENCHMARK_END: u32 = 3; -pub type InstrumentHooks = *mut u64; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct InstrumentHooks { + _unused: [u8; 0], +} unsafe extern "C" { pub fn instrument_hooks_init() -> *mut InstrumentHooks; } @@ -44,7 +48,7 @@ unsafe extern "C" { unsafe extern "C" { pub fn instrument_hooks_add_marker( arg1: *mut InstrumentHooks, - pid: u32, + pid: i32, marker_type: u8, timestamp: u64, ) -> u8; @@ -56,5 +60,25 @@ pub const instrument_hooks_feature_t_FEATURE_DISABLE_CALLGRIND_MARKERS: instrume 0; pub type instrument_hooks_feature_t = ::std::os::raw::c_uint; unsafe extern "C" { - pub fn instrument_hooks_set_feature(feature: instrument_hooks_feature_t, enabled: bool); + pub fn instrument_hooks_set_feature(feature: u64, enabled: bool); +} +unsafe extern "C" { + pub fn instrument_hooks_set_environment( + arg1: *mut InstrumentHooks, + section_name: *const ::std::os::raw::c_char, + key: *const ::std::os::raw::c_char, + value: *const ::std::os::raw::c_char, + ) -> u8; +} +unsafe extern "C" { + pub fn instrument_hooks_set_environment_list( + arg1: *mut InstrumentHooks, + section_name: *const ::std::os::raw::c_char, + key: *const ::std::os::raw::c_char, + values: *const *const ::std::os::raw::c_char, + count: u32, + ) -> u8; +} +unsafe extern "C" { + pub fn instrument_hooks_write_environment(arg1: *mut InstrumentHooks, pid: i32) -> u8; } diff --git a/crates/instrument-hooks-bindings/src/lib.rs b/crates/instrument-hooks-bindings/src/lib.rs index c4a12aaa..8ea620cb 100644 --- a/crates/instrument-hooks-bindings/src/lib.rs +++ b/crates/instrument-hooks-bindings/src/lib.rs @@ -78,7 +78,7 @@ mod linux_impl { #[inline(always)] pub fn add_benchmark_timestamps(&self, start: u64, end: u64) { - let pid = std::process::id(); + let pid = std::process::id() as i32; unsafe { ffi::instrument_hooks_add_marker( @@ -100,7 +100,7 @@ mod linux_impl { #[inline(always)] pub fn add_sample_timestamps(&self, start: u64, end: u64) { - let pid = std::process::id(); + let pid = std::process::id() as i32; unsafe { ffi::instrument_hooks_add_marker( @@ -141,7 +141,7 @@ mod linux_impl { pub fn disable_callgrind_markers() { unsafe { ffi::instrument_hooks_set_feature( - ffi::instrument_hooks_feature_t_FEATURE_DISABLE_CALLGRIND_MARKERS, + ffi::instrument_hooks_feature_t_FEATURE_DISABLE_CALLGRIND_MARKERS.into(), true, ) }; From 61422a15320de06e94650c7c5153787ab2d99b69 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 15:00:51 +0200 Subject: [PATCH 06/10] feat: bypass systemd-run usage on macos --- src/executor/wall_time/executor.rs | 27 ++++-------------- src/executor/wall_time/isolation.rs | 43 +++++++++++++++++++++++++++++ src/executor/wall_time/mod.rs | 1 + 3 files changed, 49 insertions(+), 22 deletions(-) create mode 100644 src/executor/wall_time/isolation.rs diff --git a/src/executor/wall_time/executor.rs b/src/executor/wall_time/executor.rs index c317f266..9103204f 100644 --- a/src/executor/wall_time/executor.rs +++ b/src/executor/wall_time/executor.rs @@ -1,12 +1,11 @@ use super::helpers::validate_walltime_results; +use super::isolation::wrap_with_isolation; use super::perf::PerfRunner; use crate::executor::Executor; use crate::executor::ExecutorConfig; use crate::executor::ToolStatus; use crate::executor::helpers::command::CommandBuilder; -use crate::executor::helpers::env::{ - build_path_env, get_base_injected_env, is_codspeed_debug_enabled, -}; +use crate::executor::helpers::env::{build_path_env, get_base_injected_env}; use crate::executor::helpers::get_bench_command::get_bench_command; use crate::executor::helpers::run_command_with_log_pipe::run_command_with_log_pipe; use crate::executor::helpers::run_with_env::wrap_with_env; @@ -105,28 +104,12 @@ impl WallTimeExecutor { bench_cmd.arg(script_file.path()); let (mut bench_cmd, env_file) = wrap_with_env(bench_cmd, &extra_env)?; - let mut cmd_builder = CommandBuilder::new("systemd-run"); if let Some(cwd) = &config.working_directory { let abs_cwd = canonicalize(cwd)?; - cmd_builder.current_dir(abs_cwd); + bench_cmd.current_dir(abs_cwd); } - if !is_codspeed_debug_enabled() { - cmd_builder.arg("--quiet"); - } - // Remarks: - // - We're using --scope so that perf is able to capture the events of the benchmark process. - // - We can't user `--user` here because we need to run in `codspeed.slice`, otherwise we'd run in - // user.slice` (which is isolated). We can use `--gid` and `--uid` to run the command as the current user. - // - We must use `bash` here instead of `sh` since `source` isn't available when symlinked to `dash`. - // - We have to pass the environment variables because `--scope` only inherits the system and not the user environment variables. - cmd_builder.arg("--slice=codspeed.slice"); - cmd_builder.arg("--scope"); - cmd_builder.arg("--same-dir"); - cmd_builder.arg(format!("--uid={}", nix::unistd::Uid::current().as_raw())); - cmd_builder.arg(format!("--gid={}", nix::unistd::Gid::current().as_raw())); - cmd_builder.args(["--"]); - - bench_cmd.wrap_with(cmd_builder); + + let bench_cmd = wrap_with_isolation(bench_cmd)?; Ok((env_file, script_file, bench_cmd)) } diff --git a/src/executor/wall_time/isolation.rs b/src/executor/wall_time/isolation.rs new file mode 100644 index 00000000..37c41ee9 --- /dev/null +++ b/src/executor/wall_time/isolation.rs @@ -0,0 +1,43 @@ +use crate::executor::helpers::command::CommandBuilder; +use crate::prelude::*; + +/// Run the benchmark command in an isolated process scope. +/// +/// On Linux, the command is wrapped with `systemd-run --scope` so it runs inside the +/// `codspeed.slice` cgroup (required for perf to capture the full process tree). +/// +/// Remarks: +/// - We're using `--scope` so that perf is able to capture the events of the benchmark process. +/// - We can't use `--user` here because we need to run in `codspeed.slice`, otherwise we'd run in +/// `user.slice` (which is isolated). We use `--uid` and `--gid` to keep running as the current +/// user. +/// - `--scope` only inherits the system environment, so the caller is expected to have already +/// forwarded the relevant variables (via `wrap_with_env`). +/// - The caller is expected to have already set the working directory on `bench_cmd`; it will be +/// propagated to `systemd-run` via [`CommandBuilder::wrap_with`], and `--same-dir` makes the +/// spawned scope inherit it. +#[cfg(target_os = "linux")] +pub fn wrap_with_isolation(mut bench_cmd: CommandBuilder) -> Result { + use crate::executor::helpers::env::is_codspeed_debug_enabled; + + let mut cmd_builder = CommandBuilder::new("systemd-run"); + if !is_codspeed_debug_enabled() { + cmd_builder.arg("--quiet"); + } + cmd_builder.arg("--slice=codspeed.slice"); + cmd_builder.arg("--scope"); + cmd_builder.arg("--same-dir"); + cmd_builder.arg(format!("--uid={}", nix::unistd::Uid::current().as_raw())); + cmd_builder.arg(format!("--gid={}", nix::unistd::Gid::current().as_raw())); + cmd_builder.args(["--"]); + + bench_cmd.wrap_with(cmd_builder); + Ok(bench_cmd) +} + +/// Dummy implementation on non-Linux platforms: the benchmark command is returned as-is. +// TODO(COD-2513): implement an equivalent process-isolation mechanism on macOS +#[cfg(not(target_os = "linux"))] +pub fn wrap_with_isolation(bench_cmd: CommandBuilder) -> Result { + Ok(bench_cmd) +} diff --git a/src/executor/wall_time/mod.rs b/src/executor/wall_time/mod.rs index b790b6ac..ecd1ce79 100644 --- a/src/executor/wall_time/mod.rs +++ b/src/executor/wall_time/mod.rs @@ -1,3 +1,4 @@ pub mod executor; pub mod helpers; +pub mod isolation; pub mod perf; From a7eb6e2ca7de8308f0d7203aea2abef0399d2f94 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 15:41:56 +0200 Subject: [PATCH 07/10] feat(system): represent the host OS as a SupportedOs enum with per-executor support gates Only supported Oses can be represented, the runner will bail if it detects a non supported os. Then, each executor can define its support level for the current system depending on the Os and, for example, the linux distribution/version. --- src/cli/setup.rs | 95 ++++++++++++++------ src/cli/status.rs | 7 +- src/executor/helpers/apt.rs | 4 +- src/executor/memory/executor.rs | 14 ++- src/executor/mod.rs | 39 ++++++-- src/executor/orchestrator.rs | 3 +- src/executor/valgrind/executor.rs | 25 ++++-- src/executor/valgrind/setup.rs | 84 ++++++++++++----- src/executor/wall_time/executor.rs | 18 +++- src/system/check.rs | 56 ------------ src/system/info.rs | 19 ++-- src/system/mod.rs | 4 +- src/system/os.rs | 140 +++++++++++++++++++++++++++++ src/upload/interfaces.rs | 4 +- src/upload/upload_metadata.rs | 8 +- 15 files changed, 374 insertions(+), 146 deletions(-) delete mode 100644 src/system/check.rs create mode 100644 src/system/os.rs diff --git a/src/cli/setup.rs b/src/cli/setup.rs index 19559dbe..db1d8a9d 100644 --- a/src/cli/setup.rs +++ b/src/cli/setup.rs @@ -1,4 +1,4 @@ -use crate::executor::{ToolInstallStatus, get_all_executors}; +use crate::executor::{ExecutorSupport, ToolInstallStatus, get_all_executors}; use crate::prelude::*; use crate::system::SystemInfo; use clap::{Args, Subcommand}; @@ -22,10 +22,7 @@ enum SetupCommands { pub async fn run(args: SetupArgs, setup_cache_dir: Option<&Path>) -> Result<()> { match args.command { None => setup(setup_cache_dir).await, - Some(SetupCommands::Status) => { - status(); - Ok(()) - } + Some(SetupCommands::Status) => status(), } } @@ -34,41 +31,81 @@ async fn setup(setup_cache_dir: Option<&Path>) -> Result<()> { let executors = get_all_executors(); start_group!("Setting up the environment for all executors"); for executor in executors { - info!( - "Setting up the environment for the executor: {}", - executor.name() - ); - executor.setup(&system_info, setup_cache_dir).await?; + match executor.support_level(&system_info) { + ExecutorSupport::Unsupported => { + info!( + "Skipping setup for the {} executor: not supported on {}", + executor.name(), + system_info.os + ); + } + ExecutorSupport::RequiresManualInstallation => { + info!( + "Skipping automatic setup for the {} executor on {}; install required tooling manually.", + executor.name(), + system_info.os + ); + } + ExecutorSupport::FullySupported => { + info!( + "Setting up the environment for the executor: {}", + executor.name() + ); + executor.setup(&system_info, setup_cache_dir).await?; + } + } } info!("Environment setup completed"); end_group!(); Ok(()) } -pub fn status() { +pub fn status() -> Result<()> { + let system_info = SystemInfo::new()?; info!("{}", style("Tools").bold()); for executor in get_all_executors() { - let tool_status = executor.tool_status(); - match &tool_status.status { - ToolInstallStatus::Installed { version } => { - info!(" {} {} ({})", check_mark(), tool_status.tool_name, version); - } - ToolInstallStatus::IncorrectVersion { version, message } => { - info!( - " {} {} ({}, {})", - warn_mark(), - tool_status.tool_name, - version, - message - ); - } - ToolInstallStatus::NotInstalled => { + // Don't probe for tooling that can't be used on this OS anyway. + if executor.support_level(&system_info) == ExecutorSupport::Unsupported { + continue; + } + match executor.tool_status() { + Some(tool_status) => match &tool_status.status { + ToolInstallStatus::Installed { version } => { + info!( + " {} {} executor: {} ({})", + check_mark(), + executor.name(), + tool_status.tool_name, + version + ); + } + ToolInstallStatus::IncorrectVersion { version, message } => { + info!( + " {} {} executor: {} ({}, {})", + warn_mark(), + executor.name(), + tool_status.tool_name, + version, + message + ); + } + ToolInstallStatus::NotInstalled => { + info!( + " {} {} executor: {} (not installed)", + cross_mark(), + executor.name(), + tool_status.tool_name + ); + } + }, + None => { info!( - " {} {} (not installed)", - cross_mark(), - tool_status.tool_name + " {} {} executor: No tool to install", + check_mark(), + executor.name() ); } } } + Ok(()) } diff --git a/src/cli/status.rs b/src/cli/status.rs index b8fe3f90..13a5b1b7 100644 --- a/src/cli/status.rs +++ b/src/cli/status.rs @@ -22,17 +22,14 @@ pub async fn run(api_client: &CodSpeedAPIClient) -> Result<()> { info!(""); // Setup/tools status - super::setup::status(); + super::setup::status()?; info!(""); // System info info!("{}", style("System").bold()); info!(" codspeed {VERSION}"); let system_info = SystemInfo::new()?; - info!( - " {} {} ({})", - system_info.os, system_info.os_version, system_info.arch - ); + info!(" {} ({})", system_info.os, system_info.arch); info!( " {} ({}C / {}GB)", system_info.cpu_brand, system_info.cpu_cores, system_info.total_memory_gb diff --git a/src/executor/helpers/apt.rs b/src/executor/helpers/apt.rs index 00fb1cfc..8d430bdc 100644 --- a/src/executor/helpers/apt.rs +++ b/src/executor/helpers/apt.rs @@ -1,13 +1,13 @@ use super::run_with_sudo::run_with_sudo; use crate::prelude::*; -use crate::system::SystemInfo; +use crate::system::{SupportedOs, SystemInfo}; use std::path::Path; use std::process::Command; const METADATA_FILENAME: &str = "./tmp/codspeed-cache-metadata.txt"; fn is_system_compatible(system_info: &SystemInfo) -> bool { - system_info.os == "ubuntu" || system_info.os == "debian" + matches!(system_info.os, SupportedOs::Linux(ref distro) if distro.is_supported()) } /// Installs packages with caching support. diff --git a/src/executor/memory/executor.rs b/src/executor/memory/executor.rs index d5c8320e..03f56aaa 100644 --- a/src/executor/memory/executor.rs +++ b/src/executor/memory/executor.rs @@ -1,4 +1,5 @@ use crate::executor::ExecutorName; +use crate::executor::ExecutorSupport; use crate::executor::ToolStatus; use crate::executor::helpers::command::CommandBuilder; use crate::executor::helpers::env::get_base_injected_env; @@ -11,7 +12,7 @@ use crate::executor::{ExecutionContext, Executor}; use crate::instruments::mongo_tracer::MongoTracer; use crate::prelude::*; use crate::runner_mode::RunnerMode; -use crate::system::SystemInfo; +use crate::system::{SupportedOs, SystemInfo}; use async_trait::async_trait; use ipc_channel::ipc; use memtrack::MemtrackIpcClient; @@ -72,8 +73,15 @@ impl Executor for MemoryExecutor { ExecutorName::Memory } - fn tool_status(&self) -> ToolStatus { - get_memtrack_status() + fn tool_status(&self) -> Option { + Some(get_memtrack_status()) + } + + fn support_level(&self, system_info: &SystemInfo) -> ExecutorSupport { + match &system_info.os { + SupportedOs::Linux(_) => ExecutorSupport::FullySupported, + SupportedOs::Macos { .. } => ExecutorSupport::Unsupported, + } } async fn setup( diff --git a/src/executor/mod.rs b/src/executor/mod.rs index 3cee058e..353a1669 100644 --- a/src/executor/mod.rs +++ b/src/executor/mod.rs @@ -73,12 +73,28 @@ pub enum ToolInstallStatus { NotInstalled, } +/// How well a given executor runs on a given [`SupportedOs`]. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum ExecutorSupport { + /// The executor cannot run on this OS at all — `run_executor` hard-bails. + Unsupported, + /// The executor runs on this OS, but the user is responsible for installing the required tooling themselves. + RequiresManualInstallation, + /// The executor runs on this OS and `setup()` knows how to auto-install tooling. + FullySupported, +} + #[async_trait(?Send)] pub trait Executor { fn name(&self) -> ExecutorName; /// Report the installation status of the tool(s) this executor depends on. - fn tool_status(&self) -> ToolStatus; + fn tool_status(&self) -> Option; + + /// Declare how well this executor runs on the host system. Drives whether `setup()` is invoked + /// (only when [`ExecutorSupport::FullySupported`]) and whether we bail out of running the + /// executor at all (on [`ExecutorSupport::Unsupported`]). + fn support_level(&self, system_info: &SystemInfo) -> ExecutorSupport; async fn setup( &self, @@ -107,11 +123,24 @@ pub async fn run_executor( execution_context: &ExecutionContext, setup_cache_dir: Option<&Path>, ) -> Result<()> { - if !execution_context.config.skip_setup { - executor - .setup(&orchestrator.system_info, setup_cache_dir) - .await?; + match executor.support_level(&orchestrator.system_info) { + ExecutorSupport::Unsupported => { + bail!( + "The {} executor is not supported on {}", + executor.name(), + orchestrator.system_info.os + ); + } + ExecutorSupport::RequiresManualInstallation | ExecutorSupport::FullySupported => { + if !execution_context.config.skip_setup { + executor + .setup(&orchestrator.system_info, setup_cache_dir) + .await?; + } + } + } + if !execution_context.config.skip_setup { // TODO: refactor and move directly in the Instruments struct as a `setup` method if execution_context.config.instruments.is_mongodb_enabled() { install_mongodb_tracer().await?; diff --git a/src/executor/orchestrator.rs b/src/executor/orchestrator.rs index fe40c6ff..37e2cbf5 100644 --- a/src/executor/orchestrator.rs +++ b/src/executor/orchestrator.rs @@ -11,7 +11,7 @@ use crate::local_logger::rolling_buffer::{activate_rolling_buffer, deactivate_ro use crate::prelude::*; use crate::run_environment::{self, RunEnvironment, RunEnvironmentProvider}; use crate::runner_mode::RunnerMode; -use crate::system::{self, SystemInfo}; +use crate::system::SystemInfo; use crate::upload::poll_results::poll_results; use crate::upload::{UploadResult, upload}; use serde_json::Value; @@ -43,7 +43,6 @@ impl Orchestrator { ) -> Result { let provider = run_environment::get_provider(&config, api_client).await?; let system_info = SystemInfo::new()?; - system::check_system(&system_info)?; let logger = Logger::new(provider.as_ref())?; if provider.get_run_environment() == RunEnvironment::Local { diff --git a/src/executor/valgrind/executor.rs b/src/executor/valgrind/executor.rs index c81c1046..0d0cf1f1 100644 --- a/src/executor/valgrind/executor.rs +++ b/src/executor/valgrind/executor.rs @@ -3,12 +3,14 @@ use std::path::Path; use crate::executor::Executor; use crate::executor::ToolStatus; -use crate::executor::{ExecutionContext, ExecutorName}; +use crate::executor::{ExecutionContext, ExecutorName, ExecutorSupport}; use crate::instruments::mongo_tracer::MongoTracer; use crate::prelude::*; -use crate::system::SystemInfo; +use crate::system::{SupportedOs, SystemInfo}; -use super::setup::{get_valgrind_status, install_valgrind}; +use super::setup::get_valgrind_status; +use super::setup::install_valgrind; +use super::setup::is_codspeed_valgrind_installation_supported; use super::{helpers::perf_maps::harvest_perf_maps, helpers::venv_compat, measure}; pub struct ValgrindExecutor; @@ -19,8 +21,21 @@ impl Executor for ValgrindExecutor { ExecutorName::Valgrind } - fn tool_status(&self) -> ToolStatus { - get_valgrind_status() + fn tool_status(&self) -> Option { + Some(get_valgrind_status()) + } + + fn support_level(&self, system_info: &SystemInfo) -> ExecutorSupport { + match &system_info.os { + SupportedOs::Linux(_) => { + if is_codspeed_valgrind_installation_supported(system_info) { + ExecutorSupport::FullySupported + } else { + ExecutorSupport::RequiresManualInstallation + } + } + SupportedOs::Macos { .. } => ExecutorSupport::Unsupported, + } } async fn setup(&self, system_info: &SystemInfo, setup_cache_dir: Option<&Path>) -> Result<()> { diff --git a/src/executor/valgrind/setup.rs b/src/executor/valgrind/setup.rs index 0d04c892..b04a4c6c 100644 --- a/src/executor/valgrind/setup.rs +++ b/src/executor/valgrind/setup.rs @@ -2,7 +2,7 @@ use crate::cli::run::helpers::download_file; use crate::executor::helpers::apt; use crate::executor::{ToolInstallStatus, ToolStatus}; use crate::prelude::*; -use crate::system::SystemInfo; +use crate::system::{LinuxDistribution, SupportedOs, SystemInfo}; use crate::{ VALGRIND_CODSPEED_DEB_VERSION, VALGRIND_CODSPEED_VERSION, VALGRIND_CODSPEED_VERSION_STRING, }; @@ -10,27 +10,45 @@ use semver::Version; use std::{env, path::Path, process::Command}; use url::Url; -fn get_codspeed_valgrind_filename(system_info: &SystemInfo) -> Result { - let (version, architecture) = match ( - system_info.os.as_str(), - system_info.os_version.as_str(), - system_info.arch.as_str(), - ) { - ("ubuntu", "22.04", "x86_64") | ("debian", "12", "x86_64") => ("22.04", "amd64"), - ("ubuntu", "24.04", "x86_64") => ("24.04", "amd64"), - ("ubuntu", "22.04", "aarch64") | ("debian", "12", "aarch64") => ("22.04", "arm64"), - ("ubuntu", "24.04", "aarch64") => ("24.04", "arm64"), +pub(super) fn get_codspeed_valgrind_filename(system_info: &SystemInfo) -> Result { + let SupportedOs::Linux(distro) = &system_info.os else { + bail!("Unsupported system"); + }; + + let (deb_ubuntu_version, architecture) = match (distro, system_info.arch.as_str()) { + (LinuxDistribution::Ubuntu { version }, "x86_64") + | (LinuxDistribution::Debian { version }, "x86_64") + if version == "22.04" || version == "12" => + { + ("22.04", "amd64") + } + (LinuxDistribution::Ubuntu { version }, "x86_64") if version == "24.04" => { + ("24.04", "amd64") + } + (LinuxDistribution::Ubuntu { version }, "aarch64") + | (LinuxDistribution::Debian { version }, "aarch64") + if version == "22.04" || version == "12" => + { + ("22.04", "arm64") + } + (LinuxDistribution::Ubuntu { version }, "aarch64") if version == "24.04" => { + ("24.04", "arm64") + } _ => bail!("Unsupported system"), }; Ok(format!( "valgrind_{}_ubuntu-{}_{}.deb", VALGRIND_CODSPEED_DEB_VERSION.as_str(), - version, + deb_ubuntu_version, architecture )) } +pub(super) fn is_codspeed_valgrind_installation_supported(system_info: &SystemInfo) -> bool { + get_codspeed_valgrind_filename(system_info).is_ok() +} + /// Parse a valgrind version string and extract the semantic version. /// Expected format: "valgrind-3.25.1.codspeed" or "3.25.1.codspeed" /// Returns Some(Version) if parsing succeeds, None otherwise. @@ -175,8 +193,9 @@ mod tests { #[test] fn test_system_info_to_codspeed_valgrind_version_ubuntu() { let system_info = SystemInfo { - os: "ubuntu".to_string(), - os_version: "22.04".to_string(), + os: SupportedOs::Linux(LinuxDistribution::Ubuntu { + version: "22.04".into(), + }), arch: "x86_64".to_string(), ..SystemInfo::test() }; @@ -189,8 +208,9 @@ mod tests { #[test] fn test_system_info_to_codspeed_valgrind_version_ubuntu_24() { let system_info = SystemInfo { - os: "ubuntu".to_string(), - os_version: "24.04".to_string(), + os: SupportedOs::Linux(LinuxDistribution::Ubuntu { + version: "24.04".into(), + }), arch: "x86_64".to_string(), ..SystemInfo::test() }; @@ -203,8 +223,9 @@ mod tests { #[test] fn test_system_info_to_codspeed_valgrind_version_debian() { let system_info = SystemInfo { - os: "debian".to_string(), - os_version: "12".to_string(), + os: SupportedOs::Linux(LinuxDistribution::Debian { + version: "12".into(), + }), arch: "x86_64".to_string(), ..SystemInfo::test() }; @@ -217,8 +238,9 @@ mod tests { #[test] fn test_system_info_to_codspeed_valgrind_version_ubuntu_arm() { let system_info = SystemInfo { - os: "ubuntu".to_string(), - os_version: "22.04".to_string(), + os: SupportedOs::Linux(LinuxDistribution::Ubuntu { + version: "22.04".into(), + }), arch: "aarch64".to_string(), ..SystemInfo::test() }; @@ -228,6 +250,28 @@ mod tests { ); } + #[test] + fn test_codspeed_valgrind_filename_unsupported_os() { + let system_info = SystemInfo { + os: SupportedOs::Macos { + version: "14.0".into(), + }, + ..SystemInfo::test() + }; + assert!(get_codspeed_valgrind_filename(&system_info).is_err()); + } + + #[test] + fn test_codspeed_valgrind_filename_unsupported_distro() { + let system_info = SystemInfo { + os: SupportedOs::Linux(LinuxDistribution::Ubuntu { + version: "20.04".into(), + }), + ..SystemInfo::test() + }; + assert!(get_codspeed_valgrind_filename(&system_info).is_err()); + } + #[test] fn test_parse_valgrind_codspeed_version_with_prefix() { let version = parse_valgrind_codspeed_version("valgrind-3.25.1.codspeed").unwrap(); diff --git a/src/executor/wall_time/executor.rs b/src/executor/wall_time/executor.rs index 9103204f..4da11899 100644 --- a/src/executor/wall_time/executor.rs +++ b/src/executor/wall_time/executor.rs @@ -10,11 +10,11 @@ use crate::executor::helpers::get_bench_command::get_bench_command; use crate::executor::helpers::run_command_with_log_pipe::run_command_with_log_pipe; use crate::executor::helpers::run_with_env::wrap_with_env; use crate::executor::helpers::run_with_sudo::wrap_with_sudo; -use crate::executor::{ExecutionContext, ExecutorName}; +use crate::executor::{ExecutionContext, ExecutorName, ExecutorSupport}; use crate::instruments::mongo_tracer::MongoTracer; use crate::prelude::*; use crate::runner_mode::RunnerMode; -use crate::system::SystemInfo; +use crate::system::{SupportedOs, SystemInfo}; use async_trait::async_trait; use std::fs::canonicalize; use std::io::Write; @@ -121,8 +121,18 @@ impl Executor for WallTimeExecutor { ExecutorName::WallTime } - fn tool_status(&self) -> ToolStatus { - super::perf::setup::get_perf_status() + fn tool_status(&self) -> Option { + self.perf + .as_ref() + .map(|_| super::perf::setup::get_perf_status()) + } + + fn support_level(&self, system_info: &SystemInfo) -> ExecutorSupport { + match &system_info.os { + SupportedOs::Linux(distro) if distro.is_supported() => ExecutorSupport::FullySupported, + SupportedOs::Macos { .. } => ExecutorSupport::FullySupported, + SupportedOs::Linux(_) => ExecutorSupport::RequiresManualInstallation, + } } async fn setup(&self, system_info: &SystemInfo, setup_cache_dir: Option<&Path>) -> Result<()> { diff --git a/src/system/check.rs b/src/system/check.rs deleted file mode 100644 index 9aa35b0d..00000000 --- a/src/system/check.rs +++ /dev/null @@ -1,56 +0,0 @@ -use std::collections::HashSet; -use std::sync::LazyLock; - -use crate::prelude::*; - -use super::SystemInfo; - -static SUPPORTED_SYSTEMS: LazyLock> = - LazyLock::new(|| { - HashSet::from([ - ("ubuntu", "22.04", "x86_64"), - ("ubuntu", "24.04", "x86_64"), - ("ubuntu", "22.04", "aarch64"), - ("ubuntu", "24.04", "aarch64"), - ("debian", "12", "x86_64"), - ("debian", "12", "aarch64"), - ]) - }); - -/// Checks if the provided system info is supported -/// -/// Supported systems: -/// - Ubuntu 20.04 x86_64 -/// - Ubuntu 22.04 x86_64 and aarch64 -/// - Debian 11 x86_64 -/// - Debian 12 x86_64 -pub fn check_system(system_info: &SystemInfo) -> Result<()> { - debug!("System info: {system_info:#?}"); - - let system_tuple = ( - system_info.os.as_str(), - system_info.os_version.as_str(), - system_info.arch.as_str(), - ); - - if SUPPORTED_SYSTEMS.contains(&system_tuple) { - return Ok(()); - } - - match system_info.arch.as_str() { - "x86_64" | "aarch64" => { - warn!( - "Unofficially supported system: {} {}. Continuing with best effort support.", - system_info.os, system_info.os_version - ); - return Ok(()); - } - _ => {} - } - - bail!( - "Unsupported system: {} {}", - system_info.os, - system_info.os_version - ); -} diff --git a/src/system/info.rs b/src/system/info.rs index d62fec01..51f1bde4 100644 --- a/src/system/info.rs +++ b/src/system/info.rs @@ -1,9 +1,10 @@ use std::process::Command; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System}; use crate::prelude::*; +use crate::system::os::SupportedOs; fn get_user() -> Result { let user_output = Command::new("whoami") @@ -17,11 +18,12 @@ fn get_user() -> Result { Ok(output_str.trim().to_string()) } -#[derive(Eq, PartialEq, Hash, Serialize, Deserialize, Debug, Clone)] +#[derive(Eq, PartialEq, Hash, Serialize, Debug, Clone)] #[serde(rename_all = "camelCase")] pub struct SystemInfo { - pub os: String, - pub os_version: String, + /// Flattened to the `os` and `osVersion` fields on the wire via [`SupportedOs`]'s serde impl. + #[serde(flatten)] + pub os: SupportedOs, pub arch: String, pub host: String, pub user: String, @@ -37,8 +39,9 @@ pub struct SystemInfo { impl SystemInfo { pub fn test() -> Self { SystemInfo { - os: "ubuntu".to_string(), - os_version: "20.04".to_string(), + os: SupportedOs::Linux(crate::system::LinuxDistribution::Ubuntu { + version: "20.04".into(), + }), arch: "x86_64".to_string(), host: "host".to_string(), user: "user".to_string(), @@ -96,8 +99,7 @@ fn get_cpu_flags() -> Vec { impl SystemInfo { pub fn new() -> Result { - let os = System::distribution_id(); - let os_version = System::os_version().ok_or(anyhow!("Failed to get OS version"))?; + let os = SupportedOs::from_os(std::env::consts::OS)?; let arch = System::cpu_arch(); let user = get_user()?; let host = System::host_name().ok_or(anyhow!("Failed to get host name"))?; @@ -133,7 +135,6 @@ impl SystemInfo { Ok(SystemInfo { os, - os_version, arch, host, user, diff --git a/src/system/mod.rs b/src/system/mod.rs index df68d6a9..2ffb6534 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -1,5 +1,5 @@ -mod check; mod info; +mod os; -pub use check::check_system; pub use info::SystemInfo; +pub use os::{LinuxDistribution, SupportedOs}; diff --git a/src/system/os.rs b/src/system/os.rs new file mode 100644 index 00000000..b83cb22b --- /dev/null +++ b/src/system/os.rs @@ -0,0 +1,140 @@ +use std::fmt::{self, Display}; + +use serde::{Deserialize, Serialize}; +use sysinfo::System; + +use crate::prelude::*; +/// Typed representation of the host operating system. +/// +/// Only operating systems that CodSpeed can run on are represented here. +/// Construction via [`SupportedOs::from_current_system`] bails on unsupported platforms +#[derive(Eq, PartialEq, Hash, Debug, Clone, Serialize)] +#[serde(into = "SupportedOsSerde")] +pub enum SupportedOs { + Linux(LinuxDistribution), + Macos { version: String }, +} + +impl SupportedOs { + /// Build a [`SupportedOs`] from the given OS family string. + /// Expects `std::env::consts::OS` as input + /// + /// For Linux, the distribution is identified via `sysinfo::System::distribution_id()`. + /// The OS version is read from `sysinfo::System::os_version()`. + pub fn from_os(os: &str) -> Result { + let os_version = System::os_version().ok_or(anyhow!("Failed to get OS version"))?; + match os { + "linux" => { + let os_id = System::distribution_id(); + Ok(Self::Linux(LinuxDistribution::from_id(&os_id, &os_version))) + } + "macos" => Ok(Self::Macos { + version: os_version, + }), + unsupported => bail!("Unsupported operating system: {unsupported}"), + } + } + + /// The distro/OS id as it appears on the wire (matches `sysinfo::System::distribution_id()`). + pub fn id(&self) -> &str { + match self { + Self::Linux(distro) => distro.id(), + Self::Macos { .. } => "macos", + } + } + + pub fn version(&self) -> &str { + match self { + Self::Linux(distro) => distro.version(), + Self::Macos { version } => version, + } + } +} + +impl Display for SupportedOs { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} {}", self.id(), self.version()) + } +} + +/// Flat `{os, osVersion}` shape we emit on the wire as part of `SystemInfo`. +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SupportedOsSerde { + os: String, + os_version: String, +} + +impl From for SupportedOsSerde { + fn from(os: SupportedOs) -> Self { + SupportedOsSerde { + os: os.id().to_string(), + os_version: os.version().to_string(), + } + } +} + +/// Linux distribution, identified by the `sysinfo` distribution id. +#[derive(Eq, PartialEq, Hash, Debug, Clone)] +pub enum LinuxDistribution { + Ubuntu { version: String }, + Debian { version: String }, + Other { name: String, version: String }, +} + +impl LinuxDistribution { + /// Build a [`LinuxDistribution`] from the raw `(os_id, version)` strings reported by `sysinfo`. + fn from_id(os_id: &str, version: &str) -> Self { + match os_id { + "ubuntu" => Self::Ubuntu { + version: version.to_string(), + }, + "debian" => Self::Debian { + version: version.to_string(), + }, + _ => Self::Other { + name: os_id.to_string(), + version: version.to_string(), + }, + } + } + + /// The distro id as it appears on the wire (matches `sysinfo::System::distribution_id()`). + pub fn id(&self) -> &str { + match self { + Self::Ubuntu { .. } => "ubuntu", + Self::Debian { .. } => "debian", + Self::Other { name, .. } => name, + } + } + + pub fn version(&self) -> &str { + match self { + Self::Ubuntu { version } | Self::Debian { version } | Self::Other { version, .. } => { + version + } + } + } + + /// Whether this distribution has first-class support (auto-install via apt, prebuilt .debs, etc.). + pub fn is_supported(&self) -> bool { + matches!(self, Self::Ubuntu { .. } | Self::Debian { .. }) + } +} + +impl Display for LinuxDistribution { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{} {}", self.id(), self.version()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn from_os_bails_on_unsupported() { + let err = SupportedOs::from_os("windows").unwrap_err(); + assert_eq!(err.to_string(), "Unsupported operating system: windows"); + } +} diff --git a/src/upload/interfaces.rs b/src/upload/interfaces.rs index c6dc2a8d..e07c4525 100644 --- a/src/upload/interfaces.rs +++ b/src/upload/interfaces.rs @@ -7,7 +7,7 @@ use crate::system::SystemInfo; pub const LATEST_UPLOAD_METADATA_VERSION: u32 = 10; -#[derive(Deserialize, Serialize, Debug)] +#[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct UploadMetadata { pub repository_provider: RepositoryProvider, @@ -24,7 +24,7 @@ pub struct UploadMetadata { pub run_environment_metadata: RunEnvironmentMetadata, } -#[derive(Deserialize, Serialize, Debug)] +#[derive(Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Runner { pub name: String, diff --git a/src/upload/upload_metadata.rs b/src/upload/upload_metadata.rs index 68cf51d3..fd64758e 100644 --- a/src/upload/upload_metadata.rs +++ b/src/upload/upload_metadata.rs @@ -96,8 +96,12 @@ mod tests { instruments: vec![], executor: ExecutorName::Valgrind, system_info: SystemInfo { - os: "nixos".to_string(), - os_version: "25.11".to_string(), + os: crate::system::SupportedOs::Linux( + crate::system::LinuxDistribution::Other { + name: "nixos".into(), + version: "25.11".into(), + }, + ), arch: "x86_64".to_string(), host: "badlands".to_string(), user: "guillaume".to_string(), From 25ee00100bbc04aba3b1c5df0fe0535d2d386bd1 Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Mon, 13 Apr 2026 16:07:46 +0200 Subject: [PATCH 08/10] chore: skip tests that rely on linux behavior These tests panic on macOS, and for now are not relevant since we do not support profiling on macOS. When we do support it, we should have os-specific tests --- src/executor/shared/fifo.rs | 2 +- src/executor/tests.rs | 2 ++ src/executor/wall_time/perf/debug_info.rs | 4 +++- src/executor/wall_time/perf/module_symbols.rs | 2 +- src/executor/wall_time/perf/unwind_data.rs | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/executor/shared/fifo.rs b/src/executor/shared/fifo.rs index 39b9533b..577f7bed 100644 --- a/src/executor/shared/fifo.rs +++ b/src/executor/shared/fifo.rs @@ -275,7 +275,7 @@ impl RunnerFifo { } } -#[cfg(test)] +#[cfg(all(test, target_os = "linux"))] mod tests { use super::*; use std::time::Duration; diff --git a/src/executor/tests.rs b/src/executor/tests.rs index db982741..fe38e3a5 100644 --- a/src/executor/tests.rs +++ b/src/executor/tests.rs @@ -146,6 +146,7 @@ async fn acquire_bpf_instrumentation_lock() -> SemaphorePermit<'static> { semaphore.acquire().await.unwrap() } +#[cfg(target_os = "linux")] mod valgrind { use super::*; use crate::executor::valgrind::executor::ValgrindExecutor; @@ -377,6 +378,7 @@ fi } } +#[cfg(target_os = "linux")] #[test_with::env(GITHUB_ACTIONS)] mod memory { use super::*; diff --git a/src/executor/wall_time/perf/debug_info.rs b/src/executor/wall_time/perf/debug_info.rs index 5e252bb3..5109044b 100644 --- a/src/executor/wall_time/perf/debug_info.rs +++ b/src/executor/wall_time/perf/debug_info.rs @@ -127,7 +127,9 @@ pub fn debug_info_by_path( .collect() } -#[cfg(test)] +// These tests parse Linux ELF binaries from `testdata/`; gate them on Linux so they're not +// attempted (and don't abort the test process) when running on macOS. +#[cfg(all(test, target_os = "linux"))] mod tests { use super::*; diff --git a/src/executor/wall_time/perf/module_symbols.rs b/src/executor/wall_time/perf/module_symbols.rs index c9d8fb1f..240a2602 100644 --- a/src/executor/wall_time/perf/module_symbols.rs +++ b/src/executor/wall_time/perf/module_symbols.rs @@ -177,7 +177,7 @@ impl ModuleSymbols { } } -#[cfg(test)] +#[cfg(all(test, target_os = "linux"))] mod tests { use super::*; diff --git a/src/executor/wall_time/perf/unwind_data.rs b/src/executor/wall_time/perf/unwind_data.rs index 3b538309..ae39e69d 100644 --- a/src/executor/wall_time/perf/unwind_data.rs +++ b/src/executor/wall_time/perf/unwind_data.rs @@ -87,7 +87,7 @@ pub fn unwind_data_from_elf( Ok((v3, mapping)) } -#[cfg(test)] +#[cfg(all(test, target_os = "linux"))] mod tests { use super::*; From d6ec5b14e24ce53a65ac6881e8060a21f763821d Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Thu, 16 Apr 2026 16:58:48 +0200 Subject: [PATCH 09/10] feat: make the basic run only 5 rounds to make logs not crash the github page --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 27f62812..7d6b798d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: # We use Swatinem/rust-cache to cache cargo registry, index and target in this job - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2 - name: Run tests - run: cargo run -- exec -m simulation,walltime,memory --skip-upload -- ls -la + run: cargo run -- exec -m simulation,walltime,memory --skip-upload --warmup-time 0s --max-rounds 5 -- ls -la bpf-tests: runs-on: ubuntu-latest From 8e74cca03e37892aaaa14ee0854ae4846cb2c99e Mon Sep 17 00:00:00 2001 From: Guillaume Lagrange Date: Thu, 16 Apr 2026 17:01:20 +0200 Subject: [PATCH 10/10] chore: move the config schema check from pre-commit to ci-only check --- .github/workflows/ci.yml | 2 ++ .pre-commit-config.yaml | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d6b798d..f9f3c788 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,8 @@ jobs: - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 with: extra_args: --all-files + - name: Check config schema is up to date + run: cargo run --bin generate_config_schema && git diff --exit-code schemas/codspeed.schema.json tests: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5f3e3c2..803314c9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,9 +25,3 @@ repos: - id: clang-format files: ^crates/memtrack/src/ebpf/c/.*\.(c|h|bpf\.c)$ args: [--style=file, -i] - - repo: local - hooks: - - id: check-config-schema - name: check config schema is up to date - entry: bash -c 'cargo run --bin generate_config_schema && git diff --exit-code schemas/codspeed.schema.json' - language: system