diff --git a/CLAUDE.md b/CLAUDE.md index eb457a8b167f..875b97e70037 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -130,7 +130,9 @@ what it replaced, and the second round of tapping is always the expensive one. - The version is the git tag, not a number in the tree. `AndroidManifest.xml` carries no `versionCode`/`versionName`; `app/build.gradle` derives both from `-Podr.version` (`v4.8.0` -> name `4.8.0`, code `40800`, two digits per part, parts above 99 are an - error), and a build handed no version is `0.0.0`. Do not put the attributes back in the + error), and a build handed no version is `0.0.0`. All three parts are required: a + two-part `v4.7` was once padded to `4.7.0`, which let one build carry two names and is + why the tags before `v4.8.0` are in two formats. Do not put the attributes back in the manifest: gradle's values win in the merged manifest, so a second copy can only ever disagree with the tag. The release workflow passes the tag it ran on; a dispatched run passes its `version` input diff --git a/README.md b/README.md index 8cbade1793a7..bc473dae0ac5 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,12 @@ which the build refuses rather than folding `4.100.0` onto the same code as `5.0 Nothing has to be raised by hand before tagging, and no number on `main` can describe a release that already went out. +All three parts have to be spelled out. A two-part `v4.7` used to be padded to `4.7.0`, +which meant one build could be tagged under two names, and the tags older than `v4.8.0` +are in both formats because of it. They are left as they are - a release asset is served +from a URL carrying its tag name, and F-Droid rebuilds old versions from those names - +so the rule only holds for what is tagged from here on. + Builds handed no version - local ones, PR builds, `assembleProDebug` - are `0.0.0`. Nothing reads it: no code in the app looks at its own version, and only what the release workflow builds ever leaves the machine. Any build can be given a real one anyway, with diff --git a/app/build.gradle b/app/build.gradle index c410105a6915..7619eefe5dc0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,14 +39,15 @@ def hasReleaseSigning = releaseKeystore.isPresent() && releaseKeystorePassword.i def parseVersion = { String version -> // split rather than tokenize, which would swallow the empty part in '4..8' def parts = (version - ~/^v/).split('\\.', -1) as List - if (parts.isEmpty() || parts.size() > 3 || !parts.every { it ==~ /\d+/ }) { + // all three parts, spelled out. a missing one used to be padded with a zero, so + // 'v4.7' and 'v4.7.0' were the same build under two names - which is how the tags + // ended up in two formats. the padding is gone rather than the spelling made a + // convention, because a convention cannot fail the build + if (parts.size() != 3 || !parts.every { it ==~ /\d+/ }) { throw new GradleException( - "odr.version must look like 4.8 or v4.8.0, not '${version}'") + "odr.version must look like 4.8.0 or v4.8.0, not '${version}'") } def numbers = parts*.toInteger() - while (numbers.size() < 3) { - numbers << 0 - } // two digits per component: v4.8.0 is 40800. That is a one way step past the codes // that used to be counted by hand (204 and below) - the play store accepts a higher // code than the last one it saw and never a lower one.