VersionCode should be autogenerated to ease release automation
To streamline our release automation process, it would be beneficial to implement an automatic version code generation strategy rather than relying on manual updates.
Reviewing the Firefox for Android project, I found they use a date-based system for generating a unique and sequentially increasing versionCode. Their method utilizes the format yDDDHHmm, where:
-
yrepresents the last digit of the year minus 16 (e.g., 2017 becomes 1) -
DDDis the zero-padded day of the year (e.g., September 6th is 249) -
HHfor the hour of the day (00-23) -
mmfor the minute within the hour
This approach stays within the maximum allowed versionCode of 2,100,000,000, typically producing a 9-digit code, ensuring each version is unique and sequentially higher than the last.
I propose we adopt a similar, date-based calculation for our version code, incorporating the same format yDDDHHmm:
-
y: The number of years since a base year, with 2024 as the starting point (e.g., 2024 is 0) -
DDD: The day of the year in 3 digits, zero-padded -
HHThe hour of the day in 2 digits (00-23) -
mmThe minute of the hour in 2 digits
For example:
- 2024-02-09 16:45 -> 0 | 040 | 16 | 45 -> 401_645 -> 6 digits
- 2025-10-12 09:23 -> 1 | 285 | 09 | 23 -> 12_850_923 -> 8 digits
- 2123-02-09 16:45 -> 99 | 040 | 16 | 45 -> 990_401_645 -> 9 digits
Alternatively the format ymmmmmm, with even more head room but harder to read:
-
yThe number of years since a base year, with 2024 as the starting point (e.g., 2024 is 0) -
mmmmmmDay of year in minutes + Hour in minutes + Minutes (6 digits)
This alternative approach would generate:
- 2024-02-09 16:45 -> 0 | 057_165 -> 57_165 -> 5 digits
- 2025-10-12 09:23 -> 1 | 409_523 -> 1_409_523 -> 7 digits
- 2123-02-09 16:45 -> 99 | 057_165 -> 99_057_165 -> 8 digits
- 3023-02-09 16:45 -> 999 | 057_165 -> 999_057_165 -> 9 digits
I welcome any feedback or suggestions on these proposed methods.
I think this might cause problems with F-Droid releases. I think they parse gradle files manually and if it's not a constant, they can't do that.
Right, F-Droid expects a static version code. So, if we write the version code to a file and the release build is picking that up, it should be fine. I guess we also need to commit this file for reproducible builds.
We could also use prebuild to inject the desired date before building.
Is it really necessary to have a versionCode scheme based on the date? Can't we just have a script increment the version code for every release?
It eliminates the need to do manual versionCode changes. Otherwise any automation needs manual intervention or is self updating. I'm not a fan of allowing CI worklfows to commit code.
A total different approach is to derive the version code from a git tag. But that is usually more complicated.
Currently in F-Droid all the metadata and release notes/changelog have disappeared: https://f-droid.org/en/packages/com.fsck.k9/
EDIT: Found the deedicated issue here https://github.com/thunderbird/thunderbird-android/issues/7709#issue-2179118986
If you wanted, rather than using a git tag, you can simply count the number of commits as the version code. Something like git rev-list --first-parent --count origin/main here's a sample you could add in the gradle file.
val getVersionCode: () -> Int = {
try {
val stdout = ByteArrayOutputStream()
exec {
commandLine("git", "rev-list", "--first-parent", "--count", "origin/main")
standardOutput = stdout
}
stdout.toString().trim().toInt()
} catch (ignored: Exception) {
-1
}
}