From f80cc720a9393ca77f9e417ef542e38161068bde Mon Sep 17 00:00:00 2001 From: LeNei Date: Sun, 12 Jan 2025 14:42:58 +0100 Subject: [PATCH 1/6] fix: propagate build error and check if js files exist --- crates/tuono/src/app.rs | 16 +++++++++++++++- crates/tuono/src/watch.rs | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/tuono/src/app.rs b/crates/tuono/src/app.rs index 1f1bef0b..be569ece 100644 --- a/crates/tuono/src/app.rs +++ b/crates/tuono/src/app.rs @@ -6,6 +6,7 @@ use std::collections::{hash_map::Entry, HashMap}; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; +use std::path::Path; use std::path::PathBuf; use std::process::Child; use std::process::Command; @@ -138,9 +139,18 @@ impl App { } pub fn build_react_prod(&self) { - Command::new(BUILD_JS_SCRIPT) + if !Path::new(BUILD_JS_SCRIPT).exists() { + eprintln!("Failed to find the build script. Please run `npm install`"); + std::process::exit(1); + } + let output = Command::new(BUILD_JS_SCRIPT) .output() .expect("Failed to build the react source"); + if !output.status.success() { + eprintln!("Failed to build the react source"); + eprintln!("Error: {}", String::from_utf8_lossy(&output.stderr)); + std::process::exit(1); + } } pub fn run_rust_server(&self) -> Child { @@ -154,6 +164,10 @@ impl App { } pub fn build_tuono_config(&self) -> Result { + if !Path::new(BUILD_TUONO_CONFIG).exists() { + eprintln!("Failed to find the build script. Please run `npm install`"); + std::process::exit(1); + } Command::new(BUILD_TUONO_CONFIG) .stdin(Stdio::piped()) .stdout(Stdio::piped()) diff --git a/crates/tuono/src/watch.rs b/crates/tuono/src/watch.rs index fc81e834..e2fbf489 100644 --- a/crates/tuono/src/watch.rs +++ b/crates/tuono/src/watch.rs @@ -1,3 +1,4 @@ +use std::path::Path; use std::sync::Arc; use watchexec_supervisor::command::{Command, Program}; @@ -20,6 +21,10 @@ const DEV_WATCH_BIN_SRC: &str = "node_modules/.bin/tuono-dev-watch"; const DEV_SSR_BIN_SRC: &str = "node_modules/.bin/tuono-dev-ssr"; fn watch_react_src() -> Job { + if !Path::new(DEV_SSR_BIN_SRC).exists() { + eprintln!("Failed to find script to run dev watch. Please run `npm install`"); + std::process::exit(1); + } start_job(Arc::new(Command { program: Program::Exec { prog: DEV_WATCH_BIN_SRC.into(), @@ -42,6 +47,10 @@ fn build_rust_src() -> Job { } fn build_react_ssr_src() -> Job { + if !Path::new(DEV_SSR_BIN_SRC).exists() { + eprintln!("Failed to find script to run dev ssr. Please run `npm install`"); + std::process::exit(1); + } start_job(Arc::new(Command { program: Program::Exec { prog: DEV_SSR_BIN_SRC.into(), From fad64ec2b4bd627adf283a62e75cc89885b49225 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sat, 18 Jan 2025 19:16:39 +0100 Subject: [PATCH 2/6] Add test for missing build scripts --- crates/tuono/tests/{cli_tests.rs => cli_build.rs} | 13 +++++++++++++ 1 file changed, 13 insertions(+) rename crates/tuono/tests/{cli_tests.rs => cli_build.rs} (93%) diff --git a/crates/tuono/tests/cli_tests.rs b/crates/tuono/tests/cli_build.rs similarity index 93% rename from crates/tuono/tests/cli_tests.rs rename to crates/tuono/tests/cli_build.rs index 5bc194b1..ad479dfe 100644 --- a/crates/tuono/tests/cli_tests.rs +++ b/crates/tuono/tests/cli_build.rs @@ -140,3 +140,16 @@ fn it_successfully_create_catch_all_routes() { assert!(temp_main_rs_content .contains(r#".route("/__tuono/data/*all_routes", get(dyn_catch_all_all_routes::tuono__internal__api))"#)); } + +#[test] +#[serial] +fn it_fails_without_installed_node_modules() { + TempTuonoProject::new(); + + let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); + test_tuono_build + .arg("build") + .assert() + .failure() + .stderr("Failed to find the build script. Please run `npm install`\n"); +} From 40fcece1cc28579e2daed07fcdc053510c7b34b9 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sat, 18 Jan 2025 20:03:51 +0100 Subject: [PATCH 3/6] Add test for file exists on build --- crates/tuono/Cargo.toml | 10 ++++------ crates/tuono/tests/cli_build.rs | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/crates/tuono/Cargo.toml b/crates/tuono/Cargo.toml index bf71ef21..a17e429e 100644 --- a/crates/tuono/Cargo.toml +++ b/crates/tuono/Cargo.toml @@ -5,15 +5,12 @@ edition = "2021" authors = ["V. Ageno "] description = "Superfast React fullstack framework" homepage = "https://tuono.dev" -keywords = [ "react", "typescript", "fullstack", "web", "ssr"] +keywords = ["react", "typescript", "fullstack", "web", "ssr"] repository = "https://github.com/tuono-labs/tuono" readme = "../../README.md" license-file = "../../LICENSE.md" categories = ["web-programming"] -include = [ - "src/*.rs", - "Cargo.toml" -] +include = ["src/*.rs", "Cargo.toml"] [lib] name = "tuono" @@ -29,7 +26,7 @@ serde = { version = "1.0.202", features = ["derive"] } watchexec-supervisor = "3.0.0" glob = "0.3.1" regex = "1.10.4" -reqwest = {version = "0.12.4", features =["blocking", "json"]} +reqwest = { version = "0.12.4", features = ["blocking", "json"] } serde_json = "1.0" fs_extra = "1.3.0" http = "1.1.0" @@ -38,3 +35,4 @@ http = "1.1.0" tempfile = "3.14.0" assert_cmd = "2.0.16" serial_test = "0.10.0" +predicates = "3.1.3" diff --git a/crates/tuono/tests/cli_build.rs b/crates/tuono/tests/cli_build.rs index ad479dfe..ee7e0dce 100644 --- a/crates/tuono/tests/cli_build.rs +++ b/crates/tuono/tests/cli_build.rs @@ -1,5 +1,6 @@ mod utils; use assert_cmd::Command; +use predicates::prelude::*; use serial_test::serial; use std::fs; use utils::TempTuonoProject; @@ -153,3 +154,18 @@ fn it_fails_without_installed_node_modules() { .failure() .stderr("Failed to find the build script. Please run `npm install`\n"); } + +#[test] +#[serial] +fn it_passes_with_node_modules_present() { + let temp_tuono_project = TempTuonoProject::new(); + + let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); + + temp_tuono_project.add_route("./node_modules/.bin/tuono-build-config"); + test_tuono_build + .arg("build") + .assert() + .failure() + .stderr(predicate::str::contains("Permission denied")); +} From 65eb1f13150593495c3d015d0127e8136ade4c59 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sat, 18 Jan 2025 21:18:22 +0100 Subject: [PATCH 4/6] Rename test util add_route to add_file and update test to check script existance --- crates/tuono/tests/cli_build.rs | 18 ++++++++++-------- crates/tuono/tests/utils.rs | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/tuono/tests/cli_build.rs b/crates/tuono/tests/cli_build.rs index ee7e0dce..88b83408 100644 --- a/crates/tuono/tests/cli_build.rs +++ b/crates/tuono/tests/cli_build.rs @@ -1,8 +1,8 @@ mod utils; use assert_cmd::Command; -use predicates::prelude::*; use serial_test::serial; use std::fs; +use std::os::unix::fs::PermissionsExt; use utils::TempTuonoProject; const POST_API_FILE: &str = r"#[tuono_lib::api(POST)]"; @@ -13,7 +13,7 @@ const GET_API_FILE: &str = r"#[tuono_lib::api(GET)]"; fn it_successfully_create_the_index_route() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_route("./src/routes/index.rs"); + temp_tuono_project.add_file("./src/routes/index.rs"); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); test_tuono_build @@ -101,7 +101,7 @@ fn it_successfully_create_multiple_api_for_the_same_file() { fn it_successfully_create_catch_all_routes() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_route("./src/routes/[...all_routes].rs"); + temp_tuono_project.add_file("./src/routes/[...all_routes].rs"); temp_tuono_project.add_api( "./src/routes/api/[...all_apis].rs", @@ -144,7 +144,7 @@ fn it_successfully_create_catch_all_routes() { #[test] #[serial] -fn it_fails_without_installed_node_modules() { +fn it_fails_without_installed_build_config_script() { TempTuonoProject::new(); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); @@ -157,15 +157,17 @@ fn it_fails_without_installed_node_modules() { #[test] #[serial] -fn it_passes_with_node_modules_present() { +fn it_fails_without_installed_build_script() { let temp_tuono_project = TempTuonoProject::new(); + let file = temp_tuono_project.add_file("./node_modules/.bin/tuono-build-config"); + let mut perms = file.metadata().unwrap().permissions(); + perms.set_mode(0o755); + let _ = file.set_permissions(perms); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); - - temp_tuono_project.add_route("./node_modules/.bin/tuono-build-config"); test_tuono_build .arg("build") .assert() .failure() - .stderr(predicate::str::contains("Permission denied")); + .stderr("Failed to find the build script. Please run `npm install`\n"); } diff --git a/crates/tuono/tests/utils.rs b/crates/tuono/tests/utils.rs index f46ceb52..7d10e77d 100644 --- a/crates/tuono/tests/utils.rs +++ b/crates/tuono/tests/utils.rs @@ -28,14 +28,14 @@ impl TempTuonoProject { self.temp_dir.path() } - pub fn add_route<'a>(&self, path: &'a str) { + pub fn add_file<'a>(&self, path: &'a str) -> File { let path = PathBuf::from(path); create_all( path.parent().expect("Route path does not have any parent"), false, ) .expect("Failed to create parent route directory"); - File::create(path).expect("Failed to create the route file"); + File::create(path).expect("Failed to create the route file") } pub fn add_api<'a>(&self, path: &'a str, content: &'a str) { From ebd81e6e9eb5833fdc02b1d53fae42ca70001180 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sat, 18 Jan 2025 21:18:35 +0100 Subject: [PATCH 5/6] Remove unused dependency --- crates/tuono/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/tuono/Cargo.toml b/crates/tuono/Cargo.toml index a17e429e..d433a94e 100644 --- a/crates/tuono/Cargo.toml +++ b/crates/tuono/Cargo.toml @@ -35,4 +35,3 @@ http = "1.1.0" tempfile = "3.14.0" assert_cmd = "2.0.16" serial_test = "0.10.0" -predicates = "3.1.3" From a8d28b50c15e585429bd8d205cc44255797deda1 Mon Sep 17 00:00:00 2001 From: LeNei Date: Sun, 19 Jan 2025 08:04:34 +0100 Subject: [PATCH 6/6] Fix test pipeline --- crates/tuono/tests/cli_build.rs | 18 ++++++++++-------- crates/tuono/tests/utils.rs | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/crates/tuono/tests/cli_build.rs b/crates/tuono/tests/cli_build.rs index 88b83408..54b4469b 100644 --- a/crates/tuono/tests/cli_build.rs +++ b/crates/tuono/tests/cli_build.rs @@ -2,7 +2,6 @@ mod utils; use assert_cmd::Command; use serial_test::serial; use std::fs; -use std::os::unix::fs::PermissionsExt; use utils::TempTuonoProject; const POST_API_FILE: &str = r"#[tuono_lib::api(POST)]"; @@ -39,7 +38,7 @@ fn it_successfully_create_the_index_route() { fn it_successfully_create_an_api_route() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_api("./src/routes/api/health_check.rs", POST_API_FILE); + temp_tuono_project.add_file_with_content("./src/routes/api/health_check.rs", POST_API_FILE); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); test_tuono_build @@ -68,7 +67,7 @@ fn it_successfully_create_an_api_route() { fn it_successfully_create_multiple_api_for_the_same_file() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_api( + temp_tuono_project.add_file_with_content( "./src/routes/api/health_check.rs", &format!("{POST_API_FILE}{GET_API_FILE}"), ); @@ -103,7 +102,7 @@ fn it_successfully_create_catch_all_routes() { temp_tuono_project.add_file("./src/routes/[...all_routes].rs"); - temp_tuono_project.add_api( + temp_tuono_project.add_file_with_content( "./src/routes/api/[...all_apis].rs", &format!("{POST_API_FILE}"), ); @@ -160,10 +159,13 @@ fn it_fails_without_installed_build_config_script() { fn it_fails_without_installed_build_script() { let temp_tuono_project = TempTuonoProject::new(); - let file = temp_tuono_project.add_file("./node_modules/.bin/tuono-build-config"); - let mut perms = file.metadata().unwrap().permissions(); - perms.set_mode(0o755); - let _ = file.set_permissions(perms); + temp_tuono_project + .add_file_with_content("./node_modules/.bin/tuono-build-config", "#!/bin/bash"); + Command::new("chmod") + .arg("+x") + .arg("./node_modules/.bin/tuono-build-config") + .assert() + .success(); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); test_tuono_build .arg("build") diff --git a/crates/tuono/tests/utils.rs b/crates/tuono/tests/utils.rs index 7d10e77d..0396669e 100644 --- a/crates/tuono/tests/utils.rs +++ b/crates/tuono/tests/utils.rs @@ -38,7 +38,7 @@ impl TempTuonoProject { File::create(path).expect("Failed to create the route file") } - pub fn add_api<'a>(&self, path: &'a str, content: &'a str) { + pub fn add_file_with_content<'a>(&self, path: &'a str, content: &'a str) { let path = PathBuf::from(path); create_all( path.parent().expect("Route path does not have any parent"),