LighthouseApp/build_ios_appstore.sh
speakeloudest 75d4c48e41
Some checks failed
Build Windows / build (push) Has been cancelled
feat: 源码提交
2025-10-19 23:30:54 -07:00

359 lines
8.1 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# iOS App Store 构建和上传脚本
# 支持自动构建、签名、上传到 App Store Connect
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查环境
check_environment() {
log_info "检查 App Store 构建环境..."
# 检查必要的环境变量
if [ -z "$APPLE_ID" ] || [ -z "$APPLE_PASSWORD" ] || [ -z "$TEAM_ID" ]; then
log_error "请先运行: source ios_signing_config.sh"
exit 1
fi
# 检查 Xcode
if ! command -v xcodebuild &> /dev/null; then
log_error "Xcode 未安装或不在 PATH 中"
exit 1
fi
# 检查 xcrun altool
if ! command -v xcrun &> /dev/null; then
log_error "xcrun 不可用"
exit 1
fi
log_success "环境检查通过"
}
# 检查证书和配置文件
check_certificates_and_profiles() {
log_info "检查证书和配置文件..."
# 检查分发证书
if ! security find-identity -v -p codesigning | grep -q "iPhone Distribution\|Apple Distribution"; then
log_error "未找到有效的分发证书"
log_info "请确保已安装 Apple Distribution 证书"
exit 1
fi
# 检查配置文件
local profiles_dir="$HOME/Library/MobileDevice/Provisioning Profiles"
if [ ! -d "$profiles_dir" ]; then
log_error "配置文件目录不存在: $profiles_dir"
exit 1
fi
log_success "证书和配置文件检查通过"
}
# 清理构建
clean_build() {
log_info "清理之前的构建..."
flutter clean
rm -rf build/ios
rm -rf ios/build
log_success "清理完成"
}
# 获取依赖
get_dependencies() {
log_info "获取 Flutter 依赖..."
flutter pub get
log_success "依赖获取完成"
}
# 构建 iOS 应用
build_ios_app() {
log_info "开始构建 iOS 应用 (App Store)..."
# 构建 Flutter 应用
flutter build ios --release --no-codesign
# 检查构建结果
local app_path="build/ios/iphoneos/Runner.app"
if [ ! -d "$app_path" ]; then
log_error "iOS 应用构建失败: $app_path 不存在"
exit 1
fi
log_success "iOS 应用构建完成: $app_path"
}
# 使用 Xcode 构建和签名
build_with_xcode() {
log_info "使用 Xcode 构建和签名..."
# 进入 iOS 目录
cd ios
# 使用 xcodebuild 构建
xcodebuild -workspace Runner.xcworkspace \
-scheme Runner \
-configuration Release \
-destination generic/platform=iOS \
-archivePath ../build/ios/Runner.xcarchive \
archive
if [ $? -ne 0 ]; then
log_error "Xcode 构建失败"
exit 1
fi
# 返回项目根目录
cd ..
log_success "Xcode 构建完成"
}
# 导出 IPA
export_ipa() {
log_info "导出 IPA 文件..."
# 创建导出选项文件
local export_options_plist="ios/ExportOptions.plist"
cat > "$export_options_plist" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>teamID</key>
<string>$TEAM_ID</string>
<key>uploadBitcode</key>
<false/>
<key>uploadSymbols</key>
<true/>
<key>compileBitcode</key>
<false/>
</dict>
</plist>
EOF
# 导出 IPA
xcodebuild -exportArchive \
-archivePath build/ios/Runner.xcarchive \
-exportPath build/ios/export \
-exportOptionsPlist "$export_options_plist"
if [ $? -ne 0 ]; then
log_error "IPA 导出失败"
exit 1
fi
# 移动 IPA 文件
local ipa_path="$IPA_PATH"
mkdir -p "$(dirname "$ipa_path")"
mv build/ios/export/Runner.ipa "$ipa_path"
log_success "IPA 文件导出成功: $ipa_path"
}
# 验证 IPA
validate_ipa() {
local ipa_path=$1
log_info "验证 IPA 文件..."
# 使用 xcrun altool 验证
xcrun altool --validate-app \
-f "$ipa_path" \
-t ios \
-u "$APPLE_ID" \
-p "$APPLE_PASSWORD"
if [ $? -eq 0 ]; then
log_success "IPA 验证通过"
else
log_error "IPA 验证失败"
exit 1
fi
}
# 上传到 App Store
upload_to_appstore() {
local ipa_path=$1
log_info "上传到 App Store Connect..."
# 使用 xcrun altool 上传
xcrun altool --upload-app \
-f "$ipa_path" \
-t ios \
-u "$APPLE_ID" \
-p "$APPLE_PASSWORD"
if [ $? -eq 0 ]; then
log_success "上传到 App Store Connect 成功"
else
log_error "上传到 App Store Connect 失败"
exit 1
fi
}
# 创建 DMG
create_dmg() {
local ipa_path=$1
local dmg_path=$2
log_info "创建 DMG 文件..."
# 创建临时目录
local temp_dir="build/ios/temp_dmg"
mkdir -p "$temp_dir"
# 复制 IPA 到临时目录
cp "$ipa_path" "$temp_dir/"
# 创建 DMG
hdiutil create -srcfolder "$temp_dir" \
-volname "BearVPN iOS App Store" \
-fs HFS+ \
-format UDZO \
-imagekey zlib-level=9 \
"$dmg_path"
# 清理临时目录
rm -rf "$temp_dir"
if [ -f "$dmg_path" ]; then
log_success "DMG 文件创建成功: $dmg_path"
else
log_error "DMG 文件创建失败"
exit 1
fi
}
# 显示构建结果
show_result() {
local ipa_path=$1
local dmg_path=$2
log_success "=========================================="
log_success "iOS App Store 构建完成!"
log_success "=========================================="
log_info "应用名称: $APP_NAME"
log_info "版本: $VERSION"
log_info "Bundle ID: $BUNDLE_ID"
log_info "IPA 文件: $ipa_path"
log_info "DMG 文件: $dmg_path"
log_info "开发者: $DISTRIBUTION_IDENTITY"
log_success "=========================================="
log_info "应用已上传到 App Store Connect"
log_info "请在 App Store Connect 中完成最终发布"
log_success "=========================================="
}
# 主函数
main() {
local upload=${1:-"true"}
log_info "开始 iOS App Store 构建流程..."
log_info "上传到 App Store: $upload"
log_info "=========================================="
check_environment
check_certificates_and_profiles
clean_build
get_dependencies
build_ios_app
build_with_xcode
export_ipa
# 设置路径
local ipa_path="$IPA_PATH"
local dmg_path="$DMG_PATH"
# 创建输出目录
mkdir -p "$(dirname "$dmg_path")"
# 验证 IPA
validate_ipa "$ipa_path"
# 上传到 App Store如果启用
if [ "$upload" = "true" ]; then
upload_to_appstore "$ipa_path"
else
log_info "跳过上传到 App Store"
fi
# 创建 DMG
create_dmg "$ipa_path" "$dmg_path"
# 显示结果
show_result "$ipa_path" "$dmg_path"
log_success "所有操作完成!"
}
# 显示帮助信息
show_help() {
echo "iOS App Store 构建和上传脚本"
echo ""
echo "用法: $0 [选项]"
echo ""
echo "选项:"
echo " upload 构建并上传到 App Store Connect (默认)"
echo " build 仅构建,不上传"
echo " help 显示此帮助信息"
echo ""
echo "示例:"
echo " $0 # 构建并上传到 App Store"
echo " $0 upload # 构建并上传到 App Store"
echo " $0 build # 仅构建,不上传"
echo ""
echo "注意: 请先运行 'source ios_signing_config.sh' 配置签名信息"
}
# 处理命令行参数
case "${1:-}" in
"help"|"-h"|"--help")
show_help
exit 0
;;
"upload"|"build")
main "$1"
;;
"")
main "upload"
;;
*)
log_error "未知选项: $1"
show_help
exit 1
;;
esac