From 96beba6e49abf3d7904d2f23b979f3f223e72989 Mon Sep 17 00:00:00 2001 From: Adrien Cacciaguerra Date: Thu, 6 Jun 2024 21:45:28 +0000 Subject: [PATCH] feat: add system info to upload metadata runner property --- src/run/{runner => }/check_system.rs | 53 +++++++++- src/run/ci_provider/provider.rs | 9 +- src/run/mod.rs | 6 +- src/run/runner/mod.rs | 1 - src/run/runner/run.rs | 10 +- src/run/runner/setup.rs | 100 +++++++----------- src/run/uploader/interfaces.rs | 7 +- ...ad_metadata__tests__get_metadata_hash.snap | 7 +- src/run/uploader/upload.rs | 13 ++- src/run/uploader/upload_metadata.rs | 4 +- 10 files changed, 131 insertions(+), 79 deletions(-) rename src/run/{runner => }/check_system.rs (62%) diff --git a/src/run/runner/check_system.rs b/src/run/check_system.rs similarity index 62% rename from src/run/runner/check_system.rs rename to src/run/check_system.rs index d51469d..f3b4830 100644 --- a/src/run/runner/check_system.rs +++ b/src/run/check_system.rs @@ -1,5 +1,7 @@ use std::process::Command; +use serde::{Deserialize, Serialize}; + use crate::prelude::*; /// Returns the OS and version of the system @@ -45,14 +47,54 @@ fn get_arch() -> Result { Ok(output_str.trim().to_string()) } -#[derive(Eq, PartialEq, Hash)] +fn get_host() -> Result { + let host_output = Command::new("hostname") + .output() + .map_err(|_| anyhow!("Failed to get host info"))?; + if !host_output.status.success() { + bail!("Failed to get host info"); + } + let output_str = + String::from_utf8(host_output.stdout).map_err(|_| anyhow!("Failed to parse host info"))?; + Ok(output_str.trim().to_string()) +} + +fn get_user() -> Result { + let user_output = Command::new("whoami") + .output() + .map_err(|_| anyhow!("Failed to get user info"))?; + if !user_output.status.success() { + bail!("Failed to get user info"); + } + let output_str = + String::from_utf8(user_output.stdout).map_err(|_| anyhow!("Failed to parse user info"))?; + Ok(output_str.trim().to_string()) +} + +#[derive(Eq, PartialEq, Hash, Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] pub struct SystemInfo { pub os: String, pub os_version: String, pub arch: String, + pub host: String, + pub user: String, } -/// Checks if the system is supported +#[cfg(test)] +impl SystemInfo { + pub fn test() -> Self { + SystemInfo { + os: "Ubuntu".to_string(), + os_version: "20.04".to_string(), + arch: "amd64".to_string(), + host: "host".to_string(), + user: "user".to_string(), + } + } +} + +/// Checks if the system is supported and returns the system info /// /// Supported systems: /// - Ubuntu 20.04 on amd64 @@ -73,9 +115,16 @@ pub fn check_system() -> Result { if arch != "amd64" && arch != "arm64" { bail!("Only amd64 and arm64 are supported at the moment"); } + let user = get_user()?; + debug!("User: {}", user); + let host = get_host()?; + debug!("Host: {}", host); + Ok(SystemInfo { os, os_version, arch, + host, + user, }) } diff --git a/src/run/ci_provider/provider.rs b/src/run/ci_provider/provider.rs index 4e5c769..0ad0296 100644 --- a/src/run/ci_provider/provider.rs +++ b/src/run/ci_provider/provider.rs @@ -2,6 +2,7 @@ use git2::Repository; use simplelog::SharedLogger; use crate::prelude::*; +use crate::run::check_system::SystemInfo; use crate::run::config::Config; use crate::run::uploader::{Runner, UploadMetadata}; @@ -71,7 +72,12 @@ pub trait CIProvider { /// let instruments = Instruments::new(); /// let metadata = provider.get_upload_metadata(&config, "abc123").unwrap(); /// ``` - fn get_upload_metadata(&self, config: &Config, archive_hash: &str) -> Result { + fn get_upload_metadata( + &self, + config: &Config, + system_info: &SystemInfo, + archive_hash: &str, + ) -> Result { let provider_metadata = self.get_provider_metadata()?; let commit_hash = get_commit_hash(&provider_metadata.repository_root_path)?; @@ -86,6 +92,7 @@ pub trait CIProvider { name: "codspeed-runner".into(), version: crate::VERSION.into(), instruments: config.instruments.get_active_instrument_names(), + system_info: system_info.clone(), }, platform: self.get_provider_slug().into(), }) diff --git a/src/run/mod.rs b/src/run/mod.rs index 7506f45..bf6dcd3 100644 --- a/src/run/mod.rs +++ b/src/run/mod.rs @@ -5,6 +5,7 @@ use crate::run::{config::Config, logger::Logger}; use crate::VERSION; use clap::Args; +mod check_system; pub mod ci_provider; mod helpers; mod instruments; @@ -118,12 +119,13 @@ pub async fn run(args: RunArgs, api_client: &CodSpeedAPIClient) -> Result<()> { config.set_token(codspeed_config.auth.token.clone()); } - let run_data = runner::run(&config).await?; + let system_info = check_system::check_system()?; + let run_data = runner::run(&config, &system_info).await?; if !config.skip_upload { start_group!("Upload the results"); logger.persist_log_to_profile_folder(&run_data)?; - let upload_result = uploader::upload(&config, &provider, &run_data).await?; + let upload_result = uploader::upload(&config, &system_info, &provider, &run_data).await?; end_group!(); if provider.get_provider_slug() == "local" { diff --git a/src/run/runner/mod.rs b/src/run/runner/mod.rs index ecd9468..5ae8c8c 100644 --- a/src/run/runner/mod.rs +++ b/src/run/runner/mod.rs @@ -1,4 +1,3 @@ -mod check_system; mod helpers; mod run; mod setup; diff --git a/src/run/runner/run.rs b/src/run/runner/run.rs index 1f2a8d5..8afa8cd 100644 --- a/src/run/runner/run.rs +++ b/src/run/runner/run.rs @@ -1,10 +1,11 @@ use crate::prelude::*; -use crate::run::{config::Config, instruments::mongo_tracer::MongoTracer}; +use crate::run::{ + check_system::SystemInfo, config::Config, instruments::mongo_tracer::MongoTracer, +}; use std::path::PathBuf; use super::{ - check_system::check_system, helpers::{perf_maps::harvest_perf_maps, profile_folder::create_profile_folder}, setup::setup, valgrind, @@ -14,11 +15,10 @@ pub struct RunData { pub profile_folder: PathBuf, } -pub async fn run(config: &Config) -> Result { +pub async fn run(config: &Config, system_info: &SystemInfo) -> Result { if !config.skip_setup { start_group!("Prepare the environment"); - let system_info = check_system()?; - setup(&system_info, config).await?; + setup(system_info, config).await?; end_group!(); } //TODO: add valgrind version check diff --git a/src/run/runner/setup.rs b/src/run/runner/setup.rs index e484db2..c9f3985 100644 --- a/src/run/runner/setup.rs +++ b/src/run/runner/setup.rs @@ -1,14 +1,12 @@ use std::{ - collections::HashMap, env, process::{Command, Stdio}, }; -use lazy_static::lazy_static; use url::Url; -use super::{check_system::SystemInfo, helpers::download_file::download_file}; -use crate::run::config::Config; +use super::helpers::download_file::download_file; +use crate::run::{check_system::SystemInfo, config::Config}; use crate::{prelude::*, MONGODB_TRACER_VERSION, VALGRIND_CODSPEED_VERSION}; /// Run a command with sudo if available @@ -40,55 +38,23 @@ fn run_with_sudo(command_args: &[&str]) -> Result<()> { Ok(()) } -lazy_static! { - static ref SYSTEM_INFO_TO_CODSPEED_VALGRIND_FILENAME: HashMap = { - let mut m = HashMap::new(); - m.insert( - SystemInfo { - os: "Ubuntu".to_string(), - os_version: "20.04".to_string(), - arch: "amd64".to_string(), - }, - format!( - "valgrind_{}_ubuntu-{}_amd64.deb", - VALGRIND_CODSPEED_VERSION, "20.04" - ), - ); - m.insert( - SystemInfo { - os: "Ubuntu".to_string(), - os_version: "22.04".to_string(), - arch: "amd64".to_string(), - }, - format!( - "valgrind_{}_ubuntu-{}_amd64.deb", - VALGRIND_CODSPEED_VERSION, "22.04" - ), - ); - m.insert( - SystemInfo { - os: "Debian".to_string(), - os_version: "11".to_string(), - arch: "amd64".to_string(), - }, - format!( - "valgrind_{}_ubuntu-{}_amd64.deb", - VALGRIND_CODSPEED_VERSION, "20.04" - ), - ); - m.insert( - SystemInfo { - os: "Debian".to_string(), - os_version: "12".to_string(), - arch: "amd64".to_string(), - }, - format!( - "valgrind_{}_ubuntu-{}_amd64.deb", - VALGRIND_CODSPEED_VERSION, "20.04" - ), - ); - m +fn get_codspeed_valgrind_filename(system_info: &SystemInfo) -> Result { + let version = match ( + system_info.os.as_str(), + system_info.os_version.as_str(), + system_info.arch.as_str(), + ) { + ("Ubuntu", "20.04", "amd64") => "20.04", + ("Ubuntu", "22.04", "amd64") => "22.04", + ("Debian", "11", "amd64") => "20.04", + ("Debian", "12", "amd64") => "20.04", + _ => bail!("Unsupported system"), }; + + Ok(format!( + "valgrind_{}_ubuntu_{}_amd64.deb", + VALGRIND_CODSPEED_VERSION, version + )) } fn check_installed_valgrind() -> Result { @@ -119,9 +85,7 @@ async fn install_valgrind(system_info: &SystemInfo) -> Result<()> { let valgrind_deb_url = format!( "https://github.com/CodSpeedHQ/valgrind-codspeed/releases/download/{}/{}", VALGRIND_CODSPEED_VERSION, - SYSTEM_INFO_TO_CODSPEED_VALGRIND_FILENAME - .get(system_info) - .context("Unsupported system")? + get_codspeed_valgrind_filename(system_info)? ); let deb_path = env::temp_dir().join("valgrind-codspeed.deb"); download_file(&Url::parse(valgrind_deb_url.as_str()).unwrap(), &deb_path).await?; @@ -174,18 +138,32 @@ mod tests { use super::*; #[test] - fn test_system_info_to_codspeed_valgrind_version() { + fn test_system_info_to_codspeed_valgrind_version_ubuntu() { + let system_info = SystemInfo { + os: "Ubuntu".to_string(), + os_version: "22.04".to_string(), + arch: "amd64".to_string(), + host: "host".to_string(), + user: "user".to_string(), + }; + assert_eq!( + get_codspeed_valgrind_filename(&system_info).unwrap(), + "valgrind_3.21.0-0codspeed1_ubuntu_22.04_amd64.deb" + ); + } + + #[test] + fn test_system_info_to_codspeed_valgrind_version_debian() { let system_info = SystemInfo { os: "Debian".to_string(), os_version: "11".to_string(), arch: "amd64".to_string(), + host: "host".to_string(), + user: "user".to_string(), }; assert_eq!( - SYSTEM_INFO_TO_CODSPEED_VALGRIND_FILENAME[&system_info], - format!( - "valgrind_{}_ubuntu-{}_amd64.deb", - VALGRIND_CODSPEED_VERSION, "20.04" - ) + get_codspeed_valgrind_filename(&system_info).unwrap(), + "valgrind_3.21.0-0codspeed1_ubuntu_20.04_amd64.deb" ); } } diff --git a/src/run/uploader/interfaces.rs b/src/run/uploader/interfaces.rs index 5ade856..66943aa 100644 --- a/src/run/uploader/interfaces.rs +++ b/src/run/uploader/interfaces.rs @@ -1,6 +1,9 @@ use serde::{Deserialize, Serialize}; -use crate::run::{ci_provider::interfaces::ProviderMetadata, instruments::InstrumentNames}; +use crate::run::{ + check_system::SystemInfo, ci_provider::interfaces::ProviderMetadata, + instruments::InstrumentNames, +}; #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] @@ -21,6 +24,8 @@ pub struct Runner { pub name: String, pub version: String, pub instruments: Vec, + #[serde(flatten)] + pub system_info: SystemInfo, } #[derive(Deserialize, Serialize, Debug)] diff --git a/src/run/uploader/snapshots/codspeed_runner__run__uploader__upload_metadata__tests__get_metadata_hash.snap b/src/run/uploader/snapshots/codspeed_runner__run__uploader__upload_metadata__tests__get_metadata_hash.snap index d41c738..2cddcb0 100644 --- a/src/run/uploader/snapshots/codspeed_runner__run__uploader__upload_metadata__tests__get_metadata_hash.snap +++ b/src/run/uploader/snapshots/codspeed_runner__run__uploader__upload_metadata__tests__get_metadata_hash.snap @@ -11,7 +11,12 @@ expression: upload_metadata "version": "2.1.0", "instruments": [ "MongoDB" - ] + ], + "os": "Ubuntu", + "osVersion": "20.04", + "arch": "amd64", + "host": "host", + "user": "user" }, "platform": "github-actions", "commitHash": "5bd77cb0da72bef094893ed45fb793ff16ecfbe3", diff --git a/src/run/uploader/upload.rs b/src/run/uploader/upload.rs index 41a80da..9b98003 100644 --- a/src/run/uploader/upload.rs +++ b/src/run/uploader/upload.rs @@ -1,4 +1,6 @@ -use crate::run::{ci_provider::CIProvider, config::Config, runner::RunData}; +use crate::run::{ + check_system::SystemInfo, ci_provider::CIProvider, config::Config, runner::RunData, +}; use crate::{prelude::*, request_client::REQUEST_CLIENT}; use async_compression::tokio::write::GzipEncoder; use base64::{engine::general_purpose, Engine as _}; @@ -76,6 +78,7 @@ pub struct UploadResult { #[allow(clippy::borrowed_box)] pub async fn upload( config: &Config, + system_info: &SystemInfo, provider: &Box, run_data: &RunData, ) -> Result { @@ -83,7 +86,7 @@ pub async fn upload( debug!("CI provider detected: {:#?}", provider.get_provider_name()); - let upload_metadata = provider.get_upload_metadata(config, &archive_hash)?; + let upload_metadata = provider.get_upload_metadata(config, system_info, &archive_hash)?; debug!("Upload metadata: {:#?}", upload_metadata); if upload_metadata.tokenless { let hash = upload_metadata.get_hash(); @@ -110,7 +113,6 @@ mod tests { use url::Url; use super::*; - use crate::run::runner::RunData; use std::path::PathBuf; // TODO: remove the ignore when implementing network mocking @@ -129,6 +131,7 @@ mod tests { env!("CARGO_MANIFEST_DIR") )), }; + let system_info = SystemInfo::test(); async_with_vars( [ ("GITHUB_ACTIONS", Some("true")), @@ -159,7 +162,9 @@ mod tests { ], async { let provider = crate::run::ci_provider::get_provider(&config).unwrap(); - upload(&config, &provider, &run_data).await.unwrap(); + upload(&config, &system_info, &provider, &run_data) + .await + .unwrap(); }, ) .await; diff --git a/src/run/uploader/upload_metadata.rs b/src/run/uploader/upload_metadata.rs index 94d36d5..d9a74f7 100644 --- a/src/run/uploader/upload_metadata.rs +++ b/src/run/uploader/upload_metadata.rs @@ -14,6 +14,7 @@ mod tests { use insta::assert_json_snapshot; use crate::run::{ + check_system::SystemInfo, ci_provider::interfaces::{GhData, ProviderMetadata, RunEvent, Sender}, instruments::InstrumentNames, uploader::{Runner, UploadMetadata}, @@ -29,6 +30,7 @@ mod tests { name: "codspeed-runner".into(), version: "2.1.0".into(), instruments: vec![InstrumentNames::MongoDB], + system_info: SystemInfo::test(), }, platform: "github-actions".into(), commit_hash: "5bd77cb0da72bef094893ed45fb793ff16ecfbe3".into(), @@ -54,7 +56,7 @@ mod tests { let hash = upload_metadata.get_hash(); assert_eq!( hash, - "8beb149c4645c666156e24fe0f68d24a63cec1d7756f35dd17cab1d84528ed7b" + "898dad88936e7361581d7a9cc9bf01dd35451bdcb1074397dd577bda87c1002e" ); assert_json_snapshot!(upload_metadata); }