Skip to content

feat(android): add auto_increment_version_code option for Android builds - #40

Open
tomerqodo wants to merge 6 commits into
qodo_claude_vs_qodo_base_featandroid_add_auto_increment_version_code_option_for_android_builds__pr1from
qodo_claude_vs_qodo_head_featandroid_add_auto_increment_version_code_option_for_android_builds__pr1
Open

tomerqodo wants to merge 6 commits into
qodo_claude_vs_qodo_base_featandroid_add_auto_increment_version_code_option_for_android_builds__pr1from
qodo_claude_vs_qodo_head_featandroid_add_auto_increment_version_code_option_for_android_builds__pr1

Conversation

@tomerqodo

Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#1

@qodo-code-review

Copy link
Copy Markdown

Review Summary by Qodo

Add autoIncrementVersionCode option for Android version management

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add autoIncrementVersionCode config option for Android builds
• Automatically increment version code on each build from properties file
• Refactor version code generation logic into dedicated function
• Move properties generation from build-time to CLI commands
Diagram
flowchart LR
  A["AndroidConfig"] -->|"new field"| B["auto_increment_version_code"]
  C["CLI Build/Dev"] -->|"calls"| D["generate_tauri_properties"]
  D -->|"reads last code"| E["tauri.properties"]
  D -->|"increments or uses"| F["version_code/semver"]
  D -->|"writes"| E
  G["tauri-build"] -->|"simplified"| H["generate_gradle_files"]
Loading

Grey Divider

File Changes

1. crates/tauri-utils/src/config.rs ✨ Enhancement +11/-0

Add auto_increment_version_code field to AndroidConfig

crates/tauri-utils/src/config.rs


2. crates/tauri-cli/src/mobile/android/mod.rs ✨ Enhancement +64/-0

Implement generate_tauri_properties function with auto-increment logic

crates/tauri-cli/src/mobile/android/mod.rs


3. crates/tauri-cli/src/mobile/android/build.rs ✨ Enhancement +7/-1

Call generate_tauri_properties during Android build

crates/tauri-cli/src/mobile/android/build.rs


View more (6)
4. crates/tauri-cli/src/mobile/android/dev.rs ✨ Enhancement +4/-2

Call generate_tauri_properties during Android dev mode

crates/tauri-cli/src/mobile/android/dev.rs


5. crates/tauri-build/src/lib.rs ✨ Enhancement +1/-1

Remove config parameter from generate_gradle_files call

crates/tauri-build/src/lib.rs


6. crates/tauri-build/src/mobile.rs ✨ Enhancement +3/-54

Remove version code generation logic from gradle generation

crates/tauri-build/src/mobile.rs


7. crates/tauri-cli/config.schema.json 📝 Documentation +7/-0

Add autoIncrementVersionCode schema definition

crates/tauri-cli/config.schema.json


8. crates/tauri-schema-generator/schemas/config.schema.json 📝 Documentation +7/-0

Add autoIncrementVersionCode schema definition

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


9. .changes/auto-increment-android-version-code.md 📝 Documentation +8/-0

Add changelog entry for new feature

.changes/auto-increment-android-version-code.md


Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Mar 10, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (2) 📎 Requirement gaps (0)

Grey Divider


Action required

1. generate_tauri_properties lacks docs 📘 Rule violation ✓ Correctness
Description
A new pub fn generate_tauri_properties is introduced without Rust documentation comments. This
violates the requirement to document public APIs for usability and generated docs.
Code

crates/tauri-cli/src/mobile/android/mod.rs[R625-629]

