feat(gitea): attach build artifacts to Gitea releases
Android Release / Build signed release APK (push) Successful in 37m54s
Android Release / Build signed release APK (push) Successful in 37m54s
The Android release workflow now creates or updates a Gitea release and attaches the APK and its SHA256 to it. A GITEA_TOKEN with releases: write is required for uploads. The README now documents the Gitea release flow and the required permissions. - Enforces that releases run only on a tag and matches the app version. - Replaces or updates release assets to match tag names. - Requires GITEA_TOKEN with releases: write for uploads.
This commit is contained in:
@@ -11,6 +11,9 @@ jobs:
|
||||
name: Build signed release APK
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
code: read
|
||||
releases: write
|
||||
env:
|
||||
ANDROID_COMPILE_SDK: "36"
|
||||
ANDROID_BUILD_TOOLS: "36.0.0"
|
||||
@@ -19,6 +22,7 @@ jobs:
|
||||
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
|
||||
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
|
||||
ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
steps:
|
||||
- name: Check out repository
|
||||
@@ -64,8 +68,11 @@ jobs:
|
||||
run: npm ci
|
||||
|
||||
- name: Check release tag and app version
|
||||
if: gitea.ref_type == 'tag'
|
||||
run: |
|
||||
if [ "${GITHUB_REF_TYPE}" != "tag" ]; then
|
||||
echo "Release builds must run on a tag such as v0.1.0." >&2
|
||||
exit 1
|
||||
fi
|
||||
APP_VERSION="$(node -p "require('./src-tauri/tauri.conf.json').version")"
|
||||
if [ "${GITHUB_REF_NAME}" != "v${APP_VERSION}" ]; then
|
||||
echo "Tag ${GITHUB_REF_NAME} does not match app version v${APP_VERSION}." >&2
|
||||
@@ -78,7 +85,8 @@ jobs:
|
||||
ANDROID_KEYSTORE_BASE64 \
|
||||
ANDROID_KEYSTORE_PASSWORD \
|
||||
ANDROID_KEY_ALIAS \
|
||||
ANDROID_KEY_PASSWORD
|
||||
ANDROID_KEY_PASSWORD \
|
||||
GITEA_RELEASE_TOKEN
|
||||
do
|
||||
if [ -z "${!SECRET_NAME:-}" ]; then
|
||||
echo "Missing Gitea Actions secret: ${SECRET_NAME}" >&2
|
||||
@@ -118,11 +126,73 @@ jobs:
|
||||
rm "${ALIGNED_APK}"
|
||||
(cd "${RELEASE_DIRECTORY}" && sha256sum WallpaperFlow-release.apk > WallpaperFlow-release.apk.sha256)
|
||||
|
||||
- name: Upload release APK
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: WallpaperFlow-${{ gitea.ref_name }}-android
|
||||
path: |
|
||||
release/WallpaperFlow-release.apk
|
||||
- name: Attach APK to Gitea release
|
||||
run: |
|
||||
API_ROOT="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}"
|
||||
RELEASE_JSON="${RUNNER_TEMP}/wallpaperflow-release.json"
|
||||
CREATE_JSON="${RUNNER_TEMP}/wallpaperflow-create-release.json"
|
||||
ASSETS_JSON="${RUNNER_TEMP}/wallpaperflow-release-assets.json"
|
||||
|
||||
STATUS="$(curl --silent --show-error \
|
||||
--output "${RELEASE_JSON}" \
|
||||
--write-out '%{http_code}' \
|
||||
--header "Authorization: token ${GITEA_RELEASE_TOKEN}" \
|
||||
"${API_ROOT}/releases/tags/${GITHUB_REF_NAME}")"
|
||||
|
||||
if [ "${STATUS}" = "404" ]; then
|
||||
node -e '
|
||||
process.stdout.write(JSON.stringify({
|
||||
tag_name: process.env.GITHUB_REF_NAME,
|
||||
name: `WallpaperFlow ${process.env.GITHUB_REF_NAME}`,
|
||||
body: "Automatisch erstelltes Android-Release.",
|
||||
draft: false,
|
||||
prerelease: false
|
||||
}))
|
||||
' > "${CREATE_JSON}"
|
||||
curl --fail --silent --show-error \
|
||||
--request POST \
|
||||
--header "Authorization: token ${GITEA_RELEASE_TOKEN}" \
|
||||
--header "Content-Type: application/json" \
|
||||
--data-binary "@${CREATE_JSON}" \
|
||||
--output "${RELEASE_JSON}" \
|
||||
"${API_ROOT}/releases"
|
||||
elif [ "${STATUS}" != "200" ]; then
|
||||
echo "Could not read Gitea release for ${GITHUB_REF_NAME} (HTTP ${STATUS})." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_ID="$(node -e '
|
||||
const release = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
||||
if (!release.id) process.exit(1);
|
||||
process.stdout.write(String(release.id));
|
||||
' "${RELEASE_JSON}")"
|
||||
|
||||
curl --fail --silent --show-error \
|
||||
--header "Authorization: token ${GITEA_RELEASE_TOKEN}" \
|
||||
--output "${ASSETS_JSON}" \
|
||||
"${API_ROOT}/releases/${RELEASE_ID}/assets"
|
||||
|
||||
for FILE in \
|
||||
release/WallpaperFlow-release.apk \
|
||||
release/WallpaperFlow-release.apk.sha256
|
||||
if-no-files-found: error
|
||||
do
|
||||
ASSET_NAME="$(basename "${FILE}")"
|
||||
ASSET_ID="$(ASSET_NAME="${ASSET_NAME}" node -e '
|
||||
const assets = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"));
|
||||
const asset = assets.find(item => item.name === process.env.ASSET_NAME);
|
||||
if (asset) process.stdout.write(String(asset.id));
|
||||
' "${ASSETS_JSON}")"
|
||||
|
||||
if [ -n "${ASSET_ID}" ]; then
|
||||
curl --fail --silent --show-error \
|
||||
--request DELETE \
|
||||
--header "Authorization: token ${GITEA_RELEASE_TOKEN}" \
|
||||
"${API_ROOT}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
|
||||
fi
|
||||
|
||||
curl --fail --silent --show-error \
|
||||
--request POST \
|
||||
--header "Authorization: token ${GITEA_RELEASE_TOKEN}" \
|
||||
--form "attachment=@${FILE}" \
|
||||
"${API_ROOT}/releases/${RELEASE_ID}/assets" >/dev/null
|
||||
done
|
||||
|
||||
@@ -68,10 +68,17 @@ Den Keystore-Inhalt für das Secret erzeugt man unter Linux mit:
|
||||
base64 -w 0 /sicherer/pfad/wallpaperflow-release.jks
|
||||
```
|
||||
|
||||
Nach erfolgreichem Lauf stehen `WallpaperFlow-release.apk` und die zugehörige
|
||||
SHA-256-Prüfsumme als Artefakt des Workflows bereit. Der Keystore darf nicht in
|
||||
das Repository eingecheckt werden und muss dauerhaft gesichert bleiben, da
|
||||
spätere Updates mit demselben Schlüssel signiert werden müssen.
|
||||
Nach erfolgreichem Lauf erstellt die Pipeline ein Gitea-Release für den Tag
|
||||
beziehungsweise verwendet ein bereits vorhandenes Release. Die Dateien
|
||||
`WallpaperFlow-release.apk` und `WallpaperFlow-release.apk.sha256` werden direkt
|
||||
an dieses Release angehängt. Bei einem erneuten Lauf für denselben Tag werden
|
||||
vorhandene Anhänge mit diesen Namen ersetzt. Dafür muss der integrierte
|
||||
`GITEA_TOKEN` Schreibzugriff auf Releases besitzen; die Pipeline fordert die
|
||||
Berechtigung `releases: write` selbst an.
|
||||
|
||||
Der Keystore darf nicht in das Repository eingecheckt werden und muss dauerhaft
|
||||
gesichert bleiben, da spätere Updates mit demselben Schlüssel signiert werden
|
||||
müssen.
|
||||
|
||||
Voraussetzung ist ein aktiver Gitea-Actions-Runner mit dem Label
|
||||
`ubuntu-latest`, Netzwerkzugriff auf npm, Rust und die Android-SDK-Server sowie
|
||||
|
||||
Reference in New Issue
Block a user