Files
2026-05-24 23:17:47 +03:00

304 lines
9.6 KiB
YAML
Executable File

name: Build WDTT Release
on:
push:
branches:
- "**"
workflow_dispatch:
jobs:
build-release:
name: Build release APK
runs-on: ubuntu-latest
permissions:
contents: read
env:
ANDROID_MIN_API: "29"
ANDROID_COMPILE_SDK: "35"
ANDROID_BUILD_TOOLS: "35.0.0"
ANDROID_NDK_VERSION: "27.2.12479018"
SERVER_BINARY_NAME: "server"
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Java 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"
- name: Set up Android SDK
uses: android-actions/setup-android@v3
- name: Install Android SDK packages
shell: bash
run: |
set -euo pipefail
sdkmanager \
"platforms;android-${ANDROID_COMPILE_SDK}" \
"build-tools;${ANDROID_BUILD_TOOLS}" \
"ndk;${ANDROID_NDK_VERSION}"
echo "ANDROID_NDK_HOME=${ANDROID_SDK_ROOT}/ndk/${ANDROID_NDK_VERSION}" >> "$GITHUB_ENV"
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.26.x"
cache: true
cache-dependency-path: |
go.mod
go_client/go.mod
- name: Generate Go sums
shell: bash
run: |
set -euo pipefail
echo "== Root Go module =="
go mod tidy
echo "== Go client module =="
cd go_client
go mod tidy
- name: Build Linux server binaries
shell: bash
run: |
set -euo pipefail
mkdir -p build/server
echo "== Build server linux/amd64 =="
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build \
-trimpath \
-ldflags="-s -w -checklinkname=0" \
-o build/server/wdtt-server-linux-amd64 \
./server.go
echo "== Build server linux/arm64 =="
CGO_ENABLED=0 GOOS=linux GOARCH=arm64 \
go build \
-trimpath \
-ldflags="-s -w -checklinkname=0" \
-o build/server/wdtt-server-linux-arm64 \
./server.go
chmod +x build/server/wdtt-server-linux-amd64
chmod +x build/server/wdtt-server-linux-arm64
- name: Put server binary into Android assets
shell: bash
run: |
set -euo pipefail
mkdir -p app/src/main/assets
# Android deploy code expects this exact asset name.
cp build/server/wdtt-server-linux-amd64 app/src/main/assets/${SERVER_BINARY_NAME}
chmod +x app/src/main/assets/${SERVER_BINARY_NAME}
echo "Server asset:"
ls -lh app/src/main/assets/${SERVER_BINARY_NAME}
- name: Build Android Go client libraries
shell: bash
run: |
set -euo pipefail
NDK_ROOT="${ANDROID_NDK_HOME}"
TOOLCHAIN="$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin"
if [ ! -d "$TOOLCHAIN" ]; then
echo "Android NDK toolchain not found: $TOOLCHAIN"
exit 1
fi
echo "Using NDK: $NDK_ROOT"
echo "Using toolchain: $TOOLCHAIN"
mkdir -p app/src/main/jniLibs/arm64-v8a
mkdir -p app/src/main/jniLibs/armeabi-v7a
mkdir -p app/src/main/jniLibs/x86_64
mkdir -p build/go-client
cd go_client
echo "== Build libclient.so for arm64-v8a =="
CGO_ENABLED=1 \
GOOS=android \
GOARCH=arm64 \
CC="$TOOLCHAIN/aarch64-linux-android${ANDROID_MIN_API}-clang" \
go build \
-buildmode=c-shared \
-trimpath \
-ldflags="-s -w -checklinkname=0" \
-o ../app/src/main/jniLibs/arm64-v8a/libclient.so \
.
cp ../app/src/main/jniLibs/arm64-v8a/libclient.so \
../build/go-client/libclient-arm64-v8a.so
echo "== Build libclient.so for armeabi-v7a =="
CGO_ENABLED=1 \
GOOS=android \
GOARCH=arm \
GOARM=7 \
CC="$TOOLCHAIN/armv7a-linux-androideabi${ANDROID_MIN_API}-clang" \
go build \
-buildmode=c-shared \
-trimpath \
-ldflags="-s -w -checklinkname=0" \
-o ../app/src/main/jniLibs/armeabi-v7a/libclient.so \
.
cp ../app/src/main/jniLibs/armeabi-v7a/libclient.so \
../build/go-client/libclient-armeabi-v7a.so
echo "== Build libclient.so for x86_64 =="
CGO_ENABLED=1 \
GOOS=android \
GOARCH=amd64 \
CC="$TOOLCHAIN/x86_64-linux-android${ANDROID_MIN_API}-clang" \
go build \
-buildmode=c-shared \
-trimpath \
-ldflags="-s -w -checklinkname=0" \
-o ../app/src/main/jniLibs/x86_64/libclient.so \
.
cp ../app/src/main/jniLibs/x86_64/libclient.so \
../build/go-client/libclient-x86_64.so
cd ..
echo "Built JNI libraries:"
find app/src/main/jniLibs -type f -name "libclient.so" -exec ls -lh {} \;
- name: Make Gradle wrapper executable
shell: bash
run: chmod +x ./gradlew
- name: Generate temporary release keystore
shell: bash
run: |
set -euo pipefail
KEYSTORE_PASSWORD="wdtt_temp_release_password"
KEY_PASSWORD="$KEYSTORE_PASSWORD"
KEY_ALIAS="wdtt-release"
rm -f release.keystore local.properties signing.env
keytool -genkeypair -v -keystore release.keystore -storetype PKCS12 -storepass "$KEYSTORE_PASSWORD" -keypass "$KEY_PASSWORD" -alias "$KEY_ALIAS" -keyalg RSA -keysize 4096 -validity 10000 -dname "CN=WDTT,O=WDTT,C=LV"
{
echo "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD"
echo "KEY_PASSWORD=$KEY_PASSWORD"
echo "KEY_ALIAS=$KEY_ALIAS"
} > signing.env
echo "Generated temporary release keystore"
ls -lh release.keystore
- name: Build Android release APK
shell: bash
run: |
set -euo pipefail
# No local.properties is created here, so Gradle produces unsigned release APKs.
# The workflow signs them manually in the next step using apksigner.
./gradlew clean :app:assembleRelease --stacktrace
- name: Sign release APKs manually
shell: bash
run: |
set -euo pipefail
source signing.env
BUILD_TOOLS="$(find "$ANDROID_HOME/build-tools" -mindepth 1 -maxdepth 1 -type d | sort -V | tail -n 1)"
ZIPALIGN="$BUILD_TOOLS/zipalign"
APKSIGNER="$BUILD_TOOLS/apksigner"
echo "Using zipalign: $ZIPALIGN"
echo "Using apksigner: $APKSIGNER"
mkdir -p build/signed-apk
shopt -s nullglob
unsigned_apks=(app/build/outputs/apk/release/*-unsigned.apk)
if [ ${#unsigned_apks[@]} -eq 0 ]; then
echo "No unsigned release APKs found"
echo "Available APK outputs:"
find app/build/outputs/apk -type f -name "*.apk" -print || true
exit 1
fi
for apk in "${unsigned_apks[@]}"; do
name="$(basename "$apk" -unsigned.apk)"
aligned="build/signed-apk/${name}-aligned.apk"
signed="build/signed-apk/${name}-signed.apk"
echo "== Align $apk =="
"$ZIPALIGN" -p -f 4 "$apk" "$aligned"
echo "== Sign $aligned =="
"$APKSIGNER" sign --ks release.keystore --ks-key-alias "$KEY_ALIAS" --ks-pass "pass:$KEYSTORE_PASSWORD" --key-pass "pass:$KEY_PASSWORD" --v1-signing-enabled true --v2-signing-enabled true --v3-signing-enabled true --v4-signing-enabled false --out "$signed" "$aligned"
echo "== Verify $signed =="
"$APKSIGNER" verify --verbose --print-certs "$signed"
done
echo "Signed APKs:"
ls -lh build/signed-apk/*-signed.apk
- name: Collect build outputs
shell: bash
run: |
set -euo pipefail
mkdir -p build/artifacts/apk
mkdir -p build/artifacts/server
mkdir -p build/artifacts/go-client
echo "== Signed APK outputs =="
find build/signed-apk -type f -name "*-signed.apk" -print -exec ls -lh {} \;
cp build/signed-apk/*-signed.apk build/artifacts/apk/
cp build/server/* build/artifacts/server/
cp build/go-client/* build/artifacts/go-client/
echo "== Final artifacts =="
find build/artifacts -type f -exec ls -lh {} \;
- name: Upload release APK artifact
uses: actions/upload-artifact@v4
with:
name: WDTT-release-apk
path: build/artifacts/apk/*.apk
if-no-files-found: error
retention-days: 14
- name: Upload server binaries artifact
uses: actions/upload-artifact@v4
with:
name: WDTT-server-binaries
path: build/artifacts/server/*
if-no-files-found: error
retention-days: 14
- name: Upload Go client libraries artifact
uses: actions/upload-artifact@v4
with:
name: WDTT-go-client-libraries
path: build/artifacts/go-client/*
if-no-files-found: error
retention-days: 14