Merge pull request #11: move to the 1.1 series
Verified green on the feature branch before merging: build, unit tests and Android lint (ci.yml run 59).
This commit is contained in:
@@ -34,7 +34,7 @@ jobs:
|
||||
# Stamp the APK as a dev-channel build exactly when it is a build of the
|
||||
# dev branch, which is exactly when it can be published below. Pull
|
||||
# request builds run against refs/pull/N/merge, so they stay unstamped at
|
||||
# 1.0.0-dev: they are never published and must not claim a channel
|
||||
# <series>.0-dev: they are never published and must not claim a channel
|
||||
# version.
|
||||
#
|
||||
# This condition has to stay in step with the publish steps' own. Stamping
|
||||
@@ -96,7 +96,12 @@ jobs:
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="v1.0.${{ github.run_number }}-dev"
|
||||
# The series comes from gradle.properties, which is the same file the
|
||||
# build read when it stamped the APK — so the tag and what is inside
|
||||
# it cannot name different versions.
|
||||
series="$(sed -n 's/^plgVersionSeries=//p' gradle.properties)"
|
||||
test -n "$series"
|
||||
version="v${series}.${{ github.run_number }}-dev"
|
||||
src="app/build/outputs/apk/debug/app-debug.apk"
|
||||
dest="ProLibertateGames-${version}.apk"
|
||||
cp "$src" "$dest"
|
||||
|
||||
@@ -49,7 +49,12 @@ jobs:
|
||||
id: stage
|
||||
run: |
|
||||
set -euo pipefail
|
||||
version="v1.0.${{ github.run_number }}"
|
||||
# The series comes from gradle.properties, which is the same file the
|
||||
# build read when it stamped the APK — so the tag and what is inside
|
||||
# it cannot name different versions.
|
||||
series="$(sed -n 's/^plgVersionSeries=//p' gradle.properties)"
|
||||
test -n "$series"
|
||||
version="v${series}.${{ github.run_number }}"
|
||||
src="app/build/outputs/apk/debug/app-debug.apk"
|
||||
dest="ProLibertateGames-${version}.apk"
|
||||
cp "$src" "$dest"
|
||||
|
||||
@@ -46,7 +46,7 @@ Skipping step 4 leaves a branch whose head was never built and no release.
|
||||
Both long-lived branches publish, so a merge is a release, not just an
|
||||
integration:
|
||||
|
||||
- **`dev`** → `ci.yml` publishes a `v1.0.N-dev` **prerelease**, offered by the
|
||||
- **`dev`** → `ci.yml` publishes a `v<series>.N-dev` **prerelease**, offered by the
|
||||
in-app updater to anyone on the Dev channel.
|
||||
- **`main`** → `release.yml` publishes a **production** release, which the
|
||||
updater installs for everyone on the Production channel.
|
||||
|
||||
@@ -165,9 +165,10 @@ production package instead.
|
||||
|
||||
- `.github/workflows/ci.yml` — builds, tests and lints on `dev` and on pull
|
||||
requests into `dev` or `main`. Its APK artifact is a dev build, versioned
|
||||
`1.0.0-dev`.
|
||||
`<series>.0-dev` — the series being whatever `plgVersionSeries` says in
|
||||
`gradle.properties`, currently **1.1**.
|
||||
- `.github/workflows/release.yml` — on push to `main`, builds the APK and
|
||||
publishes it as a GitHub Release tagged `v1.0.<run-number>`. The in-app updater
|
||||
publishes it as a GitHub Release tagged `v<series>.<run-number>`. The in-app updater
|
||||
reads that tag, which is why the APK's `versionCode` is the same run number.
|
||||
|
||||
### Installing without the app
|
||||
@@ -186,14 +187,34 @@ prereleases by design, and that is exactly what keeps a production install from
|
||||
being handed a dev build. Dev builds are reached through the in-app updater with
|
||||
the channel set to dev, or from the releases page.
|
||||
|
||||
### The version series
|
||||
|
||||
A version is **`<series>.<run number>`**. The series is set by hand, once, in
|
||||
`gradle.properties`:
|
||||
|
||||
```properties
|
||||
plgVersionSeries=1.1
|
||||
```
|
||||
|
||||
Both workflows read that same property when they name a release tag, and the
|
||||
build reads it when it stamps the APK, so the tag and what is inside it cannot
|
||||
name different versions. Bumping a series is a one-line change to that file and
|
||||
nothing else.
|
||||
|
||||
The number after it is the CI run number and keeps climbing on its own, which is
|
||||
what makes a series bump safe: `versionCode` is the run number *alone*, so
|
||||
going from 1.0 to 1.1 never looks like a downgrade to Android and never
|
||||
interrupts an OTA update. The series is a name for people; the run number is
|
||||
what the machines compare.
|
||||
|
||||
### Update channels
|
||||
|
||||
Both pipelines publish, to two separate channels:
|
||||
|
||||
| Channel | Published by | Tag | Marked |
|
||||
| --- | --- | --- | --- |
|
||||
| Production | `release.yml`, push to `main` | `v1.0.<n>` | release |
|
||||
| Dev | `ci.yml`, any build of `dev` | `v1.0.<n>-dev` | prerelease |
|
||||
| Production | `release.yml`, push to `main` | `v<series>.<n>` | release |
|
||||
| Dev | `ci.yml`, any build of `dev` | `v<series>.<n>-dev` | prerelease |
|
||||
|
||||
Dev builds are published as **prereleases** deliberately: GitHub's "latest
|
||||
release" endpoint skips prereleases, so a production-channel install can never
|
||||
|
||||
+12
-4
@@ -16,6 +16,11 @@ val buildChannel = System.getenv("PLG_CHANNEL").orEmpty()
|
||||
val runNumber = (System.getenv("GITHUB_RUN_NUMBER") ?: "").toIntOrNull() ?: 0
|
||||
val stampVersion = buildChannel.isNotEmpty() && runNumber > 0
|
||||
|
||||
// The version series, from gradle.properties. Both workflows read the same
|
||||
// property when they name a release tag, so the tag and the APK inside it
|
||||
// cannot disagree about which series they belong to.
|
||||
val versionSeries = (project.findProperty("plgVersionSeries") as String?) ?: "1.0"
|
||||
|
||||
// Anything that is not an explicit production build is a dev build: ci.yml
|
||||
// stamps "dev", and a local build with nothing set counts as dev too.
|
||||
//
|
||||
@@ -43,12 +48,15 @@ android {
|
||||
// know its own channel, so it must survive into the shipped APK. It
|
||||
// tracks isDevBuild rather than the stamp alone, so an unstamped local
|
||||
// build cannot end up claiming a channel its applicationId contradicts.
|
||||
// versionCode stays the run number and nothing else, so it keeps
|
||||
// climbing across a change of series: bumping 1.0 to 1.1 must not make
|
||||
// an update look like a downgrade to Android.
|
||||
versionCode = if (stampVersion) runNumber else 1
|
||||
versionName = when {
|
||||
stampVersion && buildChannel == "production" -> "1.0.$runNumber"
|
||||
stampVersion -> "1.0.$runNumber-dev"
|
||||
isDevBuild -> "1.0.0-dev"
|
||||
else -> "1.0.0"
|
||||
stampVersion && buildChannel == "production" -> "$versionSeries.$runNumber"
|
||||
stampVersion -> "$versionSeries.$runNumber-dev"
|
||||
isDevBuild -> "$versionSeries.0-dev"
|
||||
else -> "$versionSeries.0"
|
||||
}
|
||||
|
||||
// The launcher label. With both copies on the phone the app drawer shows
|
||||
|
||||
@@ -38,7 +38,7 @@ private const val DEV_SUFFIX = "-dev"
|
||||
/**
|
||||
* Over-the-air updates from the repository's GitHub Releases.
|
||||
*
|
||||
* Release tags are v1.0.<run-number> and the APK's versionCode is that same run
|
||||
* Release tags are v<series>.<run-number> and the APK's versionCode is that same run
|
||||
* number, so comparing the two is enough to tell whether a newer build exists.
|
||||
* The repository's releases must be publicly downloadable — no token is
|
||||
* embedded in the app, and GitHub blocks anonymous access to private assets.
|
||||
@@ -112,7 +112,9 @@ class Updater(private val activity: Activity) {
|
||||
|
||||
private fun toRelease(json: JSONObject): Release? {
|
||||
val tag = json.optString("tag_name").ifBlank { return null }
|
||||
// Tags are v1.0.<n> or v1.0.<n>-dev; the run number is the trailing part.
|
||||
// Tags are v<series>.<n>, with -dev on a prerelease. Only the trailing
|
||||
// run number is read: the series is a name for people and changing it
|
||||
// must not make an older build look newer.
|
||||
val versionCode = tag.substringAfterLast('.')
|
||||
.removeSuffix(DEV_SUFFIX)
|
||||
.toIntOrNull()
|
||||
|
||||
@@ -11,3 +11,15 @@ kotlin.code.style=official
|
||||
|
||||
# Only build the resources needed for the configuration being built.
|
||||
android.nonTransitiveRClass=true
|
||||
|
||||
# The version series every build and every release tag is named for: an APK is
|
||||
# <series>.<run number>, a production tag is v<series>.<n> and a dev tag adds
|
||||
# -dev. It lives here rather than in the build file because the workflows have
|
||||
# to name the tag as well, and they read it straight out of this file — three
|
||||
# copies of "1.1" would be three chances for a release to be tagged one thing
|
||||
# and built as another.
|
||||
#
|
||||
# Only the series is set by hand. The number after it is the CI run number, so
|
||||
# it keeps climbing on its own and an APK's versionCode never goes backwards
|
||||
# when this changes.
|
||||
plgVersionSeries=1.1
|
||||
|
||||
Reference in New Issue
Block a user