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
77 lines
2.9 KiB
Bash
Executable File
77 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Create (or update) the release for TAG on the Gitea build instance, the
|
|
# changelog of record there, and attach the R8 mapping. Shared by
|
|
# .gitea/workflows/release.yaml and beta.yaml.
|
|
#
|
|
# Creating it with target_commitish makes Gitea create the tag at SHA, so the
|
|
# tag only ever marks a fully-shipped version. Upsert, so re-runs are safe.
|
|
#
|
|
# Env:
|
|
# TOKEN, API Gitea token and .../api/v1/repos/<owner>/<repo>
|
|
# TAG, SHA vX.Y.Z[-beta.N] and the commit it marks
|
|
# PRERELEASE true | false
|
|
# NOTES_FILE release notes (scripts/release_notes.sh)
|
|
# MAPPING optional path to R8's mapping.txt
|
|
set -euo pipefail
|
|
: "${TOKEN:?}" "${API:?}" "${TAG:?}" "${SHA:?}" "${PRERELEASE:?}" "${NOTES_FILE:?}"
|
|
|
|
WORK=$(mktemp -d)
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
python3 - "$TAG" "$SHA" "$PRERELEASE" "$NOTES_FILE" <<'PY' > "$WORK/payload.json"
|
|
import json, sys
|
|
tag, sha, pre, notes = sys.argv[1:5]
|
|
print(json.dumps({
|
|
"tag_name": tag,
|
|
"target_commitish": sha,
|
|
"name": tag,
|
|
"body": open(notes).read(),
|
|
"draft": False,
|
|
"prerelease": pre == "true",
|
|
}))
|
|
PY
|
|
|
|
# PATCH if a release for the tag already exists, else POST a new one (which
|
|
# also creates the tag at target_commitish).
|
|
ID=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/tags/$TAG" | jq -r '.id // empty' 2>/dev/null || true)
|
|
if [ -n "$ID" ]; then
|
|
CODE=$(curl -s -o "$WORK/response.json" -w '%{http_code}' -X PATCH \
|
|
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
|
-d @"$WORK/payload.json" "$API/releases/$ID")
|
|
OK=200
|
|
else
|
|
CODE=$(curl -s -o "$WORK/response.json" -w '%{http_code}' -X POST \
|
|
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
|
-d @"$WORK/payload.json" "$API/releases")
|
|
OK=201
|
|
fi
|
|
cat "$WORK/response.json"; echo
|
|
if [ "$CODE" != "$OK" ]; then
|
|
echo "Gitea release upsert failed with HTTP $CODE (expected $OK)" >&2
|
|
exit 1
|
|
fi
|
|
ID=$(jq -r '.id' "$WORK/response.json")
|
|
echo "Created/updated Gitea release $TAG at $SHA"
|
|
|
|
# The R8 mapping keeps user crash stacktraces deobfuscatable. It's not an APK,
|
|
# so it fits the no-binaries rule for this release. Best-effort: never fail a
|
|
# release over it.
|
|
attach_mapping() {
|
|
local asset="mapping-${TAG#v}.txt.gz" old
|
|
gzip -c "$MAPPING" > "$WORK/$asset"
|
|
# Replace any prior asset of the same name (re-run safe).
|
|
old=$(curl -s -H "Authorization: token $TOKEN" "$API/releases/$ID/assets" \
|
|
| jq -r --arg n "$asset" '.[] | select(.name==$n) | .id')
|
|
if [ -n "$old" ]; then
|
|
curl -s -X DELETE -H "Authorization: token $TOKEN" "$API/releases/$ID/assets/$old" >/dev/null
|
|
fi
|
|
curl -s -X POST -H "Authorization: token $TOKEN" \
|
|
-F "attachment=@$WORK/$asset" \
|
|
"$API/releases/$ID/assets?name=$asset" -o /dev/null -w "asset $asset HTTP %{http_code}\n"
|
|
}
|
|
if [ -z "${MAPPING:-}" ] || [ ! -f "$MAPPING" ]; then
|
|
echo "No mapping.txt (R8 off?) — skipping."
|
|
else
|
|
attach_mapping || echo "warning: could not attach the R8 mapping to $TAG" >&2
|
|
fi
|