Files
mindfulness/client/ios/scripts/fix-xcarchive-header.sh
2026-02-05 16:06:49 +08:00

134 lines
6.9 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
set -euo pipefail
# 修复 Xcode Organizer 显示 “Generic Xcode Archive” 的问题:
# - 某些情况下 xcodebuild 生成的 .xcarchive/Info.plist 缺少 ApplicationProperties
# - Organizer 无法识别归档中的主 App即使 Products/Applications/*.app 存在)
#
# 说明:
# - 该脚本的核心作用是让 Organizer 能识别归档里的主 App从而出现“分发/上传 TestFlight”入口。
# - 这类问题通常发生在命令行/CI 归档xcodebuild archive或某些自定义归档流程中
# 导致 .xcarchive/Info.plist 缺少/不完整。
#
# 用法:
# ./scripts/fix-xcarchive-header.sh "/path/to/xxx.xcarchive"
ARCHIVE_PATH="${1:-}"
if [[ -z "$ARCHIVE_PATH" ]]; then
echo "用法: $0 \"/path/to/xxx.xcarchive\"" >&2
exit 2
fi
if [[ ! -d "$ARCHIVE_PATH" ]]; then
echo "错误:找不到归档目录:$ARCHIVE_PATH" >&2
exit 2
fi
ARCHIVE_INFO_PLIST="$ARCHIVE_PATH/Info.plist"
if [[ ! -f "$ARCHIVE_INFO_PLIST" ]]; then
echo "错误:找不到归档 Info.plist$ARCHIVE_INFO_PLIST" >&2
exit 2
fi
# 归档名:尽量从路径推导,避免依赖 Xcode 环境变量
archive_basename="$(/usr/bin/basename "$ARCHIVE_PATH")"
archive_name="${archive_basename%.xcarchive}"
# 取第一个 App归档里通常只有一个主 App
APP_PLIST="$(/usr/bin/find "$ARCHIVE_PATH/Products/Applications" -maxdepth 2 -name Info.plist -path "*.app/Info.plist" 2>/dev/null | /usr/bin/head -n 1 || true)"
if [[ -z "$APP_PLIST" ]]; then
echo "错误:归档中未找到 Products/Applications/*.app/Info.plist请先确保归档产出包含 .app" >&2
exit 2
fi
APP_DIR="$(/usr/bin/dirname "$APP_PLIST")"
APP_NAME="$(/usr/bin/basename "$APP_DIR")" # 例如 HeyMama.app
APP_REL_PATH="Applications/$APP_NAME"
bundle_id="$(/usr/bin/plutil -extract CFBundleIdentifier raw -o - "$APP_PLIST" 2>/dev/null || true)"
short_version="$(/usr/bin/plutil -extract CFBundleShortVersionString raw -o - "$APP_PLIST" 2>/dev/null || true)"
build_version="$(/usr/bin/plutil -extract CFBundleVersion raw -o - "$APP_PLIST" 2>/dev/null || true)"
display_name="$(/usr/bin/plutil -extract CFBundleDisplayName raw -o - "$APP_PLIST" 2>/dev/null || true)"
bundle_name="$(/usr/bin/plutil -extract CFBundleName raw -o - "$APP_PLIST" 2>/dev/null || true)"
# SchemeName 在 Organizer 中会用到,但在某些归档流程里会缺失
scheme_name="${SCHEME_NAME:-}"
if [[ -z "$scheme_name" ]]; then
scheme_name="${archive_name:-}"
fi
if [[ -z "$bundle_id" || -z "$short_version" || -z "$build_version" ]]; then
echo "错误:无法从 App Info.plist 读取 bundle/version/build$APP_PLIST" >&2
exit 2
fi
# 解析 embedded.mobileprovision若存在
profile_name=""
profile_uuid=""
team_id=""
provision_path="$APP_DIR/embedded.mobileprovision"
if [[ -f "$provision_path" ]]; then
decoded="$(/usr/bin/security cms -D -i "$provision_path" 2>/dev/null || true)"
if [[ -n "$decoded" ]]; then
# 使用 plutil 从 xml 中提取字段
profile_name="$(printf "%s" "$decoded" | /usr/bin/plutil -extract Name raw -o - - 2>/dev/null || true)"
profile_uuid="$(printf "%s" "$decoded" | /usr/bin/plutil -extract UUID raw -o - - 2>/dev/null || true)"
team_id="$(printf "%s" "$decoded" | /usr/bin/plutil -extract TeamIdentifier.0 raw -o - - 2>/dev/null || true)"
fi
fi
# 备份一份,防止误操作
cp -f "$ARCHIVE_INFO_PLIST" "$ARCHIVE_INFO_PLIST.bak"
# 修复归档根字段,避免 Organizer 仍然把它当 Generic Archive
# 参考:标准 .xcarchive/Info.plist 通常包含 Name / SchemeName / ArchiveVersion / CreationDate 等。
# 我们只在缺失时补齐,尽量不改动归档的其他内容。
if ! /usr/bin/plutil -extract Name xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
/usr/bin/plutil -insert Name -string "${archive_name:-${display_name:-${bundle_name:-}}}" "$ARCHIVE_INFO_PLIST" 2>/dev/null || true
fi
if ! /usr/bin/plutil -extract SchemeName xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
/usr/bin/plutil -insert SchemeName -string "${scheme_name:-${archive_name:-}}" "$ARCHIVE_INFO_PLIST" 2>/dev/null || true
fi
# 如果已有 ApplicationProperties直接更新关键字段即可
if /usr/bin/plutil -extract ApplicationProperties xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
/usr/bin/plutil -replace ApplicationProperties.ApplicationPath -string "$APP_REL_PATH" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -replace ApplicationProperties.CFBundleIdentifier -string "$bundle_id" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -replace ApplicationProperties.CFBundleShortVersionString -string "$short_version" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -replace ApplicationProperties.CFBundleVersion -string "$build_version" "$ARCHIVE_INFO_PLIST"
else
# 新增 ApplicationProperties注意plutil 的空字典/数组类型是 -dictionary / -array
/usr/bin/plutil -insert ApplicationProperties -dictionary "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.ApplicationPath -string "$APP_REL_PATH" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.CFBundleIdentifier -string "$bundle_id" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.CFBundleShortVersionString -string "$short_version" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.CFBundleVersion -string "$build_version" "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.Architectures -array "$ARCHIVE_INFO_PLIST"
/usr/bin/plutil -insert ApplicationProperties.Architectures.0 -string "arm64" "$ARCHIVE_INFO_PLIST"
fi
# 可选字段Provisioning Profile 信息(不保证一定存在)
if [[ -n "$profile_name" ]]; then
/usr/bin/plutil -replace ApplicationProperties.ProvisioningProfileName -string "$profile_name" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
/usr/bin/plutil -insert ApplicationProperties.ProvisioningProfileName -string "$profile_name" "$ARCHIVE_INFO_PLIST"
fi
if [[ -n "$profile_uuid" ]]; then
/usr/bin/plutil -replace ApplicationProperties.ProvisioningProfileUUID -string "$profile_uuid" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
/usr/bin/plutil -insert ApplicationProperties.ProvisioningProfileUUID -string "$profile_uuid" "$ARCHIVE_INFO_PLIST"
fi
if [[ -n "$team_id" ]]; then
/usr/bin/plutil -replace ApplicationProperties.Team -string "$team_id" "$ARCHIVE_INFO_PLIST" 2>/dev/null || \
/usr/bin/plutil -insert ApplicationProperties.Team -string "$team_id" "$ARCHIVE_INFO_PLIST"
fi
echo "已修复归档 header$ARCHIVE_INFO_PLIST"
echo "主 App$APP_REL_PATH"
echo "Bundle$bundle_id"
echo "Version/Build$short_version/$build_version"
echo "Name/SchemeName${archive_name:-} / ${scheme_name:-}"
# 轻量自检:确保关键字段存在(不强制失败,避免中断归档)
if ! /usr/bin/plutil -extract ApplicationProperties.ApplicationPath xml1 -o - "$ARCHIVE_INFO_PLIST" >/dev/null 2>&1; then
echo "警告:归档 Info.plist 仍缺少 ApplicationProperties.ApplicationPathOrganizer 可能仍显示 Generic Archive" >&2
fi