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 1m26s
### What this changes - New `scripts/release_gate.sh`, used by the `detect` jobs of both `release.yaml` and `beta.yaml`, decides whether the committed version still needs publishing. Tags are read by exact name via `git ls-remote` instead of Codeberg's `git/refs/tags/<name>` API. - A beta counts as done only once its Codeberg pre-release carries the APK, so a publish that failed part-way is redone by the next push of the branch. - A beta is refused unless it is newer than the latest stable tag (previously only an exact `vX.Y.Z` tag was checked). - `publish_codeberg_release.sh` fails a pre-release when `CODEBERG_RELEASE_TOKEN` is missing (stable still skips), fails on any asset upload that doesn't return 201, and no longer aborts when the asset listing returns an error. - `version_info.sh` rejects leading zeros (`1.1.0-beta.01` would have shared `beta.1`'s versionCode under a different tag). - `beta.yaml` header and `docs/RELEASING.md` updated to match. ### Why Codeberg's `git/refs/tags/<name>` matches by prefix: asking for `v1.1.0` returns 200 because `v1.1.0-beta.1` exists. Merging 1.1.0 into `main` would have logged "tag already exists" and shipped nothing while the run stayed green, and `1.1.0-beta.2` would have been refused as "already shipped stable". `release/v1.1.0` needs `main` merged in after this lands, since `beta.yaml` runs from the pushed branch's files. ### Also in here `gradle/gradle-daemon-jvm.properties` now points at JetBrains' own download URLs for JBR 21.0.11 instead of foojay. foojay dropped JetBrains 21 from its index, so the pinned package ids return 400 and CI couldn't provision the daemon JVM (unrelated to the release change, but it blocks every PR until fixed). ### Checklist - [x] No `values-*/strings.xml` touched - [x] No `versionName` / `versionCode` bump - [x] `CHANGELOG.md` not updated: release infrastructure, not a user-visible change Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de> Reviewed-on: https://codeberg.org/jlmakiola/agendula/pulls/40
177 lines
6.1 KiB
YAML
177 lines
6.1 KiB
YAML
name: Beta — Codeberg pre-release
|
|
|
|
# A beta is cut by pushing a release branch whose committed versionName is
|
|
# X.Y.Z-beta.N (see docs/RELEASING.md). Same model as release.yaml: the
|
|
# committed version is the trigger and the vX.Y.Z-beta.N tag is an output. If
|
|
# its Codeberg pre-release doesn't carry the APK yet, this runs the unit tests, builds and
|
|
# signs the APK with the app key, records a Gitea pre-release (with the R8
|
|
# mapping) and publishes a Codeberg pre-release with the APK + SHA-256.
|
|
#
|
|
# Deliberately nothing else. A beta never reaches the F-Droid repos or Play:
|
|
# Obtainium hides pre-releases unless a user opts in, the official F-Droid
|
|
# recipe only picks up `^v[0-9.]+$` tags, and Codeberg's "latest release"
|
|
# skips pre-releases. Pushes of a release branch carrying a stable version
|
|
# (the usual state) fall through `detect` and do nothing.
|
|
#
|
|
# Lives in .gitea/workflows next to release.yaml for the same reason: it needs
|
|
# the app signing key, which only the self-hosted Gitea instance holds.
|
|
on:
|
|
push:
|
|
branches: ['release/**']
|
|
|
|
concurrency:
|
|
group: beta
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
detect:
|
|
# Gitea only; see the same guard in release.yaml.
|
|
if: github.repository_owner == 'makiolaj'
|
|
runs-on: docker
|
|
outputs:
|
|
is_beta: ${{ steps.v.outputs.is_beta }}
|
|
version: ${{ steps.v.outputs.version }}
|
|
version_code: ${{ steps.v.outputs.version_code }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Resolve version and whether it still needs publishing
|
|
id: v
|
|
run: |
|
|
set -e
|
|
INFO=$(bash scripts/version_info.sh)
|
|
echo "$INFO"
|
|
echo "$INFO" >> "$GITHUB_OUTPUT"
|
|
if [ "$(bash scripts/version_info.sh channel)" != beta ]; then
|
|
echo "Not a beta — nothing to do."
|
|
echo "is_beta=false" >> "$GITHUB_OUTPUT"
|
|
exit 0
|
|
fi
|
|
# Done only once its Codeberg pre-release carries the APK, so a failed
|
|
# publish is redone by the next push; refused unless newer than the
|
|
# latest stable release.
|
|
GATE=$(bash scripts/release_gate.sh)
|
|
echo "is_beta=${GATE#cut=}" >> "$GITHUB_OUTPUT"
|
|
|
|
beta:
|
|
needs: detect
|
|
if: needs.detect.outputs.is_beta == 'true'
|
|
runs-on: docker
|
|
env:
|
|
ANDROID_HOME: /opt/android-sdk
|
|
ANDROID_SDK_ROOT: /opt/android-sdk
|
|
VERSION: ${{ needs.detect.outputs.version }}
|
|
VERSION_CODE: ${{ needs.detect.outputs.version_code }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: recursive
|
|
|
|
- name: Setup Java
|
|
uses: actions/setup-java@v4
|
|
with:
|
|
distribution: 'zulu'
|
|
java-version: '17'
|
|
|
|
- name: Setup Android SDK
|
|
uses: android-actions/setup-android@v3
|
|
with:
|
|
packages: ''
|
|
|
|
- name: Setup Android SDK cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: /opt/android-sdk
|
|
key: ${{ runner.os }}-android-sdk-37-36.0.0
|
|
|
|
- name: Install Android SDK packages
|
|
run: |
|
|
yes | sdkmanager --licenses >/dev/null || true
|
|
sdkmanager \
|
|
"platform-tools" \
|
|
"platforms;android-37.0" \
|
|
"build-tools;36.0.0"
|
|
|
|
- name: Setup Gradle cache
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: |
|
|
~/.gradle/caches
|
|
~/.gradle/wrapper
|
|
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle/libs.versions.toml') }}
|
|
restore-keys: |
|
|
${{ runner.os }}-gradle-
|
|
|
|
- name: Install jq
|
|
run: |
|
|
set -e
|
|
SUDO=""
|
|
if command -v sudo >/dev/null 2>&1; then SUDO="sudo"; fi
|
|
if command -v apt-get >/dev/null 2>&1; then
|
|
$SUDO apt-get update
|
|
$SUDO apt-get install -y jq
|
|
elif command -v apk >/dev/null 2>&1; then
|
|
$SUDO apk add --no-cache jq
|
|
fi
|
|
|
|
- name: Grant execute permission for gradlew
|
|
run: chmod +x ./gradlew
|
|
|
|
- name: Pin versionCode to versionName
|
|
run: |
|
|
set -e
|
|
sed -i "s/versionCode = .*/versionCode = $VERSION_CODE/" app/build.gradle.kts
|
|
grep -E 'versionName|versionCode' app/build.gradle.kts
|
|
|
|
- name: Unit tests
|
|
run: ./gradlew testDebugUnitTest
|
|
|
|
# The real app key, same as a stable release: a beta has to update in
|
|
# place to the next beta and to the stable version.
|
|
- name: Setup Android Keystore
|
|
env:
|
|
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
|
|
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
|
|
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
|
|
run: |
|
|
mkdir -p app
|
|
echo "$KEYSTORE_BASE64" | base64 --decode > app/upload-keystore.jks
|
|
cat > key.properties <<EOF
|
|
storePassword=$KEY_PASSWORD
|
|
keyPassword=$KEY_PASSWORD
|
|
keyAlias=$KEY_ALIAS
|
|
storeFile=upload-keystore.jks
|
|
EOF
|
|
|
|
- name: Build release APK
|
|
run: ./gradlew assembleRelease
|
|
|
|
# Notes = a `## [X.Y.Z-beta.N]` section if there is one, else
|
|
# `## [Unreleased]`. Gitea creates the tag at this commit.
|
|
- name: Create tag + Gitea pre-release
|
|
env:
|
|
TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
API: ${{ github.server_url }}/api/v1/repos/${{ github.repository }}
|
|
SHA: ${{ github.sha }}
|
|
run: |
|
|
set -e
|
|
bash scripts/release_notes.sh "$VERSION" > release-notes.md
|
|
cat release-notes.md
|
|
TAG="v$VERSION" PRERELEASE=true NOTES_FILE=release-notes.md \
|
|
MAPPING=app/build/outputs/mapping/release/mapping.txt \
|
|
bash scripts/publish_gitea_release.sh
|
|
|
|
# The point of the whole workflow, so NOT continue-on-error.
|
|
- name: Publish pre-release to Codeberg
|
|
env:
|
|
TOKEN: ${{ secrets.CODEBERG_RELEASE_TOKEN }}
|
|
API: https://codeberg.org/api/v1/repos/jlmakiola/agendula
|
|
SHA: ${{ github.sha }}
|
|
run: |
|
|
set -e
|
|
TAG="v$VERSION" PRERELEASE=true NOTES_FILE=release-notes.md \
|
|
APK=app/build/outputs/apk/release/app-release.apk \
|
|
bash scripts/publish_codeberg_release.sh
|