From db28a737374555f567dbbf34f43c997f857348d4 Mon Sep 17 00:00:00 2001 From: Alex Krantz Date: Wed, 26 Oct 2022 23:02:42 -0700 Subject: [PATCH] feat(deployer): add support for building wasm projects --- cargo-shuttle/src/lib.rs | 7 ++- deployer/src/deployment/queue.rs | 12 ++-- service/src/loader.rs | 32 ++++++++-- service/tests/integration/build_crate.rs | 74 +++++++++++++++++------- 4 files changed, 94 insertions(+), 31 deletions(-) diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index 102b2c3de..415cf0407 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -24,7 +24,7 @@ use crossterm::style::Stylize; use factory::LocalFactory; use futures::StreamExt; use shuttle_common::models::secret; -use shuttle_service::loader::{build_crate, Loader}; +use shuttle_service::loader::{build_crate, Loader, Runtime}; use shuttle_service::Logger; use tokio::sync::mpsc; use tracing::trace; @@ -277,7 +277,10 @@ impl Shuttle { "Building".bold().green(), working_directory.display() ); - let so_path = build_crate(id, working_directory, false, tx).await?; + let so_path = match build_crate(id, working_directory, false, false, tx).await? { + Runtime::Legacy(path) => path, + Runtime::Next(_) => todo!(), + }; trace!("loading secrets"); let secrets_path = working_directory.join("Secrets.toml"); diff --git a/deployer/src/deployment/queue.rs b/deployer/src/deployment/queue.rs index 948597d8c..14f4fe6bd 100644 --- a/deployer/src/deployment/queue.rs +++ b/deployer/src/deployment/queue.rs @@ -7,7 +7,7 @@ use cargo_metadata::Message; use chrono::Utc; use crossbeam_channel::Sender; use serde_json::json; -use shuttle_service::loader::{build_crate, get_config}; +use shuttle_service::loader::{build_crate, get_config, Runtime}; use tracing::{debug, error, info, instrument, trace}; use uuid::Uuid; @@ -158,7 +158,7 @@ impl Queued { }); let project_path = project_path.canonicalize()?; - let so_path = build_deployment(self.id, &project_path, tx.clone()).await?; + let so_path = build_deployment(self.id, &project_path, false, tx.clone()).await?; if self.will_run_tests { info!( @@ -265,13 +265,17 @@ fn extract_tar_gz_data(data: impl Read, dest: impl AsRef) -> Result<()> { async fn build_deployment( deployment_id: Uuid, project_path: &Path, + wasm: bool, tx: crossbeam_channel::Sender, ) -> Result { - let so_path = build_crate(deployment_id, project_path, true, tx) + let runtime_path = build_crate(deployment_id, project_path, true, wasm, tx) .await .map_err(|e| Error::Build(e.into()))?; - Ok(so_path) + match runtime_path { + Runtime::Legacy(so_path) => Ok(so_path), + Runtime::Next(_) => todo!(), + } } #[instrument(skip(project_path, tx))] diff --git a/service/src/loader.rs b/service/src/loader.rs index f415805f3..109b714c7 100644 --- a/service/src/loader.rs +++ b/service/src/loader.rs @@ -5,7 +5,7 @@ use std::panic::AssertUnwindSafe; use std::path::{Path, PathBuf}; use anyhow::{anyhow, Context}; -use cargo::core::compiler::{CompileMode, MessageFormat}; +use cargo::core::compiler::{CompileKind, CompileMode, CompileTarget, MessageFormat}; use cargo::core::{Manifest, PackageId, Shell, Summary, Verbosity, Workspace}; use cargo::ops::{compile, CompileOptions}; use cargo::util::interning::InternedString; @@ -100,13 +100,20 @@ impl Loader { } } +/// How to run/build the project +pub enum Runtime { + Next(PathBuf), + Legacy(PathBuf), +} + /// Given a project directory path, builds the crate pub async fn build_crate( deployment_id: Uuid, project_path: &Path, release_mode: bool, + wasm: bool, tx: Sender, -) -> anyhow::Result { +) -> anyhow::Result { let (read, write) = pipe::pipe(); let project_path = project_path.to_owned(); @@ -125,10 +132,15 @@ pub async fn build_crate( check_version(summary)?; check_no_panic(&ws)?; - let opts = get_compile_options(&config, release_mode)?; + let opts = get_compile_options(&config, release_mode, wasm)?; let compilation = compile(&ws, &opts); - Ok(compilation?.cdylibs[0].path.clone()) + let path = compilation?.cdylibs[0].path.clone(); + Ok(if wasm { + Runtime::Next(path) + } else { + Runtime::Legacy(path) + }) }); // This needs to be on a separate thread, else deployer will block (reason currently unknown :D) @@ -169,7 +181,11 @@ pub fn get_config(writer: PipeWriter) -> anyhow::Result { } /// Get options to compile in build mode -fn get_compile_options(config: &Config, release_mode: bool) -> anyhow::Result { +fn get_compile_options( + config: &Config, + release_mode: bool, + wasm: bool, +) -> anyhow::Result { let mut opts = CompileOptions::new(config, CompileMode::Build)?; opts.build_config.message_format = MessageFormat::Json { render_diagnostics: false, @@ -183,6 +199,12 @@ fn get_compile_options(config: &Config, release_mode: bool) -> anyhow::Result path, + _ => unreachable!(), + }; assert!( so_path @@ -27,20 +37,32 @@ async fn not_shuttle() { async fn not_lib() { let (tx, _) = crossbeam_channel::unbounded(); let project_path = format!("{}/tests/resources/not-lib", env!("CARGO_MANIFEST_DIR")); - build_crate(Default::default(), Path::new(&project_path), false, tx) - .await - .unwrap(); + build_crate( + Default::default(), + Path::new(&project_path), + false, + false, + tx, + ) + .await + .unwrap(); } #[tokio::test(flavor = "multi_thread")] async fn not_cdylib() { let (tx, _) = crossbeam_channel::unbounded(); let project_path = format!("{}/tests/resources/not-cdylib", env!("CARGO_MANIFEST_DIR")); - assert!( - build_crate(Default::default(), Path::new(&project_path), false, tx) - .await - .is_ok() - ); + assert!(matches!( + build_crate( + Default::default(), + Path::new(&project_path), + false, + false, + tx + ) + .await, + Ok(Runtime::Legacy(_)) + )); assert!(PathBuf::from(project_path) .join("target/debug/libnot_cdylib.so") .exists()); @@ -50,11 +72,17 @@ async fn not_cdylib() { async fn is_cdylib() { let (tx, _) = crossbeam_channel::unbounded(); let project_path = format!("{}/tests/resources/is-cdylib", env!("CARGO_MANIFEST_DIR")); - assert!( - build_crate(Default::default(), Path::new(&project_path), false, tx) - .await - .is_ok() - ); + assert!(matches!( + build_crate( + Default::default(), + Path::new(&project_path), + false, + false, + tx + ) + .await, + Ok(Runtime::Legacy(_)) + )); assert!(PathBuf::from(project_path) .join("target/debug/libis_cdylib.so") .exists()); @@ -68,7 +96,13 @@ async fn not_found() { "{}/tests/resources/non-existing", env!("CARGO_MANIFEST_DIR") ); - build_crate(Default::default(), Path::new(&project_path), false, tx) - .await - .unwrap(); + build_crate( + Default::default(), + Path::new(&project_path), + false, + false, + tx, + ) + .await + .unwrap(); }