+pub fn generate_tauri_properties(
+  config: &AndroidConfig,
+  tauri_config: &TauriConfig,
+  dev: bool,
+) -> Result<()> {
Evidence
PR Compliance ID 7 requires documentation comments for public functions; the added public function
has no preceding /// doc comments in the changed lines.

AGENTS.md
crates/tauri-cli/src/mobile/android/mod.rs[625-629]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new public function `generate_tauri_properties` was added without Rust doc comments (`///`). Public APIs must be documented.

## Issue Context
This function is `pub` and will appear in generated documentation; add docs describing what it generates, what inputs mean (`config`, `tauri_config`, `dev`), and key behavior (auto-increment logic, reading/writing `tauri.properties`).

## Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[625-629]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. tauri_config.lock() uses unwrap 📘 Rule violation ⛯ Reliability
Description
The new Android build path uses unwrap() on a mutex lock and on an Option, which can panic and
terminate the process. This violates the requirement to avoid panicking for fallible operations and
to return/propagate errors via Result.
Code

crates/tauri-cli/src/mobile/android/build.rs[R181-185]

+  generate_tauri_properties(
+    &config,
+    tauri_config.lock().unwrap().as_ref().unwrap(),
+    false,
+  )?;
Evidence
PR Compliance ID 16 forbids hiding fallible failures via panics; the added code calls unwrap()
twice when accessing tauri_config, which can panic on poisoned mutex or missing config.

AGENTS.md
crates/tauri-cli/src/mobile/android/build.rs[181-185]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New code in Android build uses `tauri_config.lock().unwrap().as_ref().unwrap()`, which can panic (poisoned mutex / missing config). Compliance requires returning/propagating errors as `Result` instead of panicking.

## Issue Context
`generate_tauri_properties` already returns `Result&lt;()&gt;`, so callers can (and should) propagate lock/option access failures via `?` and meaningful errors rather than `unwrap()`.

## Fix Focus Areas
- crates/tauri-cli/src/mobile/android/build.rs[181-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Missing Android version properties 🐞 Bug ✓ Correctness
Description
tauri-build::try_build no longer generates app/tauri.properties, so Android builds that don’t
run tauri-cli’s generate_tauri_properties will ignore tauri.conf.json version/versionCode and
fall back to the Gradle template defaults (1/1.0). This silently produces wrong Android
versionCode/versionName in those build flows.
Code

crates/tauri-build/src/lib.rs[R501-503]

  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)?;
  }
Evidence
Android’s Gradle template uses app/tauri.properties to set versionCode/versionName (defaulting
to 1/1.0 if the file is absent). The app build script calls into tauri_build::build() /
try_build(), but tauri-build now only generates Gradle include files when
TAURI_ANDROID_PROJECT_PATH is set and never writes tauri.properties, so non-CLI build flows
won’t get the version values written anymore.

crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[11-28]
crates/tauri-cli/templates/app/src-tauri/build.rs[1-3]
crates/tauri-build/src/lib.rs[473-503]
crates/tauri-build/src/mobile.rs[10-62]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Android versionCode/versionName are sourced from `app/tauri.properties` in the Android Gradle template. This PR removed `tauri.properties` generation from `tauri-build`, making correct versioning dependent on tauri-cli calling `generate_tauri_properties`, which does not cover non-CLI build flows.

### Issue Context
`tauri_build::try_build` still parses the Tauri config and still runs during Cargo build scripts, but now only writes `tauri.settings.gradle` and `tauri.build.gradle.kts`. The Gradle template defaults to versionCode=1/versionName=1.0 when `tauri.properties` is missing.

### Fix Focus Areas
- crates/tauri-build/src/lib.rs[473-503]
- crates/tauri-build/src/mobile.rs[10-62]
- crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[11-28]

### Implementation direction
- Reintroduce `tauri.properties` generation in `tauri-build` using the parsed `Config` (including the new `auto_increment_version_code` behavior), or
- Add a `tauri-build` helper (e.g., `mobile::generate_tauri_properties(project_dir, config, dev)`), called from `try_build()` when `TAURI_ANDROID_PROJECT_PATH` is present.
- Ensure behavior matches the documented limits and dev/release expectations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (2)
4. Unbounded auto-increment versionCode 🐞 Bug ✓ Correctness
Description
With autoIncrementVersionCode=true, generate_tauri_properties increments the previous
versionCode without enforcing the documented maximum (2,100,000,000). This can create an
out-of-policy versionCode (Play Store rejection) and can eventually exceed Kotlin/Gradle Int
parsing limits, breaking the build.
Code

crates/tauri-cli/src/mobile/android/mod.rs[R635-646]

+    if tauri_config.bundle.android.auto_increment_version_code {
+      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}"));
Evidence
The auto-increment path uses saturating_add(1) and writes the result directly, without checking
the max constraint used elsewhere for version_code. The Android template parses the value using
toInt(), which will throw for values above Int.MAX_VALUE, and Play Store policy is capped at
2,100,000,000 (also reflected in config validation).

