Files
jiu/scripts/ci/compile-ios.sh
T
wangjia 480ce836bb
Deploy / build-linux-web (push) Successful in 53s
Deploy / build-windows (push) Successful in 1m48s
Deploy / build-macos (push) Successful in 1m17s
Deploy / build-android (push) Successful in 4m13s
Deploy / build-ios (push) Successful in 9s
Deploy / release-deploy (push) Successful in 1m37s
chore: release v1.0.18
移动端响应式适配(抽屉导航/列表卡片/弹窗自适应)、Android 正式签名与 APK 发布、
iOS(TestFlight) 工程与 CI、多平台构建流水线、相关文档同步。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 07:55:33 +08:00

125 lines
4.8 KiB
Bash
Executable File
Raw 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.
#!/usr/bin/env bash
# compile-ios.sh <tag> — build signed iOS IPA and upload to TestFlight (App Store Connect)
#
# 需要的 CI secrets(缺任意一个则优雅跳过,不阻塞流水线):
# IOS_DIST_CERT_P12_BASE64 Apple Distribution 证书 (.p12) 的 base64
# IOS_DIST_CERT_PASSWORD .p12 导出密码
# IOS_PROVISIONING_PROFILE_BASE64 App Store 类型 provisioning profile (.mobileprovision) 的 base64
# IOS_TEAM_ID Apple Developer Team ID10 位)
# APPSTORE_API_KEY_ID App Store Connect API Key ID
# APPSTORE_API_ISSUER_ID App Store Connect API Issuer ID
# APPSTORE_API_KEY_P8_BASE64 API Key (.p8) 的 base64
#
# 详见 docs/ios-signing.md。
set -euo pipefail
# shellcheck source=scripts/ci/_env.sh
. "$(dirname "$0")/_env.sh"
TAG="$1"
VER="${TAG#v}"
# CFBundleVersionbuild 号)必须单调递增,否则 TestFlight 拒绝重复上传。
MAJOR="$(echo "$VER" | cut -d. -f1)"
MINOR="$(echo "$VER" | cut -d. -f2)"
PATCH="$(echo "$VER" | cut -d. -f3)"
BUILD=$(( MAJOR * 10000 + MINOR * 100 + PATCH ))
echo "==> compile-ios: version=${VER} build=${BUILD}"
# --- 凭证缺失则跳过(账号/证书尚未配置时不阻塞发版)---
if [ -z "${IOS_DIST_CERT_P12_BASE64:-}" ] || \
[ -z "${IOS_PROVISIONING_PROFILE_BASE64:-}" ] || \
[ -z "${APPSTORE_API_KEY_P8_BASE64:-}" ]; then
echo "==> compile-ios: SKIP — iOS signing secrets not configured (see docs/ios-signing.md)"
exit 0
fi
WORK="$(mktemp -d)"
cleanup() {
security delete-keychain "$KEYCHAIN" 2>/dev/null || true
rm -rf "$WORK"
rm -f "$HOME/Library/MobileDevice/Provisioning Profiles/jiu-ci.mobileprovision" 2>/dev/null || true
}
trap cleanup EXIT
# --- 1. 临时 keychain 导入发行证书 ---
KEYCHAIN="$WORK/jiu-ci.keychain-db"
KEYCHAIN_PWD="ci-temp-$$"
security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN"
security set-keychain-settings -lut 21600 "$KEYCHAIN"
security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN"
echo "${IOS_DIST_CERT_P12_BASE64}" | base64 --decode > "$WORK/dist.p12"
security import "$WORK/dist.p12" -k "$KEYCHAIN" \
-P "${IOS_DIST_CERT_PASSWORD:-}" -T /usr/bin/codesign -T /usr/bin/security
# 允许 codesign 非交互访问私钥
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PWD" "$KEYCHAIN" >/dev/null
# 把临时 keychain 加入搜索列表(保留默认 login keychain
security list-keychains -d user -s "$KEYCHAIN" login.keychain-db
# --- 2. 安装 provisioning profile ---
PROFILES_DIR="$HOME/Library/MobileDevice/Provisioning Profiles"
mkdir -p "$PROFILES_DIR"
echo "${IOS_PROVISIONING_PROFILE_BASE64}" | base64 --decode > "$WORK/profile.mobileprovision"
# 解出 profile 的 Name 与 UUIDExportOptions 需要)
security cms -D -i "$WORK/profile.mobileprovision" > "$WORK/profile.plist"
PROFILE_NAME="$(/usr/libexec/PlistBuddy -c 'Print :Name' "$WORK/profile.plist")"
PROFILE_UUID="$(/usr/libexec/PlistBuddy -c 'Print :UUID' "$WORK/profile.plist")"
cp "$WORK/profile.mobileprovision" "$PROFILES_DIR/${PROFILE_UUID}.mobileprovision"
echo "==> compile-ios: profile '${PROFILE_NAME}' (${PROFILE_UUID})"
# --- 3. App Store Connect API Key(供上传使用)---
API_KEYS_DIR="$HOME/.appstoreconnect/private_keys"
mkdir -p "$API_KEYS_DIR"
echo "${APPSTORE_API_KEY_P8_BASE64}" | base64 --decode > "$API_KEYS_DIR/AuthKey_${APPSTORE_API_KEY_ID}.p8"
# --- 4. 同步版本号 ---
sed -i '' "s/^version:.*/version: ${VER}+${BUILD}/" client/pubspec.yaml
# --- 5. 生成 ExportOptions.plistmanual 签名,app-store 分发)---
BUNDLE_ID="com.yanmei.jiu"
cat > "$WORK/ExportOptions.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>${IOS_TEAM_ID}</string>
<key>signingStyle</key><string>manual</string>
<key>uploadBitcode</key><false/>
<key>uploadSymbols</key><true/>
<key>provisioningProfiles</key>
<dict>
<key>${BUNDLE_ID}</key><string>${PROFILE_NAME}</string>
</dict>
</dict>
</plist>
EOF
# --- 6. 构建签名 IPA ---
cd client
flutter build ipa --release \
--build-name="${VER}" \
--build-number="${BUILD}" \
--export-options-plist="$WORK/ExportOptions.plist" \
"--dart-define=BASE_URL=https://jiu.51yanmei.com" \
"--dart-define=PUBLIC_URL=https://jiu.51yanmei.com" \
"--dart-define=APP_VERSION=${TAG}"
cd ..
IPA="$(ls client/build/ios/ipa/*.ipa | head -1)"
if [ -z "$IPA" ] || [ ! -f "$IPA" ]; then
echo "ERROR: IPA not found" >&2
exit 1
fi
echo "==> compile-ios: built ${IPA}"
# --- 7. 上传 TestFlightApp Store Connect---
echo "==> compile-ios: uploading to TestFlight"
xcrun altool --upload-app -f "$IPA" -t ios \
--apiKey "${APPSTORE_API_KEY_ID}" \
--apiIssuer "${APPSTORE_API_ISSUER_ID}"
echo "==> compile-ios: done — uploaded build ${BUILD} to TestFlight"