fix(android): restore monotonic versionCode and guard releases (v0.9.17 = uninstallable) - #110
Merged
abdulsaheel merged 1 commit intoJul 20, 2026
Conversation
pubspec 'version: 0.9.17+1' shipped v0.9.17 with versionCode 1, a downgrade from v0.9.15/v0.9.16 (versionCode 48). Android blocks the upgrade install (INSTALL_FAILED_VERSION_DOWNGRADE), surfaced to users as "App not installed". - bump to 0.9.18+49 so the next release installs over existing devices - add a release-time CI guard that fails the build when the versionCode is missing, non-integer, mismatched with the tag, or not strictly greater than the highest already-released versionCode
Contributor
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe package version is bumped to ChangesRelease version validation
Estimated code review effort: 3 (Moderate) | ~15–30 minutes Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Workflow as Android release workflow
participant Pubspec as pubspec.yaml
participant Tags as prior v* git tags
Workflow->>Pubspec: Read package version
Workflow->>Tags: Read prior versionCode values
Workflow->>Workflow: Validate tag match and increasing versionCode
Workflow->>Workflow: Continue build when checks pass
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Installing the v0.9.17 release fails on-device with a bare "App not installed" dialog. It isn't a signing issue — every official release is signed with the same keystore from CI secrets. It's a versionCode downgrade.
Actual values baked into the shipped APKs:
android/app/build.gradle.ktssetsversionCode = flutter.versionCode, and Flutter derives that from the+BUILDsuffix inpubspec.yaml. Commitc8d75afsetversion: 0.9.17+1, so versionCode collapsed 48 → 1. Android refuses to install an APK whose versionCode is lower than the installed one (INSTALL_FAILED_VERSION_DOWNGRADE), shown to users as "App not installed".(Two supporting clues: v0.9.16 is byte-for-byte identical to v0.9.15 and still reports versionName
0.9.15— pubspec wasn't bumped for that tag either; and the release trigger is justpush: tags: ['v*'], so a bad pubspec sails straight to a published release with no gate.)Fix
pubspec.yaml→0.9.18+49— restores a monotonic versionCode (49 > 48). A fresh patch release rather than re-cutting the burnedv0.9.17tag;49upgrades cleanly over both the versionCode-48 installs and anyone who grabbed the broken versionCode-1 build.Release-time CI guard in
build.yml(runs before the build) that fails the release when the versionCode is:+BUILDsuffix (the exact v0.9.17 footgun — Flutter would silently fall back to 1),Needs
fetch-depth: 0on checkout so it can read prior tags' pubspec. Verified locally: passes for0.9.18+49, and correctly rejects the0.9.17+1case (versionCode 1 <= prior max 48).Note for release cutter
v0.9.17is already published with versionCode 1 and can't be fixed in place — cut v0.9.18 from this branch once merged. Anyone who installed the broken v0.9.17 will be able to upgrade to v0.9.18 normally.Summary by CodeRabbit
New Features
Chores