Pin OTA releases to main and stop dev builds outranking them

Two ways the updater could have served or blocked the wrong build:

- release.yml also triggers on workflow_dispatch, which can be aimed at
  any branch from the Actions UI. That would have built dev code and
  published it as a real Release, which every install would then offer to
  download. The job now refuses to run off anything but main.

- versionCode came from GITHUB_RUN_NUMBER, but that counter is per
  workflow, so the dev pipeline had its own independent sequence. A debug
  APK installed from a CI artifact already carried a higher versionCode
  than the first several releases would, and the updater's check is
  latest <= installed, so those users would have been told they were up
  to date indefinitely. Only release.yml now sets PLG_RELEASE, and only
  that stamps a real version; everything else stays at 1.0.0-dev.

Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_015qjfMiPUDshdKEUa6vxqzN
This commit is contained in:
Claude
2026-08-05 23:47:20 +00:00
parent 85ec10836b
commit 80ff178437
3 changed files with 39 additions and 7 deletions
+20 -6
View File
@@ -4,10 +4,20 @@ plugins {
id("org.jetbrains.kotlin.plugin.serialization")
}
// On CI, GITHUB_RUN_NUMBER is set automatically and matches the release tag
// (v1.0.<run-number>), so the shipped APK knows its own version and the
// in-app updater can tell whether a newer release exists. Locally it's a dev build.
val ciRunNumber = (System.getenv("GITHUB_RUN_NUMBER") ?: "").toIntOrNull() ?: 0
// Only the release workflow stamps a real version. It sets PLG_RELEASE, and its
// GITHUB_RUN_NUMBER is the same number as the release tag it publishes
// (v1.0.<run-number>), so the shipped APK knows its own version and the in-app
// updater can compare against the latest published release.
//
// Everything else — a local build, or the dev CI pipeline — stays at 1.0.0-dev.
// GITHUB_RUN_NUMBER alone is NOT enough to key off: it counts per workflow, so
// the dev pipeline has its own independent sequence. A debug APK installed from
// a CI artifact would otherwise carry that counter as its versionCode, could
// outrank a genuine release, and would leave the updater reporting "you're on
// the latest version" indefinitely.
val isReleaseBuild = System.getenv("PLG_RELEASE") == "1"
val releaseRunNumber = (System.getenv("GITHUB_RUN_NUMBER") ?: "").toIntOrNull() ?: 0
val stampReleaseVersion = isReleaseBuild && releaseRunNumber > 0
android {
namespace = "org.prolibertate.games"
@@ -17,8 +27,12 @@ android {
applicationId = "org.prolibertate.games"
minSdk = 24
targetSdk = 34
versionCode = if (ciRunNumber > 0) ciRunNumber else 1
versionName = if (ciRunNumber > 0) "1.0.$ciRunNumber" else "1.0.0-dev"
// Dev builds sit at 1, below every release except the very first —
// a v1.0.1 release ties with a dev build and so is not offered as an
// update. Harmless, and preferable to versionCode 0, which Android
// documents as out of range.
versionCode = if (stampReleaseVersion) releaseRunNumber else 1
versionName = if (stampReleaseVersion) "1.0.$releaseRunNumber" else "1.0.0-dev"
}
signingConfigs {