crates/tauri-cli/src/mobile/android/mod.rs[635-646]
crates/tauri-utils/src/config.rs[2917-2931]
crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[21-28]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`autoIncrementVersionCode` increments versionCode without validating the new value against the documented maximum (2,100,000,000) and without considering Gradle/Kotlin `Int` parsing constraints.

### Issue Context
The value is written into `app/tauri.properties`, then the Android Gradle template reads it via `.toInt()`.

### Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[635-646]
- crates/tauri-utils/src/config.rs[2917-2931]
- crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[21-28]

### Implementation direction
- Parse last_version_code as `u32`.
- If last_version_code &gt;= 2_100_000_000, return an error explaining the limit and how to reset/override.
- Use `checked_add(1)` instead of `saturating_add(1)`.
- Optionally also reject values &gt; `i32::MAX` (2_147_483_647) because Gradle uses `toInt()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Auto-increment resets to 1 🐞 Bug ⛯ Reliability
Description
If tauri.properties is missing/unreadable or the tauri.android.versionCode= line can’t be
parsed, autoIncrementVersionCode silently sets versionCode to 1. This can decrease the versionCode
relative to prior releases and block upgrades/publishing without any warning.
Code

crates/tauri-cli/src/mobile/android/mod.rs[R636-646]

+      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}"));
Evidence
The code suppresses all read errors with .ok() and defaults to 1 with unwrap_or(1). Compounding
this, the Android template’s .gitignore ignores tauri.properties by default, making a missing
file a common scenario; enabling the feature in that default setup yields repeated versionCode=1.

crates/tauri-cli/src/mobile/android/mod.rs[636-646]
crates/tauri-cli/templates/mobile/android/app/.gitignore[4-6]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`autoIncrementVersionCode` silently falls back to versionCode=1 when `tauri.properties` is missing/unreadable/malformed. This is especially likely because the Android template ignores `tauri.properties` by default.

### Issue Context
Silent resets can cause non-monotonic versionCode and publishing/update failures.

### Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[636-646]
- crates/tauri-cli/templates/mobile/android/app/.gitignore[4-6]

### Implementation direction
- If `tauri.properties` is missing and auto-increment is enabled:
 - Either: bail with a clear error telling the user to commit/unignore the file or set `bundle.android.versionCode` explicitly.
 - Or: initialize from `bundle.android.version_code` if present, else from semver-derived versionCode, then write that value.
- If file exists but is unreadable/unparseable: return an error (don’t swallow with `.ok()`).
- Consider emitting a log message describing the chosen versionCode source.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment on lines +625 to +629
pub fn generate_tauri_properties(
config: &AndroidConfig,
tauri_config: &TauriConfig,
dev: bool,
) -> Result<()> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. generate_tauri_properties lacks docs 📘 Rule violation ✓ Correctness

A new pub fn generate_tauri_properties is introduced without Rust documentation comments. This
violates the requirement to document public APIs for usability and generated docs.
Agent Prompt
## Issue description
A new public function `generate_tauri_properties` was added without Rust doc comments (`///`). Public APIs must be documented.

## Issue Context
This function is `pub` and will appear in generated documentation; add docs describing what it generates, what inputs mean (`config`, `tauri_config`, `dev`), and key behavior (auto-increment logic, reading/writing `tauri.properties`).

## Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[625-629]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +181 to +185
generate_tauri_properties(
&config,
tauri_config.lock().unwrap().as_ref().unwrap(),
false,
)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. tauri_config.lock() uses unwrap 📘 Rule violation ⛯ Reliability

The new Android build path uses unwrap() on a mutex lock and on an Option, which can panic and
terminate the process. This violates the requirement to avoid panicking for fallible operations and
to return/propagate errors via Result.
Agent Prompt
## Issue description
New code in Android build uses `tauri_config.lock().unwrap().as_ref().unwrap()`, which can panic (poisoned mutex / missing config). Compliance requires returning/propagating errors as `Result` instead of panicking.

## Issue Context
`generate_tauri_properties` already returns `Result<()>`, so callers can (and should) propagate lock/option access failures via `?` and meaningful errors rather than `unwrap()`.

