diff --git a/Cargo.toml b/Cargo.toml index c72e26bae..5ee604ee8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,6 +101,7 @@ hyper = "1.1" mime = "0.3" bytes = "1.1" ipnetwork = "0.20.0" +semver = "1" axum-test = { version = "16.1.0", optional = true } diff --git a/examples/demo/Cargo.lock b/examples/demo/Cargo.lock index 3d5d8fa95..e3862cde8 100644 --- a/examples/demo/Cargo.lock +++ b/examples/demo/Cargo.lock @@ -946,38 +946,6 @@ version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" -[[package]] -name = "camino" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.23", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cc" version = "1.1.30" @@ -2983,6 +2951,23 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "loco-gen" +version = "0.11.0" +dependencies = [ + "chrono", + "clap", + "dialoguer", + "duct", + "lazy_static", + "regex", + "rrgen", + "serde", + "serde_json", + "thiserror", + "tracing", +] + [[package]] name = "loco-rs" version = "0.11.0" @@ -2996,12 +2981,10 @@ dependencies = [ "bb8", "byte-unit", "bytes", - "cargo_metadata", "cfg-if", "chrono", "clap", "colored", - "dialoguer", "duct", "duct_sh", "english-to-cron", @@ -3014,15 +2997,16 @@ dependencies = [ "jsonwebtoken", "lazy_static", "lettre", + "loco-gen", "mime", "moka", "object_store", "rand", "regex", - "rrgen", "rusty-sidekiq", "sea-orm", "sea-orm-migration", + "semver 1.0.23", "serde", "serde_json", "serde_variant", @@ -4793,9 +4777,6 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" -dependencies = [ - "serde", -] [[package]] name = "semver-parser" diff --git a/src/cli.rs b/src/cli.rs index 731bb8435..550d17b64 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -546,7 +546,7 @@ pub async fn main() -> crate::Result<()> { println!("Environment: {}", &environment); } else { let mut should_exit = false; - for (_, check) in doctor::run_all(&config).await { + for (_, check) in doctor::run_all(&config).await? { if !should_exit && !check.valid() { should_exit = true; } diff --git a/src/db.rs b/src/db.rs index 19fe38564..fcbd3faad 100644 --- a/src/db.rs +++ b/src/db.rs @@ -268,7 +268,7 @@ where /// /// Returns a [`AppResult`] if an error occurs during generate model entity. pub async fn entities(ctx: &AppContext) -> AppResult { - doctor::check_seaorm_cli().to_result()?; + doctor::check_seaorm_cli()?.to_result()?; doctor::check_db(&ctx.config.database).await.to_result()?; let out = cmd!( diff --git a/src/doctor.rs b/src/doctor.rs index cb5e44fe4..78019b332 100644 --- a/src/doctor.rs +++ b/src/doctor.rs @@ -1,5 +1,8 @@ use std::{collections::BTreeMap, process::Command}; +use regex::Regex; +use semver::Version; + use crate::{ bgworker, config::{self, Config, Database}, @@ -88,9 +91,11 @@ impl std::fmt::Display for Check { } /// Runs checks for all configured resources. -pub async fn run_all(config: &Config) -> BTreeMap { +/// # Errors +/// Error when one of the checks fail +pub async fn run_all(config: &Config) -> Result> { let mut checks = BTreeMap::from([ - (Resource::SeaOrmCLI, check_seaorm_cli()), + (Resource::SeaOrmCLI, check_seaorm_cli()?), (Resource::Database, check_db(&config.database).await), ]); @@ -98,7 +103,7 @@ pub async fn run_all(config: &Config) -> BTreeMap { checks.insert(Resource::Redis, check_queue(config).await); } - checks + Ok(checks) } /// Checks the database connection. @@ -155,19 +160,54 @@ pub async fn check_queue(config: &Config) -> Check { } } +const MIN_SEAORMCLI_VER: &str = "1.1.0"; /// Checks the presence and version of `SeaORM` CLI. -#[must_use] -pub fn check_seaorm_cli() -> Check { +/// # Panics +/// On illegal regex +/// # Errors +/// Fails when cannot check version +pub fn check_seaorm_cli() -> Result { match Command::new("sea-orm-cli").arg("--version").output() { - Ok(_) => Check { - status: CheckStatus::Ok, - message: SEAORM_INSTALLED.to_string(), - description: None, - }, - Err(_) => Check { + Ok(out) => { + let input = String::from_utf8_lossy(&out.stdout); + // Extract the version from the input string + let re = Regex::new(r"(\d+\.\d+\.\d+)").unwrap(); + + let version_str = re + .captures(&input) + .and_then(|caps| caps.get(0)) + .map(|m| m.as_str()) + .ok_or("SeaORM CLI version not found") + .map_err(Box::from)?; + + // Parse the extracted version using semver + let version = Version::parse(version_str).map_err(Box::from)?; + + // Parse the minimum version for comparison + let min_version = Version::parse(MIN_SEAORMCLI_VER).map_err(Box::from)?; + + // Compare the extracted version with the minimum version + if version >= min_version { + Ok(Check { + status: CheckStatus::Ok, + message: SEAORM_INSTALLED.to_string(), + description: None, + }) + } else { + Ok(Check { + status: CheckStatus::NotOk, + message: format!( + "SeaORM CLI minimal version is `{min_version}` (you have `{version}`). \ + Run `cargo install sea-orm-cli` to update." + ), + description: Some(SEAORM_NOT_FIX.to_string()), + }) + } + } + Err(_) => Ok(Check { status: CheckStatus::NotOk, message: SEAORM_NOT_INSTALLED.to_string(), description: Some(SEAORM_NOT_FIX.to_string()), - }, + }), } }