Skip to content

Commit c8f55b6

Browse files
feat(bundler): add wix > version option (#11388)
* feat(bundler): add `wix > version` option closes #11253 * Update crates/tauri-bundler/src/bundle/settings.rs --------- Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
1 parent bd1b2a1 commit c8f55b6

File tree

7 files changed

+107
-7
lines changed

7 files changed

+107
-7
lines changed

.changes/bundler-wix-version.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-bundler": "patch:feat"
3+
---
4+
5+
Add `bundler > windows > wix > version` to manually specify a wix-compatible version.
6+

crates/tauri-bundler/src/bundle/settings.rs

+9
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,15 @@ impl Default for WixLanguage {
351351
/// Settings specific to the WiX implementation.
352352
#[derive(Clone, Debug, Default)]
353353
pub struct WixSettings {
354+
/// MSI installer version in the format `major.minor.patch.build` (build is optional).
355+
///
356+
/// Because a valid version is required for MSI installer, it will be derived from [`PackageSettings::version`] if this field is not set.
357+
///
358+
/// The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.
359+
/// The third and fourth fields have a maximum value of 65,535.
360+
///
361+
/// See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.
362+
pub version: Option<String>,
354363
/// A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,
355364
/// otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.
356365
///

crates/tauri-bundler/src/bundle/windows/msi/mod.rs

+68-7
Original file line numberDiff line numberDiff line change
@@ -282,19 +282,37 @@ fn clear_env_for_wix(cmd: &mut Command) {
282282
}
283283
}
284284

285-
// WiX requires versions to be numeric only in a `major.minor.patch.build` format
286-
pub fn convert_version(version_str: &str) -> anyhow::Result<String> {
287-
let version = semver::Version::parse(version_str).context("invalid app version")?;
288-
if version.major > 255 {
285+
fn validate_wix_version(version_str: &str) -> anyhow::Result<()> {
286+
let components = version_str
287+
.split('.')
288+
.flat_map(|c| c.parse::<u64>().ok())
289+
.collect::<Vec<_>>();
290+
291+
anyhow::ensure!(
292+
components.len() >= 3,
293+
"app wix version should be in the format major.minor.patch.build (build is optional)"
294+
);
295+
296+
if components[0] > 255 {
289297
bail!("app version major number cannot be greater than 255");
290298
}
291-
if version.minor > 255 {
299+
if components[1] > 255 {
292300
bail!("app version minor number cannot be greater than 255");
293301
}
294-
if version.patch > 65535 {
302+
if components[2] > 65535 {
295303
bail!("app version patch number cannot be greater than 65535");
296304
}
297305

306+
if components.len() == 4 && components[3] > 65535 {
307+
bail!("app version build number cannot be greater than 65535");
308+
}
309+
310+
Ok(())
311+
}
312+
313+
// WiX requires versions to be numeric only in a `major.minor.patch.build` format
314+
fn convert_version(version_str: &str) -> anyhow::Result<String> {
315+
let version = semver::Version::parse(version_str).context("invalid app version")?;
298316
if !version.build.is_empty() {
299317
let build = version.build.parse::<u64>();
300318
if build.map(|b| b <= 65535).unwrap_or_default() {
@@ -433,7 +451,18 @@ pub fn build_wix_app_installer(
433451
}
434452
};
435453

436-
let app_version = convert_version(settings.version_string())?;
454+
let app_version = if let Some(version) = settings
455+
.windows()
456+
.wix
457+
.as_ref()
458+
.and_then(|wix| wix.version.clone())
459+
{
460+
version
461+
} else {
462+
convert_version(settings.version_string())?
463+
};
464+
465+
validate_wix_version(&app_version)?;
437466

438467
// target only supports x64.
439468
log::info!("Target: {}", arch);
@@ -1056,3 +1085,35 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourceMap> {
10561085

10571086
Ok(resources)
10581087
}
1088+
1089+
#[cfg(test)]
1090+
mod tests {
1091+
use super::*;
1092+
1093+
#[test]
1094+
fn validates_wix_version() {
1095+
assert!(validate_wix_version("1.1.1").is_ok());
1096+
assert!(validate_wix_version("1.1.1.1").is_ok());
1097+
assert!(validate_wix_version("255.1.1.1").is_ok());
1098+
assert!(validate_wix_version("1.255.1.1").is_ok());
1099+
assert!(validate_wix_version("1.1.65535.1").is_ok());
1100+
assert!(validate_wix_version("1.1.1.65535").is_ok());
1101+
1102+
assert!(validate_wix_version("256.1.1.1").is_err());
1103+
assert!(validate_wix_version("1.256.1.1").is_err());
1104+
assert!(validate_wix_version("1.1.65536.1").is_err());
1105+
assert!(validate_wix_version("1.1.1.65536").is_err());
1106+
}
1107+
1108+
#[test]
1109+
fn converts_version_to_wix() {
1110+
assert_eq!(convert_version("1.1.2").unwrap(), "1.1.2");
1111+
assert_eq!(convert_version("1.1.2-4").unwrap(), "1.1.2.4");
1112+
assert_eq!(convert_version("1.1.2-65535").unwrap(), "1.1.2.65535");
1113+
assert_eq!(convert_version("1.1.2+2").unwrap(), "1.1.2.2");
1114+
1115+
assert!(convert_version("1.1.2-alpha").is_err());
1116+
assert!(convert_version("1.1.2-alpha.4").is_err());
1117+
assert!(convert_version("1.1.2+asd.3").is_err());
1118+
}
1119+
}

crates/tauri-cli/config.schema.json

+7
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,13 @@
21702170
"description": "Configuration for the MSI bundle using WiX.\n\n See more: <https://v2.tauri.app/reference/config/#wixconfig>",
21712171
"type": "object",
21722172
"properties": {
2173+
"version": {
2174+
"description": "MSI installer version in the format `major.minor.patch.build` (build is optional).\n\n Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.\n\n The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.\n The third and foruth fields have a maximum value of 65,535.\n\n See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.",
2175+
"type": [
2176+
"string",
2177+
"null"
2178+
]
2179+
},
21732180
"upgradeCode": {
21742181
"description": "A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,\n otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.\n\n By default, tauri generates this code by generating a Uuid v5 using the string `<productName>.exe.app.x64` in the DNS namespace.\n You can use Tauri's CLI to generate and print this code for you, run `tauri inspect wix-upgrade-code`.\n\n It is recommended that you set this value in your tauri config file to avoid accidental changes in your upgrade code\n whenever you want to change your product name.",
21752182
"type": [

crates/tauri-cli/src/helpers/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub type ConfigHandle = Arc<Mutex<Option<ConfigMetadata>>>;
6262

6363
pub fn wix_settings(config: WixConfig) -> tauri_bundler::WixSettings {
6464
tauri_bundler::WixSettings {
65+
version: config.version,
6566
upgrade_code: config.upgrade_code,
6667
language: tauri_bundler::WixLanguage(match config.language {
6768
WixLanguage::One(lang) => vec![(lang, Default::default())],

crates/tauri-schema-generator/schemas/config.schema.json

+7
Original file line numberDiff line numberDiff line change
@@ -2170,6 +2170,13 @@
21702170
"description": "Configuration for the MSI bundle using WiX.\n\n See more: <https://v2.tauri.app/reference/config/#wixconfig>",
21712171
"type": "object",
21722172
"properties": {
2173+
"version": {
2174+
"description": "MSI installer version in the format `major.minor.patch.build` (build is optional).\n\n Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.\n\n The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.\n The third and foruth fields have a maximum value of 65,535.\n\n See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.",
2175+
"type": [
2176+
"string",
2177+
"null"
2178+
]
2179+
},
21732180
"upgradeCode": {
21742181
"description": "A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,\n otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.\n\n By default, tauri generates this code by generating a Uuid v5 using the string `<productName>.exe.app.x64` in the DNS namespace.\n You can use Tauri's CLI to generate and print this code for you, run `tauri inspect wix-upgrade-code`.\n\n It is recommended that you set this value in your tauri config file to avoid accidental changes in your upgrade code\n whenever you want to change your product name.",
21752182
"type": [

crates/tauri-utils/src/config.rs

+9
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,15 @@ impl Default for WixLanguage {
658658
#[cfg_attr(feature = "schema", derive(JsonSchema))]
659659
#[serde(rename_all = "camelCase", deny_unknown_fields)]
660660
pub struct WixConfig {
661+
/// MSI installer version in the format `major.minor.patch.build` (build is optional).
662+
///
663+
/// Because a valid version is required for MSI installer, it will be derived from [`Config::version`] if this field is not set.
664+
///
665+
/// The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.
666+
/// The third and foruth fields have a maximum value of 65,535.
667+
///
668+
/// See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.
669+
pub version: Option<String>,
661670
/// A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,
662671
/// otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.
663672
///

0 commit comments

Comments
 (0)