90 lines
3.4 KiB
Bash
Executable File
90 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# DSH 工作台 APK 构建:Docker 内完成,宿主机无需安装 Flutter/Android SDK
|
||
# 用法:./build.sh URL --keystore PATH --alias NAME [--no-cache]
|
||
# 产出:build/app/outputs/flutter-apk/app-*.apk
|
||
set -euo pipefail
|
||
|
||
if [ "$#" -lt 1 ]; then
|
||
echo '用法:./build.sh https://你的域名 --keystore PATH --alias NAME [--no-cache]' >&2
|
||
exit 64
|
||
fi
|
||
DSH_SITE_URL=$1
|
||
shift
|
||
case "$DSH_SITE_URL" in
|
||
https://?*) ;;
|
||
*) echo '必须传入完整的 HTTPS 站点地址' >&2; exit 64 ;;
|
||
esac
|
||
case "$DSH_SITE_URL" in
|
||
*[[:space:]]*) echo '站点地址不能包含空白字符' >&2; exit 64 ;;
|
||
esac
|
||
REBUILD=false
|
||
KEYSTORE=''
|
||
DSH_KEY_ALIAS=''
|
||
while [ "$#" -gt 0 ]; do
|
||
case "$1" in
|
||
--keystore|--alias)
|
||
if [ "$#" -lt 2 ] || [ -z "$2" ]; then
|
||
echo "$1 缺少参数值" >&2; exit 64
|
||
fi
|
||
if [ "$1" = '--keystore' ]; then KEYSTORE=$2; else DSH_KEY_ALIAS=$2; fi
|
||
shift 2 ;;
|
||
--no-cache) REBUILD=true; shift ;;
|
||
*) echo "未知参数:$1" >&2; exit 64 ;;
|
||
esac
|
||
done
|
||
if [ -z "$KEYSTORE" ] || [ -z "$DSH_KEY_ALIAS" ]; then
|
||
echo '必须提供 --keystore PATH 和 --alias NAME;release 不使用 debug 签名' >&2
|
||
exit 64
|
||
fi
|
||
if [ ! -f "$KEYSTORE" ] || [ ! -r "$KEYSTORE" ]; then
|
||
echo '密钥库文件不存在或不可读' >&2; exit 64
|
||
fi
|
||
# 相对路径基于调用者的工作目录,不基于脚本目录。
|
||
KEYSTORE="$(cd -- "$(dirname -- "$KEYSTORE")" && pwd)/$(basename -- "$KEYSTORE")"
|
||
case "$KEYSTORE" in
|
||
*,*) echo '密钥库路径不能含逗号(Docker mount 分隔符)' >&2; exit 64 ;;
|
||
esac
|
||
if [ -z "${DSH_STORE_PASSWORD:-}" ]; then
|
||
if [ ! -t 0 ]; then
|
||
echo '非交互构建请通过受保护的环境变量提供 DSH_STORE_PASSWORD' >&2; exit 64
|
||
fi
|
||
read -r -s -p '密钥库密码:' DSH_STORE_PASSWORD
|
||
printf '\n'
|
||
fi
|
||
if [ -z "$DSH_STORE_PASSWORD" ]; then echo '密码不能为空' >&2; exit 64; fi
|
||
if [ -z "${DSH_KEY_PASSWORD:-}" ]; then
|
||
if [ -t 0 ]; then
|
||
read -r -s -p '私钥密码(回车使用密钥库密码):' DSH_KEY_PASSWORD
|
||
printf '\n'
|
||
fi
|
||
DSH_KEY_PASSWORD=${DSH_KEY_PASSWORD:-$DSH_STORE_PASSWORD}
|
||
fi
|
||
export DSH_STORE_PASSWORD DSH_KEY_PASSWORD DSH_KEY_ALIAS
|
||
|
||
cd "$(dirname "$0")"
|
||
|
||
IMAGE=dsh-appbuilder:3.47.7
|
||
|
||
if [ "$REBUILD" = true ] || ! docker image inspect "$IMAGE" > /dev/null 2>&1; then
|
||
echo "==> 构建镜像 $IMAGE(首次较慢,需下载 Flutter/Android SDK)"
|
||
BUILD_ARGS=()
|
||
if [ "$REBUILD" = true ]; then BUILD_ARGS+=(--no-cache); fi
|
||
docker build --build-arg http_proxy --build-arg https_proxy --build-arg no_proxy "${BUILD_ARGS[@]}" -t "$IMAGE" .
|
||
fi
|
||
|
||
echo "==> 在容器内构建 release APK"
|
||
docker run --rm \
|
||
-v "$PWD":/project \
|
||
-w /project \
|
||
--mount "type=bind,source=$KEYSTORE,target=/run/dsh-signing/release.keystore,readonly" \
|
||
-e DSH_KEYSTORE=/run/dsh-signing/release.keystore \
|
||
-e DSH_KEY_ALIAS -e DSH_STORE_PASSWORD -e DSH_KEY_PASSWORD \
|
||
-e http_proxy -e https_proxy -e no_proxy \
|
||
-e PUB_CACHE=/opt/pub-cache \
|
||
-e DSH_SITE_URL="$DSH_SITE_URL" \
|
||
"$IMAGE" \
|
||
sh -ec 'dart tool/validate_site_url.dart "$DSH_SITE_URL"; flutter pub get; flutter test --dart-define="DSH_SITE_URL=$DSH_SITE_URL"; flutter build apk --dart-define="DSH_SITE_URL=$DSH_SITE_URL" --release --split-per-abi --obfuscate --split-debug-info=build/symbols'
|
||
|
||
echo "==> 完成,产物:"
|
||
ls -lh build/app/outputs/flutter-apk/*.apk
|