diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0bcf0e026..9c0dfad2d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -73,7 +73,7 @@ jobs: uses: ./.github/actions/free-disk-space - uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - uses: dtolnay/rust-toolchain@1.86.0 with: @@ -94,7 +94,7 @@ jobs: uses: ./.github/actions/free-disk-space - uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - uses: dtolnay/rust-toolchain@1.86.0 with: @@ -127,7 +127,7 @@ jobs: - uses: actions/checkout@v4 - uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - name: Install Rust ${{ env.rust_nightly }} uses: dtolnay/rust-toolchain@nightly @@ -150,7 +150,7 @@ jobs: - uses: actions/checkout@v4 - uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - uses: dtolnay/rust-toolchain@1.86.0 - uses: Swatinem/rust-cache@v2 @@ -166,7 +166,7 @@ jobs: - uses: actions/checkout@v4 - uses: awalsh128/cache-apt-pkgs-action@latest with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - uses: dtolnay/rust-toolchain@1.86.0 with: @@ -309,8 +309,8 @@ jobs: - uses: awalsh128/cache-apt-pkgs-action@latest if: ${{ matrix.platform.os == 'ubuntu-24.04' || matrix.platform.os == 'ubuntu-24.04-arm' }} with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev - version: 1.0 + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev + version: ${{ matrix.platform.target }}-${{ matrix.platform.os }} # disambiguate since we're in a matrix and this caching action doesn't factor in these variables - name: Install cross if: ${{ matrix.platform.cross == true }} diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index e077c383e..a161169b5 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -40,7 +40,7 @@ jobs: steps: - uses: actions/checkout@v4 - run: sudo apt-get update - - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev - uses: dtolnay/rust-toolchain@nightly with: toolchain: nightly-2024-02-01 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b14512b7e..f5197aaa0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -80,7 +80,7 @@ jobs: - uses: awalsh128/cache-apt-pkgs-action@latest if: ${{ matrix.platform.os == 'ubuntu-24.04' || matrix.platform.os == 'ubuntu-24.04-arm' }} with: - packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + packages: libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev version: 1.0 - name: Install stable @@ -127,7 +127,7 @@ jobs: # - uses: actions/checkout@v4 # ref: ${{ github.event.inputs.channel }} # - run: sudo apt-get update - # - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev + # - run: sudo apt install libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev libxdo-dev libglib2.0-dev # - uses: dtolnay/rust-toolchain@nightly # with: # toolchain: nightly-2024-02-01 diff --git a/packages/cli/src/cli/run.rs b/packages/cli/src/cli/run.rs index b31bb8b18..6230a155e 100644 --- a/packages/cli/src/cli/run.rs +++ b/packages/cli/src/cli/run.rs @@ -1,13 +1,16 @@ use super::*; use crate::{ serve::{AppServer, ServeUpdate, WebServer}, - BuilderUpdate, Platform, Result, + BuilderUpdate, Error, Platform, Result, }; use dioxus_dx_wire_format::BuildStage; /// Run the project with the given arguments /// /// This is a shorthand for `dx serve` with interactive mode and hot-reload disabled. +/// +/// Unlike `dx serve`, errors during build and run will cascade out as an error, rather than being +/// handled by the TUI, making it more suitable for scripting, automation, or CI/CD pipelines. #[derive(Clone, Debug, Parser)] pub(crate) struct RunArgs { /// Information about the target to build @@ -36,15 +39,15 @@ impl RunArgs { }; match msg { - // Wait for logs from the build engine - // These will cause us to update the screen - // We also can check the status of the builds here in case we have multiple ongoing builds ServeUpdate::BuilderUpdate { id, update } => { let platform = builder.get_build(id).unwrap().build.platform; // And then update the websocketed clients with the new build status in case they want it devserver.new_build_update(&update).await; + // Finally, we also want to update the builder with the new update + builder.new_build_update(&update, &devserver).await; + // And then open the app if it's ready match update { BuilderUpdate::BuildReady { bundle } => { @@ -72,7 +75,9 @@ impl RunArgs { total, krate, } => { - tracing::info!("[{platform}] Compiling {krate} ({current}/{total})",) + tracing::debug!( + "[{platform}] ({current}/{total}) Compiling {krate} ", + ) } BuildStage::RunningBindgen => { tracing::info!("[{platform}] Running WASM bindgen") @@ -82,7 +87,7 @@ impl RunArgs { tracing::info!("[{platform}] Optimizing WASM with `wasm-opt`") } BuildStage::Linking => tracing::info!("Linking app"), - BuildStage::Hotpatching => todo!(), + BuildStage::Hotpatching => {} BuildStage::CopyingAssets { current, total, @@ -96,10 +101,24 @@ impl RunArgs { tracing::info!("[{platform}] Running Gradle") } BuildStage::Success => {} - BuildStage::Failed => {} - BuildStage::Aborted => {} BuildStage::Restarting => {} BuildStage::CompressingAssets => {} + BuildStage::ExtractingAssets => {} + BuildStage::Prerendering => { + tracing::info!("[{platform}] Prerendering app") + } + BuildStage::Failed => { + tracing::error!("[{platform}] Build failed"); + return Err(Error::Cargo(format!( + "Build failed for platform: {platform}" + ))); + } + BuildStage::Aborted => { + tracing::error!("[{platform}] Build aborted"); + return Err(Error::Cargo(format!( + "Build aborted for platform: {platform}" + ))); + } _ => {} }, BuilderUpdate::CompilerMessage { message } => { @@ -107,6 +126,7 @@ impl RunArgs { } BuilderUpdate::BuildFailed { err } => { tracing::error!("Build failed: {}", err); + return Err(err); } BuilderUpdate::StdoutReceived { msg } => { tracing::info!("[{platform}] {msg}"); @@ -119,14 +139,28 @@ impl RunArgs { tracing::error!( "Application [{platform}] exited with error: {status}" ); + return Err(Error::Runtime(format!( + "Application [{platform}] exited with error: {status}" + ))); } break; } - BuilderUpdate::ProcessWaitFailed { .. } => {} + BuilderUpdate::ProcessWaitFailed { err } => { + return Err(err.into()); + } } } - _ => {} + ServeUpdate::Exit { .. } => break, + ServeUpdate::NewConnection { .. } => {} + ServeUpdate::WsMessage { .. } => {} + ServeUpdate::FilesChanged { .. } => {} + ServeUpdate::OpenApp => {} + ServeUpdate::RequestRebuild => {} + ServeUpdate::ToggleShouldRebuild => {} + ServeUpdate::OpenDebugger { .. } => {} + ServeUpdate::Redraw => {} + ServeUpdate::TracingLog { .. } => {} } } diff --git a/packages/cli/src/wasm_opt.rs b/packages/cli/src/wasm_opt.rs index 180b901e6..d3f4d45db 100644 --- a/packages/cli/src/wasm_opt.rs +++ b/packages/cli/src/wasm_opt.rs @@ -1,12 +1,10 @@ -use anyhow::{anyhow, Context}; -use flate2::read::GzDecoder; -use tar::Archive; -use tempfile::NamedTempFile; -use tokio::fs; - use crate::config::WasmOptLevel; use crate::{CliSettings, Result, WasmOptConfig, Workspace}; +use anyhow::{anyhow, Context}; +use flate2::read::GzDecoder; use std::path::{Path, PathBuf}; +use tar::Archive; +use tempfile::NamedTempFile; /// Write these wasm bytes with a particular set of optimizations pub async fn write_wasm(bytes: &[u8], output_path: &Path, cfg: &WasmOptConfig) -> Result<()> { @@ -16,7 +14,9 @@ pub async fn write_wasm(bytes: &[u8], output_path: &Path, cfg: &WasmOptConfig) - } pub async fn optimize(input_path: &Path, output_path: &Path, cfg: &WasmOptConfig) -> Result<()> { - let wasm_opt = WasmOpt::new(input_path, output_path, cfg).await?; + let wasm_opt = WasmOpt::new(input_path, output_path, cfg) + .await + .inspect_err(|err| tracing::error!("Failed to create wasm-opt instance: {}", err))?; wasm_opt.optimize().await?; Ok(()) @@ -127,6 +127,20 @@ impl WasmOpt { // Find the URL for the latest binaryen release that contains wasm-opt async fn find_latest_wasm_opt_download_url() -> anyhow::Result { + // Find the platform identifier based on the current OS and architecture + // hardcoded for now to get around github api rate limits + if cfg!(all(target_os = "windows", target_arch = "x86_64")) { + return Ok("https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-x86_64-windows.tar.gz".to_string()); + } else if cfg!(all(target_os = "linux", target_arch = "x86_64")) { + return Ok("https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-x86_64-linux.tar.gz".to_string()); + } else if cfg!(all(target_os = "linux", target_arch = "aarch64")) { + return Ok("https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-aarch64-linux.tar.gz".to_string()); + } else if cfg!(all(target_os = "macos", target_arch = "x86_64")) { + return Ok("https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-x86_64-macos.tar.gz".to_string()); + } else if cfg!(all(target_os = "macos", target_arch = "aarch64")) { + return Ok("https://github.com/WebAssembly/binaryen/releases/download/version_123/binaryen-version_123-arm64-macos.tar.gz".to_string()); + }; + let url = "https://api.github.com/repos/WebAssembly/binaryen/releases/latest"; let client = reqwest::Client::new(); let response = client @@ -136,6 +150,9 @@ async fn find_latest_wasm_opt_download_url() -> anyhow::Result { .await? .json::() .await?; + + tracing::trace!("Response from GitHub: {:#?}", response); + let assets = response .get("assets") .and_then(|assets| assets.as_array()) @@ -165,7 +182,7 @@ async fn find_latest_wasm_opt_download_url() -> anyhow::Result { asset .get("name") .and_then(|name| name.as_str()) - .is_some_and(|name| name.contains(platform)) + .is_some_and(|name| name.contains(platform) && !name.ends_with("sha256")) }) .ok_or_else(|| { anyhow::anyhow!( @@ -185,31 +202,30 @@ async fn find_latest_wasm_opt_download_url() -> anyhow::Result { /// Get the path to the wasm-opt binary, downloading it if necessary async fn get_binary_path() -> anyhow::Result { - let existing_path = which::which("wasm-opt"); + let install_dir = install_dir(); + let install_path = installed_bin_path(&install_dir); - match existing_path { - // If wasm-opt is already in the PATH, return its path - Ok(path) => Ok(path), - // If wasm-opt is not found in the path and we prefer no downloads, return an error - Err(_) if CliSettings::prefer_no_downloads() => Err(anyhow!("Missing wasm-opt")), - // Otherwise, try to install it - Err(_) => { - let install_dir = install_dir().await?; - let install_path = installed_bin_path(&install_dir); - if !install_path.exists() { - tracing::info!("Installing wasm-opt"); - install_github(&install_dir).await?; - tracing::info!("wasm-opt installed from Github"); - } - Ok(install_path) + if install_path.exists() { + return Ok(install_path); + } + + if CliSettings::prefer_no_downloads() { + if let Ok(existing) = which::which("wasm-opt") { + return Ok(existing); + } else { + return Err(anyhow!("Missing wasm-opt")); } } + + tracing::info!("Installing wasm-opt"); + install_github(&install_dir).await?; + tracing::info!("wasm-opt installed from Github"); + + Ok(install_path) } -async fn install_dir() -> anyhow::Result { - let bindgen_dir = Workspace::dioxus_home_dir().join("binaryen"); - fs::create_dir_all(&bindgen_dir).await?; - Ok(bindgen_dir) +fn install_dir() -> PathBuf { + Workspace::dioxus_home_dir().join("binaryen") } fn installed_bin_name() -> &'static str { @@ -221,14 +237,15 @@ fn installed_bin_name() -> &'static str { } fn installed_bin_path(install_dir: &Path) -> PathBuf { - let bin_name = installed_bin_name(); - install_dir.join("bin").join(bin_name) + install_dir.join("bin").join(installed_bin_name()) } /// Install wasm-opt from GitHub releases into the specified directory async fn install_github(install_dir: &Path) -> anyhow::Result<()> { tracing::trace!("Attempting to install wasm-opt from GitHub"); + std::fs::create_dir_all(install_dir)?; + let url = find_latest_wasm_opt_download_url() .await .context("Failed to find latest wasm-opt download URL")?; diff --git a/packages/playwright-tests/playwright.config.js b/packages/playwright-tests/playwright.config.js index 7ee56e941..188f1fab6 100644 --- a/packages/playwright-tests/playwright.config.js +++ b/packages/playwright-tests/playwright.config.js @@ -87,7 +87,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "web"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 9990', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 9990', port: 9990, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -96,7 +96,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "web-routing"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 2020', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 2020', port: 2020, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -105,7 +105,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "fullstack"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 3333', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 3333', port: 3333, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -114,7 +114,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "fullstack-mounted"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 7777', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 7777', port: 7777, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -123,7 +123,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "fullstack-routing"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 8888', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 8888', port: 8888, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -132,7 +132,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "suspense-carousel"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 4040', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 4040', port: 4040, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -141,7 +141,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "nested-suspense"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --platform web --addr "127.0.0.1" --port 5050', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --platform web --addr "127.0.0.1" --port 5050', port: 5050, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -150,7 +150,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "nested-suspense"), command: - 'cargo run --package dioxus-cli --release -- serve --bin nested-suspense-ssg --force-sequential --platform web --ssg --addr "127.0.0.1" --port 6060', + 'cargo run --package dioxus-cli --release -- run --verbose --bin nested-suspense-ssg --force-sequential --platform web --ssg --addr "127.0.0.1" --port 6060', port: 6060, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -160,7 +160,7 @@ module.exports = defineConfig({ cwd: path.join(process.cwd(), "cli-optimization"), // Remove the cache folder for the cli-optimization build to force a full cache reset command: - 'cargo run --package dioxus-cli --release -- serve --addr "127.0.0.1" --port 8989', + 'cargo run --package dioxus-cli --release -- run --verbose --addr "127.0.0.1" --port 8989', port: 8989, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -169,7 +169,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "wasm-split-harness"), command: - 'cargo run --package dioxus-cli --release -- serve --bin wasm-split-harness --platform web --addr "127.0.0.1" --port 8001 --wasm-split --profile wasm-split-release', + 'cargo run --package dioxus-cli --release -- run --verbose --bin wasm-split-harness --platform web --addr "127.0.0.1" --port 8001 --wasm-split --profile wasm-split-release', port: 8001, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -178,7 +178,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "default-features-disabled"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --addr "127.0.0.1" --port 8002', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --addr "127.0.0.1" --port 8002', port: 8002, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI, @@ -187,7 +187,7 @@ module.exports = defineConfig({ { cwd: path.join(process.cwd(), "barebones-template"), command: - 'cargo run --package dioxus-cli --release -- serve --force-sequential --addr "127.0.0.1" --port 8123', + 'cargo run --package dioxus-cli --release -- run --verbose --force-sequential --addr "127.0.0.1" --port 8123', port: 8123, timeout: 50 * 60 * 1000, reuseExistingServer: !process.env.CI,