Kaynağa Gözat

feat(cli): add `beforeBundleCommand`, closes #4879 (#4893)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Amr Bashir 3 yıl önce
ebeveyn
işleme
57ab9847eb

+ 7 - 0
.changes/before-bundle-command.md

@@ -0,0 +1,7 @@
+---
+"tauri-utils": minor
+"cli.rs": minor
+"cli.js": minor
+---
+
+Allow adding `build > beforeBundleCommand` in tauri.conf.json to run a shell command before the bundling phase.

+ 13 - 3
core/tauri-utils/src/config.rs

@@ -2396,11 +2396,11 @@ pub enum BeforeDevCommand {
   },
 }
 
-/// Describes the shell command to run before `tauri build`.
+/// Describes a shell command to be executed when a CLI hook is triggered.
 #[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
 #[cfg_attr(feature = "schema", derive(JsonSchema))]
 #[serde(rename_all = "camelCase", untagged)]
-pub enum BeforeBuildCommand {
+pub enum HookCommand {
   /// Run the given script with the default options.
   Script(String),
   /// Run the given script with custom options.
@@ -2451,7 +2451,12 @@ pub struct BuildConfig {
   ///
   /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
   #[serde(alias = "before-build-command")]
-  pub before_build_command: Option<BeforeBuildCommand>,
+  pub before_build_command: Option<HookCommand>,
+  /// A shell command to run before the bundling phase in `tauri build` kicks in.
+  ///
+  /// The TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.
+  #[serde(alias = "before-build-command")]
+  pub before_bundle_command: Option<HookCommand>,
   /// Features passed to `cargo` commands.
   pub features: Option<Vec<String>>,
   /// Whether we should inject the Tauri API on `window.__TAURI__` or not.
@@ -2467,6 +2472,7 @@ impl Default for BuildConfig {
       dist_dir: default_dist_dir(),
       before_dev_command: None,
       before_build_command: None,
+      before_bundle_command: None,
       features: None,
       with_global_tauri: false,
     }
@@ -2679,6 +2685,7 @@ fn default_build() -> BuildConfig {
     dist_dir: default_dist_dir(),
     before_dev_command: None,
     before_build_command: None,
+    before_bundle_command: None,
     features: None,
     with_global_tauri: false,
   }
@@ -3146,6 +3153,7 @@ mod build {
       let runner = quote!(None);
       let before_dev_command = quote!(None);
       let before_build_command = quote!(None);
+      let before_bundle_command = quote!(None);
       let features = quote!(None);
 
       literal_struct!(
@@ -3157,6 +3165,7 @@ mod build {
         with_global_tauri,
         before_dev_command,
         before_build_command,
+        before_bundle_command,
         features
       );
     }
@@ -3557,6 +3566,7 @@ mod test {
       dist_dir: AppUrl::Url(WindowUrl::App("../dist".into())),
       before_dev_command: None,
       before_build_command: None,
+      before_bundle_command: None,
       features: None,
       with_global_tauri: false,
     };

+ 14 - 3
tooling/cli/schema.json

@@ -2462,7 +2462,18 @@
           "description": "A shell command to run before `tauri build` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.",
           "anyOf": [
             {
-              "$ref": "#/definitions/BeforeBuildCommand"
+              "$ref": "#/definitions/HookCommand"
+            },
+            {
+              "type": "null"
+            }
+          ]
+        },
+        "beforeBundleCommand": {
+          "description": "A shell command to run before the bundling phase in `tauri build` kicks in.\n\nThe TAURI_PLATFORM, TAURI_ARCH, TAURI_FAMILY, TAURI_PLATFORM_VERSION, TAURI_PLATFORM_TYPE and TAURI_DEBUG environment variables are set if you perform conditional compilation.",
+          "anyOf": [
+            {
+              "$ref": "#/definitions/HookCommand"
             },
             {
               "type": "null"
@@ -2541,8 +2552,8 @@
         }
       ]
     },
-    "BeforeBuildCommand": {
-      "description": "Describes the shell command to run before `tauri build`.",
+    "HookCommand": {
+      "description": "Describes a shell command to be executed when a CLI hook is triggered.",
       "anyOf": [
         {
           "description": "Run the given script with the default options.",

+ 49 - 37
tooling/cli/src/build.rs

@@ -6,9 +6,7 @@ use crate::{
   helpers::{
     app_paths::{app_dir, tauri_dir},
     command_env,
-    config::{
-      get as get_config, AppUrl, BeforeBuildCommand, WindowUrl, MERGE_CONFIG_EXTENSION_NAME,
-    },
+    config::{get as get_config, AppUrl, HookCommand, WindowUrl, MERGE_CONFIG_EXTENSION_NAME},
     updater_signature::{read_key_from_file, secret_key as updater_secret_key, sign_file},
   },
   interface::{AppInterface, AppSettings, Interface},
@@ -115,40 +113,7 @@ pub fn command(mut options: Options) -> Result<()> {
   }
 
   if let Some(before_build) = config_.build.before_build_command.clone() {
-    let (script, script_cwd) = match before_build {
-      BeforeBuildCommand::Script(s) if s.is_empty() => (None, None),
-      BeforeBuildCommand::Script(s) => (Some(s), None),
-      BeforeBuildCommand::ScriptWithOptions { script, cwd } => (Some(script), cwd.map(Into::into)),
-    };
-    let cwd = script_cwd.unwrap_or_else(|| app_dir().clone());
-    if let Some(before_build) = script {
-      info!(action = "Running"; "beforeBuildCommand `{}`", before_build);
-      #[cfg(target_os = "windows")]
-      let status = Command::new("cmd")
-        .arg("/S")
-        .arg("/C")
-        .arg(&before_build)
-        .current_dir(cwd)
-        .envs(command_env(options.debug))
-        .piped()
-        .with_context(|| format!("failed to run `{}` with `cmd /C`", before_build))?;
-      #[cfg(not(target_os = "windows"))]
-      let status = Command::new("sh")
-        .arg("-c")
-        .arg(&before_build)
-        .current_dir(cwd)
-        .envs(command_env(options.debug))
-        .piped()
-        .with_context(|| format!("failed to run `{}` with `sh -c`", before_build))?;
-
-      if !status.success() {
-        bail!(
-          "beforeBuildCommand `{}` failed with exit code {}",
-          before_build,
-          status.code().unwrap_or_default()
-        );
-      }
-    }
+    run_hook("beforeBuildCommand", before_build, options.debug)?;
   }
 
   if let AppUrl::Url(WindowUrl::App(web_asset_path)) = &config_.build.dist_dir {
@@ -238,6 +203,13 @@ pub fn command(mut options: Options) -> Result<()> {
       }
     }
 
+    // if we have a package to bundle, let's run the `before_bundle_command`.
+    if package_types.as_ref().map_or(true, |p| !p.is_empty()) {
+      if let Some(before_bundle) = config_.build.before_bundle_command.clone() {
+        run_hook("beforeBundleCommand", before_bundle, options.debug)?;
+      }
+    }
+
     let settings = app_settings
       .get_bundler_settings(&options.into(), config_, out_dir, package_types)
       .with_context(|| "failed to build bundler settings")?;
@@ -337,6 +309,46 @@ pub fn command(mut options: Options) -> Result<()> {
   Ok(())
 }
 
+fn run_hook(name: &str, hook: HookCommand, debug: bool) -> Result<()> {
+  let (script, script_cwd) = match hook {
+    HookCommand::Script(s) if s.is_empty() => (None, None),
+    HookCommand::Script(s) => (Some(s), None),
+    HookCommand::ScriptWithOptions { script, cwd } => (Some(script), cwd.map(Into::into)),
+  };
+  let cwd = script_cwd.unwrap_or_else(|| app_dir().clone());
+  if let Some(script) = script {
+    info!(action = "Running"; "{} `{}`", name, script);
+    #[cfg(target_os = "windows")]
+    let status = Command::new("cmd")
+      .arg("/S")
+      .arg("/C")
+      .arg(&script)
+      .current_dir(cwd)
+      .envs(command_env(debug))
+      .piped()
+      .with_context(|| format!("failed to run `{}` with `cmd /C`", script))?;
+    #[cfg(not(target_os = "windows"))]
+    let status = Command::new("sh")
+      .arg("-c")
+      .arg(&script)
+      .current_dir(cwd)
+      .envs(command_env(debug))
+      .piped()
+      .with_context(|| format!("failed to run `{}` with `sh -c`", script))?;
+
+    if !status.success() {
+      bail!(
+        "{} `{}` failed with exit code {}",
+        name,
+        script,
+        status.code().unwrap_or_default()
+      );
+    }
+  }
+
+  Ok(())
+}
+
 fn print_signed_updater_archive(output_paths: &[PathBuf]) -> crate::Result<()> {
   let pluralised = if output_paths.len() == 1 {
     "updater archive"