Files
wirevpn/.github/workflows/release.yml
T

173 lines
6.9 KiB
YAML

# Builds the signed release APK and F-Droid v2 artifacts as soon as a new
# release is created, and attaches everything to that release.
#
# Written for Gitea Actions (GitHub-Actions-compatible) — the repo lives on
# https://git.obahan.xyz/frank/wirevpn. If release-attachment storage is
# unavailable on the server, outputs are also published to the `artifacts`
# branch (tag-name addressed via commit message).
#
# Required repository secrets:
# KEYSTORE_FILE base64-encoded release signing keystore (.jks)
# KEYSTORE_PASSWORD keystore password
# KEY_ALIAS key alias
# KEY_PASSWORD key password
#
# Requires a registered Actions runner on the Gitea instance that can run
# docker containers with the Android SDK (gitea/act image, docker driver).
name: release
on:
release:
types: [published, created]
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
env:
ANDROID_NDK_VERSION: "28.2.13676358"
ANDROID_API_LEVEL: "36"
GRADLE_USER_HOME: ${{ github.workspace }}/.gradle
jobs:
build:
runs-on: self-hosted
timeout-minutes: 90
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
- name: Ensure Android SDK (platform, build-tools, NDK)
run: |
set -e
if [ -z "${ANDROID_HOME:-}" ] && [ -d /usr/lib/android-sdk ]; then
export ANDROID_HOME=/usr/lib/android-sdk
fi
if [ -z "${ANDROID_HOME:-}" ]; then
echo "ANDROID_HOME not set; installing SDK"
export ANDROID_HOME=$HOME/android-sdk
mkdir -p "$ANDROID_HOME/cmdline-tools"
curl -fsSL https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -o ct.zip
(cd "$ANDROID_HOME/cmdline-tools" && unzip -q ../../ct.zip && mv cmdline-tools latest && rm -rf latest/latest)
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" --licenses >/dev/null
fi
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --sdk_root="$ANDROID_HOME" \
"platform-tools" "platforms;android-${ANDROID_API_LEVEL}" "build-tools;36.0.0" "ndk;${ANDROID_NDK_VERSION}"
echo "sdk.dir=$ANDROID_HOME" > local.properties
- name: Ensure build prerequisites (patch)
run: |
set -e
if ! command -v patch >/dev/null 2>&1; then
echo "patch not found; using vendored shim"
mkdir -p "$HOME/bin"
cp scripts/patch-shim.py "$HOME/bin/patch"
chmod +x "$HOME/bin/patch"
echo "$HOME/bin" >> "$GITHUB_PATH"
echo "patch shim ready (vendored)"
else
echo "patch present on runner"
fi
- name: Decode signing keystore
run: |
mkdir -p "$HOME/keystore"
echo "$KEYSTORE_FILE" | base64 -d > "$HOME/keystore/wirevpn-release.jks"
env:
KEYSTORE_FILE: ${{ secrets.KEYSTORE_FILE }}
- name: Build signed release APK
uses: gradle/actions/setup-gradle@v4
env:
KEYSTORE_FILE: ${{ env.HOME }}/keystore/wirevpn-release.jks
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
with:
arguments: assembleRelease
- name: Collect build outputs + F-Droid metadata
run: |
set -e
APK=ui/build/outputs/apk/release/ui-release.apk
test -f "$APK"
mkdir -p dist
cp "$APK" dist/page.onram.wirevpn.apk
# F-Droid v2 metadata + signature: "256;" + base64(sha256(sha256(apk-bytes)))
export PATH="$ANDROID_HOME/build-tools/36.0.0:$PATH"
python3 scripts/fdroid_metadata.py dist/page.onram.wirevpn.apk > dist/page.onram.wirevpn.metadata
python3 -c "
import hashlib, base64
d = open('dist/page.onram.wirevpn.apk', 'rb').read()
sig = base64.b64encode(hashlib.sha256(hashlib.sha256(d).digest()).digest()).decode()
open('dist/page.onram.wirevpn.signature', 'w').write(f'256;{sig}\n')
"
echo "--- metadata ---"
cat dist/page.onram.wirevpn.metadata
echo "--- signature ---"
cat dist/page.onram.wirevpn.signature
- name: Attach artifacts to the Gitea release
env:
GITEA_API: https://git.obahan.xyz/api/v1
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN || github.token }}
REPO: frank/wirevpn
run: |
set -e
tag="${GITHUB_REF#refs/tags/}"
[ -n "$tag" ] || tag="latest"
# Find or create the release
rid=$(curl -fsSL -H "Authorization: token $GITEA_TOKEN" "$GITEA_API/repos/$REPO/releases/tags/$tag" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' 2>/dev/null || true)
if [ -z "$rid" ]; then
rid=$(curl -fsSL -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \
-d "{\"name\":\"$tag\",\"tag_name\":\"$tag\",\"target\":\"master\"}" \
"$GITEA_API/repos/$REPO/releases" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
fi
ok=0
for f in dist/page.onram.wirevpn.apk dist/page.onram.wirevpn.metadata dist/page.onram.wirevpn.signature; do
if curl -fsSL -H "Authorization: token $GITEA_TOKEN" \
-F "file=@$f" \
"$GITEA_API/repos/$REPO/releases/$rid/assets" >/dev/null; then
echo "uploaded $f"
ok=1
else
echo "attachment upload failed for $f (Gitea attachment storage broken?)"
fi
done
if [ "$ok" != "1" ]; then
echo "::warning::Could not attach release assets; falling back to artifacts branch"
fi
- name: Publish build outputs to artifacts branch (fallback + archive)
if: always()
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN || github.token }}
run: |
set -e
tag="${GITHUB_REF#refs/tags/}"
[ -n "$tag" ] || tag="latest"
mkdir -p dist-artifacts && cd dist-artifacts
cp ../dist/page.onram.wirevpn.apk ../dist/page.onram.wirevpn.metadata ../dist/page.onram.wirevpn.signature . 2>/dev/null || exit 0
git config user.name "wirevpn-ci"
git config user.email "ci@localhost"
git init -q .
git add -A
git commit -qm "build outputs for $tag"
git push -q --force "https://frank:${GITEA_TOKEN}@git.obahan.xyz/frank/wirevpn.git" HEAD:artifacts
echo "artifacts published to branch 'artifacts'"
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: fdroid-bundle
path: dist/