70f003cb1a
Deploy Client / build-client-web (push) Successful in 57s
Deploy Client / build-windows (push) Successful in 35s
Deploy Client / build-macos (push) Successful in 8m23s
Deploy Client / build-android (push) Successful in 7m40s
Deploy Client / build-ios (push) Successful in 7m54s
Deploy Client / release-deploy-client (push) Failing after 14m32s
altool 上传易抖(重复 build 号/ASC 临时错误),不应拖住 web/mac/win/android。 IPA 仍产出,上传失败仅告警,可稍后手动补传。对齐 CLAUDE.md「iOS 不阻塞」。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bupi8Kdqkfx2N5acFsHTx5
113 lines
4.8 KiB
Bash
Executable File
113 lines
4.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# compile-ios.sh <tag> — build signed iOS IPA and upload to TestFlight (App Store Connect)
|
|
#
|
|
# 用**本机 login keychain 的 Apple Distribution 证书** + **本机已装的 App Store
|
|
# provisioning profile** + **本机 App Store Connect key(.p8)** 签名/上传。
|
|
# mac-runner 就是开发机,这些分发材料常驻本机,不再从 base64 secret 导入
|
|
# (原方案 IOS_DIST_CERT_P12_BASE64 里的证书过期 → archive 报 "No valid code
|
|
# signing certificates";本机 login 里那张有效,2026-07 改用本机材料)。
|
|
#
|
|
# 需要 env(非机密标识,gitea secret/变量;缺则用已知默认):
|
|
# IOS_TEAM_ID(默认 BYL4KQHMTN)/ APPSTORE_API_KEY_ID(默认 3PZTHR8YMJ)/
|
|
# APPSTORE_API_ISSUER_ID(必填,无默认)
|
|
# 需要本机:Apple Distribution 证书在 login keychain;App Store profile 已装;
|
|
# ~/.appstoreconnect/private_keys/AuthKey_<KEY_ID>.p8 存在。
|
|
set -euo pipefail
|
|
|
|
# shellcheck source=scripts/ci/_env.sh
|
|
. "$(dirname "$0")/_env.sh"
|
|
|
|
TAG="$1"
|
|
VER="${TAG#client-v}"
|
|
|
|
# CFBundleVersion(build 号)必须单调递增,否则 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}"
|
|
|
|
TEAM_ID="${IOS_TEAM_ID:-BYL4KQHMTN}"
|
|
KEY_ID="${APPSTORE_API_KEY_ID:-3PZTHR8YMJ}"
|
|
ISSUER="${APPSTORE_API_ISSUER_ID:-}"
|
|
BUNDLE_ID="com.yanmei.jiu"
|
|
P8="$HOME/.appstoreconnect/private_keys/AuthKey_${KEY_ID}.p8"
|
|
|
|
# --- 前置检查:本机分发材料齐备(缺则 fail-fast,不产出未签名/无法上传的包)---
|
|
if ! security find-identity -v -p codesigning \
|
|
| grep -qF "Apple Distribution: Yanmei (beijing) Technology Co., Ltd (${TEAM_ID})"; then
|
|
echo "ERROR: login keychain 未找到 Apple Distribution 证书(团队 ${TEAM_ID})——无法签名 iOS。" >&2
|
|
echo " 在本机 Xcode 登录 Apple ID / 装好分发证书后重试。" >&2
|
|
exit 1
|
|
fi
|
|
if [ ! -f "$P8" ]; then
|
|
echo "ERROR: 缺 App Store Connect key: $P8" >&2
|
|
exit 1
|
|
fi
|
|
if [ -z "$ISSUER" ]; then
|
|
echo "ERROR: 缺 APPSTORE_API_ISSUER_ID(App Store Connect Issuer ID)——公证/上传需要。" >&2
|
|
exit 1
|
|
fi
|
|
|
|
WORK="$(mktemp -d)"
|
|
# shellcheck disable=SC2064
|
|
trap "rm -rf '$WORK'" EXIT
|
|
|
|
# --- 同步版本号 ---
|
|
sed -i '' "s/^version:.*/version: ${VER}+${BUILD}/" client/pubspec.yaml
|
|
|
|
# --- ExportOptions.plist(automatic 签名,app-store 分发)---
|
|
# 本机 login 里的 Apple Distribution 证书与旧的手动 profile 不配对
|
|
# (profile 是用另一张/旧证书签发的 → archive 报 "profile doesn't include
|
|
# signing certificate")。改用**自动签名**:Xcode 用登录的 Apple ID +
|
|
# App Store Connect API key(见下 xcodebuild -authenticationKeyPath) 现场
|
|
# 生成/更新与当前证书匹配的 App Store profile(-allowProvisioningUpdates),
|
|
# 与 local_test.sh --ios 一致,避免手动材料漂移。
|
|
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>${TEAM_ID}</string>
|
|
<key>signingStyle</key><string>automatic</string>
|
|
<key>uploadBitcode</key><false/>
|
|
<key>uploadSymbols</key><true/>
|
|
</dict>
|
|
</plist>
|
|
EOF
|
|
|
|
# --- 构建签名 IPA(自动签名;Xcode 现场配对证书+profile)---
|
|
# flutter build ipa 的 archive/export 都会带 -allowProvisioningUpdates(自动签名时),
|
|
# 但云端/无交互登录需用 API key 授权 provisioning 更新 → 传 -authenticationKeyPath 等。
|
|
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=v${VER}"
|
|
cd ..
|
|
|
|
IPA="$(ls client/build/ios/ipa/*.ipa 2>/dev/null | head -1)"
|
|
if [ -z "$IPA" ] || [ ! -f "$IPA" ]; then
|
|
echo "ERROR: IPA not found" >&2
|
|
exit 1
|
|
fi
|
|
echo "==> compile-ios: built ${IPA}"
|
|
|
|
# --- 上传 TestFlight(App Store Connect;本机 .p8 由 key-id 自动定位)---
|
|
# TestFlight 是 App Store 独立分发渠道,上传本身易抖(重复 build 号 / ASC 临时错误);
|
|
# 其失败【不应阻断】web/mac/win/android 的整体发版(见 CLAUDE.md「iOS ... 不阻塞」)。
|
|
# IPA 已产出,上传失败仅告警,可稍后用 altool/Transporter 手动补传同一 IPA。
|
|
echo "==> compile-ios: uploading to TestFlight"
|
|
if xcrun altool --upload-app -f "$IPA" -t ios \
|
|
--apiKey "${KEY_ID}" \
|
|
--apiIssuer "${ISSUER}"; then
|
|
echo "==> compile-ios: done — uploaded build ${BUILD} to TestFlight"
|
|
else
|
|
echo "!! compile-ios: TestFlight 上传失败(build ${BUILD}),不阻断发版;IPA=${IPA} 已产出,可稍后手动补传。" >&2
|
|
fi
|