ci: publish a test APK as a pre-release for outside testers
🏗️ Build and Test JellyTau / Run Tests (push) Successful in 29m49s
🏗️ Build and Test JellyTau / Supply Chain (push) Successful in 57s
Publish Documentation / Build & publish docs to gitea-pages (push) Successful in 9m25s
Traceability Validation / Check Requirement Traces (push) Successful in 17s
🏗️ Build and Test JellyTau / Android Compile Check (push) Failing after 51s

Gitea artifacts need an account with read access to download, which makes
them useless for handing a build to someone outside the project -- the
actual reason a test APK gets built in the first place.

An optional publish input attaches the APK to a pre-release instead,
whose assets are a plain public URL on a public repo. No merge to master,
no MR, no version tag, and the tester needs no account.

Safe from a feature branch on two counts. The tag is test-<branch> rather
than v*, and only v* triggers build-release.yml, so nothing else reacts
to it. And it cannot reach existing users: the desktop updater reads a
static latest.json from the updater branch, not the release list.

Re-dispatching the same branch replaces the APK on the existing
pre-release rather than accumulating one release per attempt.
This commit is contained in:
2026-08-30 20:06:40 +02:00
parent 03c0b5cd17
commit 10d77f1380
2 changed files with 106 additions and 0 deletions
+87
View File
@@ -15,6 +15,11 @@ name: '📱 Test APK'
# Both variants install as com.dtourolle.jellytau.debug ("JellyTau Debug"), # Both variants install as com.dtourolle.jellytau.debug ("JellyTau Debug"),
# side by side with a real install and with their own data directory. Neither # side by side with a real install and with their own data directory. Neither
# needs the release signing key. # needs the release signing key.
#
# Getting the APK to somebody else: Gitea artifacts need an account with read
# access to download, so `publish: true` also attaches the APK to a pre-release
# whose assets are a plain public URL. That is the only way an outside tester
# gets the file without being given an account.
on: on:
workflow_dispatch: workflow_dispatch:
@@ -41,6 +46,11 @@ on:
- aarch64 - aarch64
- armv7 - armv7
- x86_64 - x86_64
publish:
description: 'Also publish as a pre-release, for testers with no Gitea account'
required: false
default: false
type: boolean
concurrency: concurrency:
# One test build at a time; a newer dispatch supersedes an in-flight one. # One test build at a time; a newer dispatch supersedes an in-flight one.
@@ -171,6 +181,83 @@ jobs:
ls -lah dist/test-apk/ ls -lah dist/test-apk/
# Deliberately NOT tagged `v*`: that pattern triggers build-release.yml,
# which would run the whole three-platform release matrix and publish a
# real release off a feature branch. The tag here is derived from the
# branch name and carries no version, so nothing else reacts to it.
#
# This also cannot reach existing users. The desktop updater reads a
# static latest.json from the `updater` branch, not the release list, so a
# pre-release published here is invisible to anyone without the link.
- name: Publish as a pre-release
if: ${{ inputs.publish }}
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
AUTO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -e
command -v jq >/dev/null || { echo "❌ jq is required on the runner"; exit 1; }
API="${GITHUB_SERVER_URL}/api/v1"
REPO="${GITHUB_REPOSITORY}"
TOKEN="${GITEA_TOKEN:-$AUTO_TOKEN}"
BRANCH="${GITHUB_REF#refs/heads/}"
TAG="test-$(echo "$BRANCH" | tr '/' '-')"
# printf, not a heredoc: inside a YAML block scalar every line is
# indented, and a heredoc terminator has to sit at column 0.
BODY=$(printf '%s\n' \
"Test build of \`$BRANCH\` at \`${GITHUB_SHA::8}\` — **not a release**." \
"" \
"Installs as **JellyTau Debug** (\`com.dtourolle.jellytau.debug\`), alongside a" \
"normal install and with its own separate data. Uninstalling it does not touch" \
"the real app." \
"" \
"Variant: \`${{ inputs.variant }}\` · ABI: \`${{ inputs.abi }}\`" \
"" \
"Android will warn about installing from an unknown source; that is expected" \
"for a build signed with a debug key rather than the store key.")
PAYLOAD=$(jq -n \
--arg tag "$TAG" \
--arg name "Test build: $BRANCH" \
--arg body "$BODY" \
--arg target "$GITHUB_SHA" \
'{tag_name:$tag, target_commitish:$target, name:$name, body:$body, draft:false, prerelease:true}')
HTTP=$(curl -sS -o resp.json -w '%{http_code}' -X POST "$API/repos/$REPO/releases" \
-H "Authorization: token $TOKEN" -H "Content-Type: application/json" -d "$PAYLOAD")
if [ "$HTTP" = "201" ]; then
RELEASE_ID=$(jq -r '.id' resp.json)
elif [ "$HTTP" = "409" ]; then
# Re-dispatching for the same branch replaces the previous APK rather
# than accumulating one release per attempt.
echo "️ Pre-release $TAG exists; reusing it"
RELEASE_ID=$(curl -fsS "$API/repos/$REPO/releases/tags/$TAG" \
-H "Authorization: token $TOKEN" | jq -r '.id')
for id in $(curl -fsS "$API/repos/$REPO/releases/$RELEASE_ID/assets" \
-H "Authorization: token $TOKEN" | jq -r '.[].id'); do
curl -fsS -X DELETE "$API/repos/$REPO/releases/$RELEASE_ID/assets/$id" \
-H "Authorization: token $TOKEN" >/dev/null
done
else
echo "❌ Failed to create pre-release (HTTP $HTTP):"; cat resp.json; exit 1
fi
for f in dist/test-apk/*.apk; do
echo "⬆️ $(basename "$f")"
curl -fsS -X POST \
"$API/repos/$REPO/releases/$RELEASE_ID/assets?name=$(basename "$f")" \
-H "Authorization: token $TOKEN" -F "attachment=@$f" >/dev/null
done
{
echo ""
echo "**Published:** ${GITHUB_SERVER_URL}/${REPO}/releases/tag/${TAG}"
echo ""
echo "Public link — no Gitea account needed. Delete the release when testing is done."
} >> "$GITHUB_STEP_SUMMARY"
- name: Upload APK - name: Upload APK
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3
with: with:
+19
View File
@@ -110,6 +110,25 @@ two other projects, so building on every feature-branch commit would starve
them. The APK lands as the `jellytau-test-apk` artifact (7-day retention), named them. The APK lands as the `jellytau-test-apk` artifact (7-day retention), named
for the branch and short SHA, with its size and SHA256 in the run summary. for the branch and short SHA, with its size and SHA256 in the run summary.
#### Sending a build to an outside tester
Gitea **artifacts require an account** with read access to download, so an
artifact is no use to someone outside the project. Tick **`publish`** on the
dispatch and the APK is also attached to a **pre-release**, whose assets are a
plain public URL on a public repo — no account, no MR, no merge to `master`.
Two things make that safe to do from a feature branch:
- The tag is `test-<branch>`, **not** `v*`. Only `v*` triggers
`build-release.yml`, so nothing else reacts to it.
- It cannot reach existing users. The desktop updater reads a static
`latest.json` from the `updater` branch, not the release list, so a
pre-release published this way is invisible to anyone without the link.
Re-dispatching for the same branch replaces the APK on the existing
pre-release rather than piling up one release per attempt. Delete the release
when testing is over.
### Key Files ### Key Files
Player-related Kotlin files: Player-related Kotlin files: