diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ba1012..f72ec6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [1.15.0] +- Ensuring temp files are cleaned up +- Applying visual style to the update check output + ## [1.14.0] - Fixed several malformed rules - Now validating that response_matcher is present in validation section of all rules diff --git a/src/main.rs b/src/main.rs index 673a99b..7314aa2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -190,6 +190,8 @@ async fn async_main(args: CommandLineArgs) -> Result<()> { let rules_db = Arc::new(load_and_record_rules(&scan_args, &datastore)?); run_scan(&args.global_args, &scan_args, &rules_db, Arc::clone(&datastore)).await?; let exit_code = determine_exit_code(&datastore); + + temp_dir.close()?; std::process::exit(exit_code); } Command::Rules(ref rule_args) => match &rule_args.command { diff --git a/src/update.rs b/src/update.rs index 59cbea0..5648855 100644 --- a/src/update.rs +++ b/src/update.rs @@ -1,25 +1,32 @@ -use std::{fs, io::ErrorKind, path::PathBuf}; +use std::{ + fs, + io::{ErrorKind, IsTerminal}, + path::PathBuf, +}; use self_update::{backends::github::Update, cargo_crate_version, errors::Error as UpdError}; use tracing::{error, info, warn}; use crate::cli::global::GlobalArgs; +use crate::reporter::styles::Styles; /// Return `true` when the canonical executable path lives inside a Homebrew Cellar. -/// Works for Intel macOS (/usr/local/Cellar), Apple-Silicon macOS (/opt/homebrew/Cellar) +/// Works for Intel macOS (/usr/local/Cellar), Apple‑Silicon macOS (/opt/homebrew/Cellar) /// and Linuxbrew (~/.linuxbrew/Cellar). fn installed_via_homebrew() -> bool { fn canonical_exe() -> Option { std::env::current_exe().ok().and_then(|p| fs::canonicalize(p).ok()) } - canonical_exe().map(|p| p.components().any(|c| c.as_os_str() == "Cellar")).unwrap_or(false) + canonical_exe() + .map(|p| p.components().any(|c| c.as_os_str() == "Cellar")) + .unwrap_or(false) } /// Check GitHub for a newer Kingfisher release. /// /// * `base_url` lets tests point at a mock server. -/// * Self-update is performed unless the user disabled it **or** the binary is a Homebrew install. +/// * Self‑update is performed unless the user disabled it **or** the binary is a Homebrew install. pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Option { if global_args.no_update_check { return None; @@ -27,11 +34,19 @@ pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Opt let is_brew = installed_via_homebrew(); if is_brew { - info!("Homebrew install detected – will notify about updates but not self-update"); + info!( + "Homebrew install detected – will notify about updates but not self‑update" + ); } info!("Checking for updates…"); + // ------------------------------------------------------------- + // Prepare colour/style helper so every message looks consistent + // ------------------------------------------------------------- + let use_color = std::io::stderr().is_terminal() && !global_args.quiet; + let styles = Styles::new(use_color); + let mut builder = Update::configure(); builder .repo_owner("mongodb") @@ -54,15 +69,22 @@ pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Opt return None; }; + // ---------------------------- + // Already on the latest version + // ---------------------------- if release.version == cargo_crate_version!() { - let msg = format!("Kingfisher {} is up to date", release.version); - info!("{msg}"); - return Some(msg); + let plain = format!("Kingfisher {} is up to date", release.version); + let styled = styles.style_finding_active_heading.apply_to(&plain); + info!("{}", styled); + return Some(plain); } - // There is a newer release. - let msg = format!("New Kingfisher release {} available", release.version); - info!("{msg}"); + // ---------------------------- + // A newer version is available + // ---------------------------- + let plain = format!("New Kingfisher release {} available", release.version); + let styled = styles.style_finding_active_heading.apply_to(&plain); + info!("{}", styled); // Decide whether to perform the update in place. if global_args.self_update && !is_brew { @@ -73,7 +95,7 @@ pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Opt warn!( "Cannot replace the current binary – permission denied.\n\ If you installed via a package manager, run its upgrade command.\n\ - Otherwise reinstall to a user-writable directory or re-run with sudo." + Otherwise reinstall to a user‑writable directory or re‑run with sudo." ); } _ => error!("Failed to update: {e}"), @@ -83,5 +105,5 @@ pub fn check_for_update(global_args: &GlobalArgs, base_url: Option<&str>) -> Opt info!("Run `brew upgrade kingfisher` to install the new version."); } - Some(msg) + Some(plain) } diff --git a/testdata/e2e/e2e_localgit.go b/testdata/e2e/e2e_localgit.go deleted file mode 100644 index 8d78145..0000000 --- a/testdata/e2e/e2e_localgit.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "strconv" - - regexp "github.com/wasilibs/go-re2" -) - -func main() { - // fmt.Println(">> [*] Testing 'kingfisher local-git' functionality against owasp/wrongsecrets repo.") - - // Remove the existing /tmp/wrongsecrets directory - if err := os.RemoveAll("/tmp/wrongsecrets"); err != nil { - fmt.Printf("Error removing /tmp/wrongsecrets: %s\n", err) - return - } - - // Clone the owasp/wrongsecrets repository - gitCloneCmd := exec.Command("git", "clone", "https://github.com/OWASP/wrongsecrets.git", "/tmp/wrongsecrets", "--depth", "1") - if err := gitCloneCmd.Run(); err != nil { - fmt.Printf("Error cloning repository: %s\n", err) - return - } - defer os.RemoveAll("/tmp/wrongsecrets") - - // Get the current working directory - cwd, err := os.Getwd() - if err != nil { - fmt.Printf("Error getting current directory: %s\n", err) - return - } - - // Construct the path to main.go - mainGoPath := filepath.Join(cwd, "main.go") - - // Run the main.go with local-git command - mainGoCmd := exec.Command("go", "run", mainGoPath, "local-git", "--path", "/tmp/wrongsecrets", "--silent", "--debug", "--confidence", "low") - outputBytes, err := mainGoCmd.CombinedOutput() - if err != nil { - fmt.Printf("Error running main.go: %s\nOutput: %s\n", err, string(outputBytes)) - return - } - output := string(outputBytes) - - // Print output - // fmt.Println(output) - - // Extract the number of files processed - re := regexp.MustCompile(`Files Read\.*?: (\d+)`) - matches := re.FindStringSubmatch(output) - if len(matches) < 2 { - fmt.Println("Error: Could not find files count") - os.Exit(1) - return - } - - filesCount, err := strconv.Atoi(matches[1]) - if err != nil { - fmt.Printf("Error parsing files count: %s\n", err) - os.Exit(1) - return - } - - // Check if the files count is greater than 10 - if filesCount <= 10 { - fmt.Printf("Error: Files count (%d) is not greater than 10\n", filesCount) - os.Exit(1) - return - } - - fmt.Println("Test completed successfully.") -} diff --git a/tests/smoke_update.rs b/tests/smoke_update.rs index 29ae49c..8224d42 100644 --- a/tests/smoke_update.rs +++ b/tests/smoke_update.rs @@ -16,9 +16,9 @@ async fn detects_new_release() { let server = MockServer::start().await; let body = serde_json::json!({ - "tag_name": "v1.99.0", + "tag_name": "v99.999.0", "created_at": "2025-01-01T00:00:00Z", - "name": "Kingfisher 1.99.0", + "name": "Kingfisher 99.999.0", "body": "", "assets": [{"url": "http://example.com/bin", "name": "bin"}] }); @@ -42,5 +42,5 @@ async fn detects_new_release() { .expect("blocking task panicked") .expect("update checker returned None"); - assert!(msg.contains("1.99.0")); + assert!(msg.contains("99.999.0")); }