mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
feat(android): add auto_increment_version_code option for Android builds (#14194)
* add new api (auto_increment_version_code) in android configuration * ensure increment is only ran once * skip on dev * update doc * change file --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
8
.changes/auto-increment-android-version-code.md
Normal file
8
.changes/auto-increment-android-version-code.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"tauri-cli": minor:feat
|
||||
"@tauri-apps/cli": minor:feat
|
||||
"tauri-build": minor:feat
|
||||
"tauri-utils": minor:feat
|
||||
---
|
||||
|
||||
Add `tauri.conf.json > bundle > android > autoIncrementVersionCode` config option to automatically increment the Android version code.
|
||||
@@ -499,7 +499,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
|
||||
println!("cargo:rustc-env=TAURI_ANDROID_PACKAGE_NAME_PREFIX={android_package_prefix}");
|
||||
|
||||
if let Some(project_dir) = env::var_os("TAURI_ANDROID_PROJECT_PATH").map(PathBuf::from) {
|
||||
mobile::generate_gradle_files(project_dir, &config)?;
|
||||
mobile::generate_gradle_files(project_dir)?;
|
||||
}
|
||||
|
||||
cfg_alias("dev", is_dev());
|
||||
|
||||
@@ -2,18 +2,14 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{fs::write, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use semver::Version;
|
||||
use tauri_utils::{config::Config, write_if_changed};
|
||||
use tauri_utils::write_if_changed;
|
||||
|
||||
use crate::is_dev;
|
||||
|
||||
pub fn generate_gradle_files(project_dir: PathBuf, config: &Config) -> Result<()> {
|
||||
pub fn generate_gradle_files(project_dir: PathBuf) -> Result<()> {
|
||||
let gradle_settings_path = project_dir.join("tauri.settings.gradle");
|
||||
let app_build_gradle_path = project_dir.join("app").join("tauri.build.gradle.kts");
|
||||
let app_tauri_properties_path = project_dir.join("app").join("tauri.properties");
|
||||
|
||||
let mut gradle_settings =
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n".to_string();
|
||||
@@ -21,7 +17,6 @@ pub fn generate_gradle_files(project_dir: PathBuf, config: &Config) -> Result<()
|
||||
val implementation by configurations
|
||||
dependencies {"
|
||||
.to_string();
|
||||
let mut app_tauri_properties = Vec::new();
|
||||
|
||||
for (env, value) in std::env::vars_os() {
|
||||
let env = env.to_string_lossy();
|
||||
@@ -54,32 +49,6 @@ dependencies {"
|
||||
|
||||
app_build_gradle.push_str("\n}");
|
||||
|
||||
if let Some(version) = config.version.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionName={version}"));
|
||||
if let Some(version_code) = config.bundle.android.version_code.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
} else if let Ok(version) = Version::parse(version) {
|
||||
let mut version_code = version.major * 1000000 + version.minor * 1000 + version.patch;
|
||||
|
||||
if is_dev() {
|
||||
version_code = version_code.clamp(1, 2100000000);
|
||||
}
|
||||
|
||||
if version_code == 0 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"You must change the `version` in `tauri.conf.json`. The default value `0.0.0` is not allowed for Android package and must be at least `0.0.1`."
|
||||
));
|
||||
} else if version_code > 2100000000 {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Invalid version code {}. Version code must be between 1 and 2100000000. You must change the `version` in `tauri.conf.json`.",
|
||||
version_code
|
||||
));
|
||||
}
|
||||
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite only if changed to not trigger rebuilds
|
||||
write_if_changed(&gradle_settings_path, gradle_settings)
|
||||
.context("failed to write tauri.settings.gradle")?;
|
||||
@@ -87,28 +56,8 @@ dependencies {"
|
||||
write_if_changed(&app_build_gradle_path, app_build_gradle)
|
||||
.context("failed to write tauri.build.gradle.kts")?;
|
||||
|
||||
if !app_tauri_properties.is_empty() {
|
||||
let app_tauri_properties_content = format!(
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n{}",
|
||||
app_tauri_properties.join("\n")
|
||||
);
|
||||
if std::fs::read_to_string(&app_tauri_properties_path)
|
||||
.map(|o| o != app_tauri_properties_content)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
write(&app_tauri_properties_path, app_tauri_properties_content)
|
||||
.context("failed to write tauri.properties")?;
|
||||
}
|
||||
}
|
||||
|
||||
println!("cargo:rerun-if-changed={}", gradle_settings_path.display());
|
||||
println!("cargo:rerun-if-changed={}", app_build_gradle_path.display());
|
||||
if !app_tauri_properties.is_empty() {
|
||||
println!(
|
||||
"cargo:rerun-if-changed={}",
|
||||
app_tauri_properties_path.display()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"default": {
|
||||
"active": false,
|
||||
"android": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"createUpdaterArtifacts": false,
|
||||
@@ -2282,6 +2283,7 @@
|
||||
"android": {
|
||||
"description": "Android configuration.",
|
||||
"default": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"allOf": [
|
||||
@@ -3826,6 +3828,11 @@
|
||||
"format": "uint32",
|
||||
"maximum": 2100000000.0,
|
||||
"minimum": 1.0
|
||||
},
|
||||
"autoIncrementVersionCode": {
|
||||
"description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -15,7 +15,7 @@ use crate::{
|
||||
flock,
|
||||
},
|
||||
interface::{AppInterface, Interface, Options as InterfaceOptions},
|
||||
mobile::{write_options, CliOptions, TargetDevice},
|
||||
mobile::{android::generate_tauri_properties, write_options, CliOptions, TargetDevice},
|
||||
ConfigValue, Error, Result,
|
||||
};
|
||||
use clap::{ArgAction, Parser};
|
||||
@@ -178,6 +178,12 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<BuiltApplica
|
||||
let mut env = env(options.ci)?;
|
||||
configure_cargo(&mut env, &config)?;
|
||||
|
||||
generate_tauri_properties(
|
||||
&config,
|
||||
tauri_config.lock().unwrap().as_ref().unwrap(),
|
||||
false,
|
||||
)?;
|
||||
|
||||
crate::build::setup(&interface, &mut build_options, tauri_config.clone(), true)?;
|
||||
|
||||
let installed_targets =
|
||||
|
||||
@@ -16,8 +16,8 @@ use crate::{
|
||||
},
|
||||
interface::{AppInterface, Interface, MobileOptions, Options as InterfaceOptions},
|
||||
mobile::{
|
||||
use_network_address_for_dev_url, write_options, CliOptions, DevChild, DevHost, DevProcess,
|
||||
TargetDevice,
|
||||
android::generate_tauri_properties, use_network_address_for_dev_url, write_options, CliOptions,
|
||||
DevChild, DevHost, DevProcess, TargetDevice,
|
||||
},
|
||||
ConfigValue, Error, Result,
|
||||
};
|
||||
@@ -271,6 +271,8 @@ fn run_dev(
|
||||
|
||||
configure_cargo(&mut env, config)?;
|
||||
|
||||
generate_tauri_properties(config, tauri_config.lock().unwrap().as_ref().unwrap(), true)?;
|
||||
|
||||
let installed_targets =
|
||||
crate::interface::rust::installation::installed_targets().unwrap_or_default();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use cargo_mobile2::{
|
||||
util::prompt,
|
||||
};
|
||||
use clap::{Parser, Subcommand};
|
||||
use semver::Version;
|
||||
use std::{
|
||||
env::set_var,
|
||||
fs::{create_dir, create_dir_all, read_dir, write},
|
||||
@@ -620,3 +621,66 @@ fn configure_cargo(env: &mut Env, config: &AndroidConfig) -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_tauri_properties(
|
||||
config: &AndroidConfig,
|
||||
tauri_config: &TauriConfig,
|
||||
dev: bool,
|
||||
) -> Result<()> {
|
||||
let app_tauri_properties_path = config.project_dir().join("app").join("tauri.properties");
|
||||
|
||||
let mut app_tauri_properties = Vec::new();
|
||||
if let Some(version) = tauri_config.version.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionName={version}"));
|
||||
if tauri_config.bundle.android.auto_increment_version_code && !dev {
|
||||
let last_version_code = std::fs::read_to_string(&app_tauri_properties_path)
|
||||
.ok()
|
||||
.and_then(|content| {
|
||||
content
|
||||
.lines()
|
||||
.find(|line| line.starts_with("tauri.android.versionCode="))
|
||||
.and_then(|line| line.split('=').nth(1))
|
||||
.and_then(|s| s.trim().parse::<u32>().ok())
|
||||
});
|
||||
let new_version_code = last_version_code.map(|v| v.saturating_add(1)).unwrap_or(1);
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={new_version_code}"));
|
||||
} else if let Some(version_code) = tauri_config.bundle.android.version_code.as_ref() {
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
} else if let Ok(version) = Version::parse(version) {
|
||||
let mut version_code = version.major * 1000000 + version.minor * 1000 + version.patch;
|
||||
|
||||
if dev {
|
||||
version_code = version_code.clamp(1, 2100000000);
|
||||
}
|
||||
|
||||
if version_code == 0 {
|
||||
crate::error::bail!(
|
||||
"You must change the `version` in `tauri.conf.json`. The default value `0.0.0` is not allowed for Android package and must be at least `0.0.1`."
|
||||
);
|
||||
} else if version_code > 2100000000 {
|
||||
crate::error::bail!(
|
||||
"Invalid version code {}. Version code must be between 1 and 2100000000. You must change the `version` in `tauri.conf.json`.",
|
||||
version_code
|
||||
);
|
||||
}
|
||||
|
||||
app_tauri_properties.push(format!("tauri.android.versionCode={version_code}"));
|
||||
}
|
||||
}
|
||||
|
||||
if !app_tauri_properties.is_empty() {
|
||||
let app_tauri_properties_content = format!(
|
||||
"// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.\n{}",
|
||||
app_tauri_properties.join("\n")
|
||||
);
|
||||
if std::fs::read_to_string(&app_tauri_properties_path)
|
||||
.map(|o| o != app_tauri_properties_content)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
write(&app_tauri_properties_path, app_tauri_properties_content)
|
||||
.context("failed to write tauri.properties")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"default": {
|
||||
"active": false,
|
||||
"android": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"createUpdaterArtifacts": false,
|
||||
@@ -2282,6 +2283,7 @@
|
||||
"android": {
|
||||
"description": "Android configuration.",
|
||||
"default": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"allOf": [
|
||||
@@ -3826,6 +3828,11 @@
|
||||
"format": "uint32",
|
||||
"maximum": 2100000000.0,
|
||||
"minimum": 1.0
|
||||
},
|
||||
"autoIncrementVersionCode": {
|
||||
"description": "Whether to automatically increment the `versionCode` on each build.\n\n - If `true`, the generator will try to read the last `versionCode` from\n `tauri.properties` and increment it by 1 for every build.\n - If `false` or not set, it falls back to `version_code` or semver-derived logic.\n\n Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -2929,6 +2929,16 @@ pub struct AndroidConfig {
|
||||
#[serde(alias = "version-code")]
|
||||
#[cfg_attr(feature = "schema", validate(range(min = 1, max = 2_100_000_000)))]
|
||||
pub version_code: Option<u32>,
|
||||
|
||||
/// Whether to automatically increment the `versionCode` on each build.
|
||||
///
|
||||
/// - If `true`, the generator will try to read the last `versionCode` from
|
||||
/// `tauri.properties` and increment it by 1 for every build.
|
||||
/// - If `false` or not set, it falls back to `version_code` or semver-derived logic.
|
||||
///
|
||||
/// Note that to use this feature, you should remove `/tauri.properties` from `src-tauri/gen/android/app/.gitignore` so the current versionCode is committed to the repository.
|
||||
#[serde(alias = "auto-increment-version-code", default)]
|
||||
pub auto_increment_version_code: bool,
|
||||
}
|
||||
|
||||
impl Default for AndroidConfig {
|
||||
@@ -2936,6 +2946,7 @@ impl Default for AndroidConfig {
|
||||
Self {
|
||||
min_sdk_version: default_min_sdk_version(),
|
||||
version_code: None,
|
||||
auto_increment_version_code: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user