mirror of
git://f0xx.org/android_cast
synced 2026-07-29 08:37:37 +03:00
152 lines
5.5 KiB
Bash
Executable File
152 lines
5.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# CI pipeline entry: optional git checkout, native, gradle, OTA publish.
|
|
#
|
|
# Env:
|
|
# GRADLE_TASK assembleDebug | assembleRelease | testDebugUnitTest | …
|
|
# RUN_UNIT_TESTS 1 (default) | 0
|
|
# RUN_NATIVE 1 (default) | 0
|
|
# RUN_APK 1 (default) | 0 — set 0 for tests-only
|
|
# OTA_BASE_URL public base for v0/ota (empty = skip OTA)
|
|
# OTA_CHANNEL stable | staging | dev | nightly | custom name
|
|
# AUTO_OTA 1 to emit OTA tree under OUT_DIR
|
|
# OUT_DIR artifact root (default ./out/builds/$BUILD_ID)
|
|
# BUILD_ID build record id
|
|
# GIT_REF branch | tag | commit to checkout before build
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
cd "$ROOT"
|
|
|
|
BUILD_ID="${BUILD_ID:-local}"
|
|
OUT_DIR="${OUT_DIR:-${ROOT}/out/builds/${BUILD_ID}}"
|
|
GRADLE_TASK="${GRADLE_TASK:-assembleDebug}"
|
|
RUN_UNIT_TESTS="${RUN_UNIT_TESTS:-1}"
|
|
RUN_NATIVE="${RUN_NATIVE:-1}"
|
|
RUN_APK="${RUN_APK:-1}"
|
|
OTA_CHANNEL="${OTA_CHANNEL:-staging}"
|
|
AUTO_OTA="${AUTO_OTA:-0}"
|
|
|
|
mkdir -p "$OUT_DIR"
|
|
exec > >(tee -a "${OUT_DIR}/build.log") 2>&1
|
|
|
|
echo "==> Phase: init build_id=${BUILD_ID} channel=${OTA_CHANNEL}"
|
|
|
|
if [[ -n "${GIT_REF:-}" ]]; then
|
|
echo "==> Phase: git checkout ${GIT_REF}"
|
|
git fetch --all --tags 2>/dev/null || true
|
|
git checkout --force "$GIT_REF"
|
|
if [[ -n "${GIT_SHA:-}" ]]; then
|
|
git reset --hard "$GIT_SHA"
|
|
fi
|
|
fi
|
|
|
|
export ANDROIDCAST_ROOT="$ROOT"
|
|
export ANDROIDCAST_CCACHE="${ANDROIDCAST_CCACHE:-1}"
|
|
GRADLE_JAVA_OPT=()
|
|
if [[ -n "${JAVA_HOME:-}" ]]; then
|
|
GRADLE_JAVA_OPT=(-Dorg.gradle.java.home="${JAVA_HOME}")
|
|
fi
|
|
# shellcheck source=android-ndk.sh
|
|
source "$ROOT/scripts/android-ndk.sh"
|
|
export ANDROID_NDK_HOME="$(androidcast_find_ndk_root "$ROOT")"
|
|
export ANDROID_NDK_ROOT="$ANDROID_NDK_HOME"
|
|
if [[ -n "${ANDROID_SDK_ROOT:-}" ]]; then
|
|
LOCAL_PROPS="$ROOT/local.properties"
|
|
LOCAL_PROPS_BACKUP=""
|
|
if [[ -f "$LOCAL_PROPS" ]]; then
|
|
LOCAL_PROPS_BACKUP="$(mktemp)"
|
|
cp -f "$LOCAL_PROPS" "$LOCAL_PROPS_BACKUP"
|
|
fi
|
|
trap 'if [[ -n "${LOCAL_PROPS_BACKUP:-}" && -f "${LOCAL_PROPS_BACKUP}" ]]; then cp -f "${LOCAL_PROPS_BACKUP}" "$LOCAL_PROPS"; rm -f "${LOCAL_PROPS_BACKUP}"; else rm -f "$LOCAL_PROPS"; fi' EXIT
|
|
printf 'sdk.dir=%s\n' "${ANDROID_SDK_ROOT//\\/\\\\}" > "$LOCAL_PROPS"
|
|
fi
|
|
|
|
echo "==> Phase: third-party submodules (libvpx, opus, speex, wireguard-android)"
|
|
bash "$ROOT/scripts/init-third-party-submodules.sh"
|
|
|
|
if [[ "$RUN_NATIVE" == "1" && "$RUN_APK" == "1" ]]; then
|
|
echo "==> Phase: native codecs"
|
|
ABIS="${ANDROIDCAST_CI_ABIS:-armeabi-v7a arm64-v8a x86_64}"
|
|
rm -rf "$ROOT/build/native"
|
|
mkdir -p "$ROOT/build/native"
|
|
for abi in $ABIS; do
|
|
./scripts/build-native-codecs.sh "$abi"
|
|
done
|
|
else
|
|
echo "==> Phase: native codecs (skipped)"
|
|
fi
|
|
|
|
# Avoid host-specific CMake cache paths when running in Docker.
|
|
rm -rf "$ROOT/app/.cxx" "$ROOT/app/build/.cxx" "$ROOT/app/build/intermediates/cxx"
|
|
rm -rf "$ROOT/gradle/wireguard-tunnel/.cxx" "$ROOT/gradle/wireguard-tunnel/build" 2>/dev/null || true
|
|
|
|
WG_HEAD="$(git -C "$ROOT/third-party/wireguard-android" rev-parse --short HEAD 2>/dev/null || echo unknown)"
|
|
echo "==> Phase: wireguard-android (:tunnel) third-party/wireguard-android @ ${WG_HEAD}"
|
|
|
|
if [[ "$RUN_APK" == "1" ]]; then
|
|
echo "==> Phase: gradle :tunnel + ${GRADLE_TASK}"
|
|
if [[ "$RUN_UNIT_TESTS" == "1" ]]; then
|
|
./gradlew --no-daemon "${GRADLE_JAVA_OPT[@]}" clean :tunnel:assembleDebug "${GRADLE_TASK}" testDebugUnitTest
|
|
else
|
|
./gradlew --no-daemon "${GRADLE_JAVA_OPT[@]}" clean :tunnel:assembleDebug "${GRADLE_TASK}"
|
|
fi
|
|
else
|
|
echo "==> Phase: gradle tests-only (:tunnel + testDebugUnitTest)"
|
|
./gradlew --no-daemon "${GRADLE_JAVA_OPT[@]}" :tunnel:assembleDebug testDebugUnitTest
|
|
fi
|
|
|
|
APK=""
|
|
if [[ "$RUN_APK" == "1" ]]; then
|
|
for candidate in \
|
|
"$ROOT/app/build/outputs/apk/debug/app-debug.apk" \
|
|
"$ROOT/app/build/outputs/apk/release/app-release-unsigned.apk" \
|
|
"$ROOT/app/build/outputs/apk/release/app-release.apk"; do
|
|
if [[ -f "$candidate" ]]; then
|
|
APK="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
if [[ -z "$APK" ]]; then
|
|
echo "ERROR: no APK produced" >&2
|
|
exit 1
|
|
fi
|
|
cp -f "$APK" "${OUT_DIR}/android_cast-latest.apk"
|
|
echo "==> APK: ${OUT_DIR}/android_cast-latest.apk"
|
|
fi
|
|
|
|
if [[ "$AUTO_OTA" == "1" && -n "${OTA_BASE_URL:-}" && -n "$APK" ]]; then
|
|
echo "==> Phase: OTA publish channel=${OTA_CHANNEL}"
|
|
OTA_PUBLISH="${OUT_DIR}/ota-publish"
|
|
rm -rf "$OTA_PUBLISH"
|
|
./scripts/generate-ota-v0.sh "$APK" "$OTA_BASE_URL" "$OTA_PUBLISH" "$OTA_CHANNEL"
|
|
mkdir -p "${OUT_DIR}/ota"
|
|
cp -rf "${OTA_PUBLISH}/v0" "${OUT_DIR}/ota/"
|
|
for ch in staging dev nightly stable; do
|
|
if [[ "$OTA_CHANNEL" == "$ch" ]]; then
|
|
continue
|
|
fi
|
|
if [[ "$OTA_CHANNEL" == "stable" || "$OTA_CHANNEL" == "prod" || "$OTA_CHANNEL" == "production" || "$OTA_CHANNEL" == "release" ]]; then
|
|
./scripts/generate-ota-v0.sh "$APK" "$OTA_BASE_URL" "${OUT_DIR}/ota-publish-${ch}" "$ch" || true
|
|
mkdir -p "${OUT_DIR}/ota-${ch}"
|
|
cp -rf "${OUT_DIR}/ota-publish-${ch}/v0" "${OUT_DIR}/ota-${ch}/" 2>/dev/null || true
|
|
fi
|
|
done
|
|
fi
|
|
|
|
cat >"${OUT_DIR}/BUILD_INFO.json" <<EOF
|
|
{
|
|
"buildId": "${BUILD_ID}",
|
|
"gradleTask": "${GRADLE_TASK}",
|
|
"otaChannel": "${OTA_CHANNEL}",
|
|
"apk": "android_cast-latest.apk",
|
|
"gitSha": "$(git -C "$ROOT" rev-parse HEAD 2>/dev/null || echo unknown)",
|
|
"gitRef": "${GIT_REF:-}",
|
|
"ciVersion": "${ANDROIDCAST_CI_VERSION:-00.01.00.1000}"
|
|
}
|
|
EOF
|
|
|
|
echo "==> Phase: done"
|
|
|
|
# Mounted-repo Docker runs must not leave /opt/android-sdk paths in app/.cxx on the host.
|
|
rm -rf "$ROOT/app/.cxx"
|