Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Renovate / renovate (push) Successful in 52s
### What this changes Adds beta releases. Pushing a `release/*` branch whose committed `versionName` is `X.Y.Z-beta.N` makes the new `.gitea/workflows/beta.yaml` run the unit tests, build and sign the APK with the app key, and publish it as a **Codeberg pre-release** (APK + `.sha256`), plus a Gitea pre-release with the R8 mapping. F-Droid (self-hosted and official) and Play never get a beta; Obtainium only offers it with *Include prereleases* on. - **`scripts/version_info.sh`** is the single source for `versionName` → `versionCode`, used by `release.yaml`, `beta.yaml`, the changelog sync and the store-listing check. From 1.1.0: `X*1000000 + Y*10000 + Z*100 + N` for betas (N = 1–98), `+ 99` for stable, so `1.1.0-beta.1` → `1010001`, `1.1.0` → `1010099`. All 1.0.x versions keep the legacy formula, so `release/v1.0.1` (code `10001`) stays valid. - **Shared publish scripts:** `scripts/publish_codeberg_release.sh`, `scripts/publish_gitea_release.sh` and `scripts/release_notes.sh`, moved out of `release.yaml`. The stable path behaves as before. - **Guards:** - CI fails a PR whose committed `versionCode` doesn't match its `versionName`. - CI fails a PR into `main` that carries a beta version. - `release.yaml`'s `detect` refuses a beta on `main` as a backstop. - `beta.yaml` refuses a beta of a version that has already shipped as stable. - Betas get no store What's New file. - **Docs:** "Cutting a beta" and the versionCode table in `docs/RELEASING.md`; a note on beta tags in `docs/fdroid-official/README.md`; how to opt in to betas in the README. ### Why To ship a test build of an upcoming version (e.g. 1.1.0) to opted-in testers before the stable release, without it reaching F-Droid or Play users. ### How it was tested - `scripts/version_info.sh` against stable, beta, legacy and invalid version names. - Both publish scripts against a mock forge API: create, re-run (PATCH plus asset replacement), Codeberg's 500-then-retry path, and the skip when no token is set. - A scratch copy with `1.1.0-beta.1` committed: the version check passes, the changelog sync and `check_store_listing.py --complete` pass without a What's New, the PR-into-main guard trips, and a wrong `versionCode` is rejected. - `sync_changelog_to_fastlane.sh` and `check_store_listing.py` (with and without `--complete`) still pass on the current `1.0.0`. - All three workflow files parse as YAML. Not run on the real runners yet. The first beta push is the live test of `beta.yaml`, which assumes a mirrored branch push starts a workflow on Gitea, the same way pushes to `main` already do. ### Checklist - [x] No `versionName` / `versionCode` bump - [x] No `values-*/strings.xml` touched - [x] `CHANGELOG.md` not updated: this is release infrastructure, not a user-visible change Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Reviewed-on: https://codeberg.org/jlmakiola/agendula/pulls/38
88 lines
3.5 KiB
Bash
Executable File
88 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# The one place that turns the committed versionName into a versionCode and a
|
|
# release channel. The release and beta pipelines, the changelog sync and the
|
|
# store-listing check all read it from here, so the scheme can't drift between
|
|
# them.
|
|
#
|
|
# versionName channel versionCode
|
|
# X.Y.Z (< 1.1.0) stable X*10000 + Y*100 + Z (legacy)
|
|
# X.Y.Z-beta.N beta X*1000000 + Y*10000 + Z*100 + N (N = 1..98)
|
|
# X.Y.Z (>= 1.1.0) stable X*1000000 + Y*10000 + Z*100 + 99
|
|
#
|
|
# A beta's code sits below its own stable release and above everything before
|
|
# it, so a beta install updates in place to the next beta and then to the
|
|
# stable version. Every 1.0.x keeps the legacy code it already shipped with;
|
|
# the first new-scheme code (1.1.0-beta.1 -> 1010001) is above all of them.
|
|
#
|
|
# scripts/version_info.sh print version, version_code, base_version,
|
|
# channel and prerelease as key=value lines
|
|
# (ready for $GITHUB_OUTPUT)
|
|
# scripts/version_info.sh <key> print just that value
|
|
# scripts/version_info.sh --check also fail unless the committed versionCode
|
|
# matches; the official F-Droid repo builds
|
|
# the tag as committed, so it must
|
|
set -euo pipefail
|
|
cd "$(dirname "$0")/.." # repo root
|
|
|
|
GRADLE="app/build.gradle.kts"
|
|
NAME=$(grep -oP 'versionName\s*=\s*"\K[^"]+' "$GRADLE" || true)
|
|
COMMITTED=$(grep -oP 'versionCode\s*=\s*\K[0-9]+' "$GRADLE" || true)
|
|
[ -n "$NAME" ] || { echo "No versionName in $GRADLE" >&2; exit 1; }
|
|
|
|
if [[ ! "$NAME" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)(-beta\.([0-9]+))?$ ]]; then
|
|
echo "versionName '$NAME' is neither X.Y.Z nor X.Y.Z-beta.N" >&2
|
|
exit 1
|
|
fi
|
|
MAJOR=$((10#${BASH_REMATCH[1]})); MINOR=$((10#${BASH_REMATCH[2]})); PATCH=$((10#${BASH_REMATCH[3]}))
|
|
BETA=${BASH_REMATCH[5]:+$((10#${BASH_REMATCH[5]}))}
|
|
BASE="$MAJOR.$MINOR.$PATCH"
|
|
|
|
if [ "$MINOR" -gt 99 ] || [ "$PATCH" -gt 99 ]; then
|
|
echo "versionName '$NAME': MINOR and PATCH each have room for 0-99" >&2
|
|
exit 1
|
|
fi
|
|
|
|
LEGACY=$(( MAJOR * 10000 + MINOR * 100 + PATCH ))
|
|
if [ -n "$BETA" ]; then
|
|
if [ "$LEGACY" -lt 10100 ]; then
|
|
echo "versionName '$NAME': betas start at 1.1.0; 1.0.x codes have no room for them" >&2
|
|
exit 1
|
|
fi
|
|
if [ "$BETA" -lt 1 ] || [ "$BETA" -gt 98 ]; then
|
|
echo "versionName '$NAME': beta number must be 1-98 (99 is the stable release)" >&2
|
|
exit 1
|
|
fi
|
|
CHANNEL=beta
|
|
CODE=$(( MAJOR * 1000000 + MINOR * 10000 + PATCH * 100 + BETA ))
|
|
elif [ "$LEGACY" -lt 10100 ]; then
|
|
CHANNEL=stable
|
|
CODE=$LEGACY
|
|
else
|
|
CHANNEL=stable
|
|
CODE=$(( MAJOR * 1000000 + MINOR * 10000 + PATCH * 100 + 99 ))
|
|
fi
|
|
|
|
# Betas are always pre-releases; so was everything before 1.0.0.
|
|
if [ "$CHANNEL" = beta ] || [ "$MAJOR" = 0 ]; then PRERELEASE=true; else PRERELEASE=false; fi
|
|
|
|
case "${1:-}" in
|
|
"")
|
|
printf 'version=%s\nversion_code=%s\nbase_version=%s\nchannel=%s\nprerelease=%s\n' \
|
|
"$NAME" "$CODE" "$BASE" "$CHANNEL" "$PRERELEASE"
|
|
;;
|
|
--check)
|
|
if [ "$COMMITTED" != "$CODE" ]; then
|
|
echo "ERROR: $GRADLE has versionCode = ${COMMITTED:-<none>}, but versionName '$NAME' needs $CODE." >&2
|
|
echo "Set versionCode = $CODE (see docs/RELEASING.md for the scheme)." >&2
|
|
exit 1
|
|
fi
|
|
echo "OK: versionName $NAME -> versionCode $CODE ($CHANNEL)."
|
|
;;
|
|
version) echo "$NAME" ;;
|
|
version_code) echo "$CODE" ;;
|
|
base_version) echo "$BASE" ;;
|
|
channel) echo "$CHANNEL" ;;
|
|
prerelease) echo "$PRERELEASE" ;;
|
|
*) echo "Unknown key '$1'" >&2; exit 2 ;;
|
|
esac
|