Skip to content

Lock the Android tag to versionName, the way the exporter's is - #59

Merged
parawanderer merged 1 commit into
mainfrom
feat/lock-android-tag-to-version
Aug 9, 2026
Merged

parawanderer merged 1 commit into
mainfrom
feat/lock-android-tag-to-version

Conversation

@parawanderer

Copy link
Copy Markdown
Owner

The exporter cannot be released under a tag that disagrees with its source — that check runs before either binary builds. The Android app had no equivalent, so an android-app-v* tag could claim any version while the APK reported another.

That asymmetry existed for no better reason than the exporter being the release that was being cut when the check was written.

One mechanism, not two

exporter_version.py becomes release_version.py with a --kind, rather than a second copy of the same idea:

Kind Version lives in Tag
exporter VERSION in python/main/wizard.py macos-exporter-v*
android versionName in app/build.gradle.kts android-app-v*

Both work the same way: the version lives in the source, the tag is derived from it, and a disagreement fails the release with instructions naming the file to edit.

ERROR: Release tag and source version disagree.

    tag  android-app-v9.9.9  declares  9.9.9
    app/build.gradle.kts:36  declares  1.0.5

app/build.gradle.kts is the single source of truth.
versionName is what the app reports about itself in Settings and in bug reports,
and it is baked into the APK - no build step rewrites it from the tag.

The messages differ per kind because the reasons differ — the exporter's VERSION is stamped into every export as via:, while versionName is what users and bug reports quote.

In the workflow

build-release.yml now runs the check instead of parsing the tag by hand with awk and cut, and takes the version from the source. It runs before the Gradle build, so a mismatch costs seconds rather than a full signed build.

Tests

Cover the Android side, including the trap that makes a naive regex wrong — versionNameSuffix = "-debug" sits four lines below versionName — and assert the two tag prefixes cannot overlap, since both releases live in one repository and a shared prefix would let either check the other.

Docs

CONTRIBUTING gains a Releasing the Android app section, which the new error message points at. It says to bump versionCode as well: Android refuses an APK whose code is not higher than the installed one, so a versionName-only bump leaves existing users unable to update — and that fails on their phone, never in any build.

It also notes the signing secrets the Android release needs, which are separate from the exporter's token and have not been exercised since July 2025.

Note

Depends on nothing, but overlaps #58 (the token fix in the same workflow, different region) and #53 (release_notes.py imports the renamed module — I will rebase that branch once this lands).

🤖 Generated with Claude Code

The exporter cannot be released under a tag that disagrees with its source - the
check runs before either binary builds. The Android app had no equivalent, so an
android-app-v* tag could claim any version while the APK reported another. That
asymmetry existed only because the exporter was the release being cut when the
check was written.

exporter_version.py is now release_version.py with a --kind, rather than a
second copy of the same idea. Both releases work the same way: the version lives
in the source, the tag is derived from it, and a disagreement fails the release
with instructions naming the file to edit.

  exporter -> VERSION in python/main/wizard.py
  android  -> versionName in app/build.gradle.kts

build-release.yml now runs that check instead of parsing the tag by hand with
awk and cut, and takes the version from the source. It runs before the Gradle
build, so a mismatch costs seconds rather than a full signed build.

The failure messages differ per kind because the reasons differ: the exporter's
VERSION is stamped into every export as `via:`, while versionName is what the
app reports in Settings and in bug reports. Both are baked in at build time by
something no later step rewrites, which is why the tag alone cannot be trusted.

Tests cover the Android side including the trap that makes a naive regex wrong -
versionNameSuffix = "-debug" sits four lines below versionName - and assert the
two tag prefixes cannot overlap, since both releases live in one repository and
a shared prefix would let either check the other.

CONTRIBUTING gains a Releasing the Android app section, which the new error
message points at. It says to bump versionCode as well: Android refuses an APK
whose code is not higher than the installed one, so a versionName-only bump
leaves existing users unable to update, and it fails on their phone rather than
in any build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@parawanderer
parawanderer merged commit 9e008fe into main Aug 9, 2026
8 checks passed

This branch was previously deployed

1 inactive deployment
Android Build — 460cdaef Deployed Aug 9, 2026 by parawanderer via build #40
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.

1 participant