Repository navigation
Implement 30-bit version code schema with automatic derivation from git tags - #4
Conversation
- Add version code calculation using 7-7-7-9 bit schema (Major-Minor-Patch-Qualifier) - Version code: Stable releases use qualifier=511, beta builds use commits-since-tag - Version name follows v*.*.* pattern (stable) or v*.*.*-beta.X (development) - Update all CI workflows to pass version environment variables - Add fetch-depth: 0 to checkout for proper git history access Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com>
- Add clearer comments explaining intentional exception handling - Clarify that environment variables take precedence over git-derived values - Document that VERSION_STABLE must be explicitly "true" for stable releases Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com>
|
@copilot assuming the latest release version is v5.4.3(.511), your current method for computing the major.minor.patch.qualifier would cause the debug/test versions for the next semver to stay v5.4.3(.0-.510) depending the commit since last release, which isn't ideal since these versions should be higher than v5.4.3; therefore, the correct approach is to increase the .patch by 1 so that the "test releases" work towards v5.4.4(.0-.510) and then the next release whether it be v5.4.4 or v5.5.0 are both fine. can you verify my logic and if this fix makes sense, implement it? ensure to follow best practices and write idiomatic code; document our versionCode generation logic carefully in the docs/ and improve all documentations as well. |
- For beta builds, increment patch by 1 so betas are higher than previous stable - Add bounds checking for version overflow (patch > 127 rolls to next minor) - Update CI workflows with patch increment logic - Create comprehensive docs/VERSIONING.md documentation - Add versioning documentation link to README.md Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com>
Verified and implemented in a13df66. The logic is correct - after v5.4.3, betas now become v5.4.4-beta.X with version codes higher than v5.4.3. Changes made:
|
Implements automatic version code derivation using a 30-bit schema (7-7-7-9 bits for Major-Minor-Patch-Qualifier) that ensures proper ordering (
1.2.0-beta < 1.2.0 < 1.2.1) while staying under Google Play's 2.1B limit.Version Code Schema
<< 23<< 16<< 9Changes
app/build.gradle: Version code/name auto-derived from latestv*.*.*git tagv1.2.3v1.2.4-beta.XVERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_BUILD_COUNT,VERSION_STABLE) override git values for CICI Workflows: All updated with
fetch-depth: 0and version calculation stepsci-build.yml: Beta versioning for PR/push builds with patch incrementrelease.yml: Stable versioning forv*.*.*tag releasesbuild-release.yaml: Legacy workflow aligned with schemaci-tests.yml: Fetch depth for version consistencyDocumentation: Created comprehensive
docs/VERSIONING.mdand updatedREADME.mdwith versioning sectionExample
After releasing
v5.4.3:Original prompt
I want the versionCode for the project to be automatically derived following the schema attached. I want you to carefully think through the schema and how to apply that in the most elegant way to the current build pipeline. (The Python script is for your reference; it's probably not the best way to integrate this versioning schema into the project). Please follow best practices and write idiomatic code for this significant change to the build pipeline, and ensure you look through all CI files that produce binaries carefully to upgrade them to the same schema so there must be no difference. Also you must ensure all release versions follows the v*.. pattern by updating the gradle build file and all files you deem necessary to achieve a consistent state (which may involve changes to the gradle configuration and CI files as well) and all commit/pr CI generate binaries with sensible version name and version code following the same schema as well.
=== versioning documentation ===
To ensure ordering (
1.2.0-beta < 1.2.0 < 1.2.1), safety (under 2.1B), and automation, I recommend a 30-bit schema that partitions the integer into four fixed-width fields.Using 30 bits ensures the maximum value ($\approx 1.07$ billion) is safely under Google Play’s 2.1 billion limit ($2^{31}-1$ is the hard technical max, but 2.1B is the safe zone).
The Recommended "Safe 30-Bit" Schema
This split balances standard SemVer growth with a healthy buffer for CI/test builds between releases.
<< 23<< 16<< 9<< 0Total Capacity:$2^{30}-1 = 1,073,741,823$ (Safe).
The Logic: How to Interleave Test vs. Stable
To satisfy the rule Test < Stable, we reserve the maximum possible value of the "Qualifier" field for the Stable release. All test/beta builds use numbers lower than that maximum.
1. For a Stable Release (
1.2.3):Set the Qualifier to its max value (
511or binary111111111).[
\text{Code} = (\text{Major} \times 2^{23}) + (\text{Minor} \times 2^{16}) + (\text{Patch} \times 2^{9}) + 511
]
2. For a Test/Beta Release ($< 511$ .
1.2.3-beta.X):Set the Qualifier to your build counter (derived from git). It must be
[
\text{Code} = (\text{Major} \times 2^{23}) + (\text{Minor} \times 2^{16}) + (\text{Patch} \times 2^{9}) + \text{BuildCount}
]
Why this works (Example)
Notice how the integer naturally scales. Even the "highest" beta for
1.2.0is lower than the stable1.2.0, and stable1.2.0is lower than the very first beta of1.2.1.1.2.0-beta.55...010 0000000 00110111(Ends in 55)1.2.0(Stable)...010 0000000 11111111(Ends in 511)1.2.1-beta.1...010 0000001 00000001(Patch bit flips, value jumps)How to Derive the "BuildCount" Automatically
Since you only have 9 bits (511 slots) for the test field, you cannot use the global commit count (which reaches thousands). You must use the commits since the last tag.
Git Command for CI:
If you are on a fresh version tag (e.g., just tagged 1.2.3), this returns 0. For the beta releases following it, it counts up 1, 2, 3...
Python Implementation
Here is a script you can use in your build pipeline to generate this deterministically.