## Fix Focus Areas
- crates/tauri-cli/src/mobile/android/build.rs[181-185]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines 501 to 503
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)?;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Missing android version properties 🐞 Bug ✓ Correctness

tauri-build::try_build no longer generates app/tauri.properties, so Android builds that don’t
run tauri-cli’s generate_tauri_properties will ignore tauri.conf.json version/versionCode and
fall back to the Gradle template defaults (1/1.0). This silently produces wrong Android
versionCode/versionName in those build flows.
Agent Prompt
### Issue description
Android versionCode/versionName are sourced from `app/tauri.properties` in the Android Gradle template. This PR removed `tauri.properties` generation from `tauri-build`, making correct versioning dependent on tauri-cli calling `generate_tauri_properties`, which does not cover non-CLI build flows.

### Issue Context
`tauri_build::try_build` still parses the Tauri config and still runs during Cargo build scripts, but now only writes `tauri.settings.gradle` and `tauri.build.gradle.kts`. The Gradle template defaults to versionCode=1/versionName=1.0 when `tauri.properties` is missing.

### Fix Focus Areas
- crates/tauri-build/src/lib.rs[473-503]
- crates/tauri-build/src/mobile.rs[10-62]
- crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[11-28]

### Implementation direction
- Reintroduce `tauri.properties` generation in `tauri-build` using the parsed `Config` (including the new `auto_increment_version_code` behavior), or
- Add a `tauri-build` helper (e.g., `mobile::generate_tauri_properties(project_dir, config, dev)`), called from `try_build()` when `TAURI_ANDROID_PROJECT_PATH` is present.
- Ensure behavior matches the documented limits and dev/release expectations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +635 to +646
if tauri_config.bundle.android.auto_increment_version_code {
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}"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

4. Unbounded auto-increment versioncode 🐞 Bug ✓ Correctness

With autoIncrementVersionCode=true, generate_tauri_properties increments the previous
versionCode without enforcing the documented maximum (2,100,000,000). This can create an
out-of-policy versionCode (Play Store rejection) and can eventually exceed Kotlin/Gradle Int
parsing limits, breaking the build.
Agent Prompt
### Issue description
`autoIncrementVersionCode` increments versionCode without validating the new value against the documented maximum (2,100,000,000) and without considering Gradle/Kotlin `Int` parsing constraints.

### Issue Context
The value is written into `app/tauri.properties`, then the Android Gradle template reads it via `.toInt()`.

### Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[635-646]
- crates/tauri-utils/src/config.rs[2917-2931]
- crates/tauri-cli/templates/mobile/android/app/build.gradle.kts[21-28]

### Implementation direction
- Parse last_version_code as `u32`.
- If last_version_code >= 2_100_000_000, return an error explaining the limit and how to reset/override.
- Use `checked_add(1)` instead of `saturating_add(1)`.
- Optionally also reject values > `i32::MAX` (2_147_483_647) because Gradle uses `toInt()`.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +636 to +646
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}"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

5. Auto-increment resets to 1 🐞 Bug ⛯ Reliability

If tauri.properties is missing/unreadable or the tauri.android.versionCode= line can’t be
parsed, autoIncrementVersionCode silently sets versionCode to 1. This can decrease the versionCode
relative to prior releases and block upgrades/publishing without any warning.
Agent Prompt
### Issue description
`autoIncrementVersionCode` silently falls back to versionCode=1 when `tauri.properties` is missing/unreadable/malformed. This is especially likely because the Android template ignores `tauri.properties` by default.

### Issue Context
Silent resets can cause non-monotonic versionCode and publishing/update failures.

### Fix Focus Areas
- crates/tauri-cli/src/mobile/android/mod.rs[636-646]
- crates/tauri-cli/templates/mobile/android/app/.gitignore[4-6]

### Implementation direction
- If `tauri.properties` is missing and auto-increment is enabled:
  - Either: bail with a clear error telling the user to commit/unignore the file or set `bundle.android.versionCode` explicitly.
  - Or: initialize from `bundle.android.version_code` if present, else from semver-derived versionCode, then write that value.
- If file exists but is unreadable/unparseable: return an error (don’t swallow with `.ok()`).
- Consider emitting a log message describing the chosen versionCode source.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants