Mac多账户右键菜单上传IPA文件的方案落地
一、背景:
由于我从以前管理的一个AppStore 开发者账号到现在两个AppStore 开发者账号,我发现官方的Transporter IPA上传工具一次只能登一个账号,没有切换账号的功能,如果要上传IPA的话,每次就都需要再退出一个,再登一个,实在是太麻烦了,因此就去搜索了一下,发现官方的Transporter 提供命令的方式调用上传,官方帮助文档:help.apple.com/itc/transpo…,以此写了一个快速操作菜单,实现效果如下图:
图1 右键选择IPA文件上传 | 图2 打开终端显示信息,确认是否上传 |
|---|---|
图3 显示上传成功结果 | 图4 在AppStore开发者后台显示已上传,正在处理 |
二、准备
-
首先去account.apple.com/account/man… 生成一个安全密码, 在登录和安全-App专用密码-生成APP专用密码,作为下面脚本的 password
-
准备您的Transporter APP
-
登录AppstoreConnect - 编辑个人资料 - 团队ID , 复制您的团队ID 作为下面uploadIPA2 脚本的 provider ,复制您的登录账户作为 username
-
非必选,如果您使用keychain 方式的话,那么可以使用以下命令,设置您的用户名、密码、提供者
security add-generic-password -s "com.juming.ipa.uploader.username" -a "jmIPA" -w "您的登录账户" -U
security add-generic-password -s "com.juming.ipa.uploader.password" -a "jmIPA" -w "您的app专用密码" -U
security add-generic-password -s "com.juming.ipa.uploader.provider" -a "jmIPA" -w "您的团队ID" -U
三、实现
-
首先打开自动操作,选择应用程序,复制以下脚本内容到shell 脚本中,保存为app(目前有个不完美的地方,就是tell application "Terminal" 之前的 echo 是无法显示到前台的,因为这些echo 是在打开终端之前输出的,可以使用其他办法来解决这个小问题,例如打开新的终端 tail -f 日志文件)
#!/bin/bash # 获取 Automator 传来的单一参数(例如 "/path/to/app.ipa,-m:keychain,-u:xxx,-p:xxx,-pr:xxx") rawInput="$1" if [ -z "$rawInput" ]; then echo "Usage:" echo "$0 \"/path/to/app.ipa,-m:input,-u:username,-p:password,-pr:provider\"" echo "或" echo "$0 \"/path/to/app.ipa,-m:keychain,-u:key_username,-p:key_password,-pr:key_provider\"" exit 1 fi # 将输入按逗号拆分 IFS=',' read -r ipaFile modeArg userArg passArg providerArg <<< "$rawInput" # 从各参数中提取标识和值 mode="${modeArg#-m:}" userParam="${userArg#-u:}" passParam="${passArg#-p:}" providerParam="${providerArg#-pr:}" # 检查 IPA 是否存在 if [ ! -f "$ipaFile" ]; then echo "❌ IPA 文件不存在: $ipaFile" exit 1 fi echo "📦 IPA 路径: $ipaFile" echo "🔧 模式: $mode" # 根据模式确定用户名、密码、Provider 的来源 if [[ "$mode" == "input" ]]; then echo "💬 使用用户输入模式" username="$userParam" password="$passParam" provider="$providerParam" elif [[ "$mode" == "keychain" ]]; then echo "🔐 从钥匙串读取..." username=$(security find-generic-password -s "$userParam" -w 2>/dev/null || echo "") password=$(security find-generic-password -s "$passParam" -w 2>/dev/null || echo "") provider=$(security find-generic-password -s "$providerParam" -w 2>/dev/null || echo "") else echo "❌ 未识别的模式,请使用 -m:input 或 -m:keychain" exit 1 fi # 校验是否获取成功 if [[ -z "$username" || -z "$password" || -z "$provider" ]]; then echo "❌ 无法获取账号信息:" echo " username=$username" echo " password=$password" echo " provider=$provider" exit 1 fi echo "✅ 用户名: $username" echo "✅ Provider: $provider" echo # 生成临时执行脚本 dateStr=$(date +"%Y%m%d_%H%M%S") tmpScript="/tmp/ipa_upload_${dateStr}.sh" cat > "$tmpScript" <<'EOS' #!/bin/bash set -e ipaFile="$1" username="$2" password="$3" provider="$4" unzipDir=$(mktemp -d) echo "接收参数如下:" echo "IPA文件: $ipaFile" echo "用户名: $username" echo "Provider: $provider" echo clear echo "正在解压 IPA 并分析信息..." unzip -q "$ipaFile" -d "$unzipDir" >/dev/null 2>&1 appDir=$(find "$unzipDir/Payload" -name '*.app' -type d | head -n1) plist="$appDir/Info.plist" if [ ! -f "$plist" ]; then echo "Error: 未找到 Info.plist 文件" rm -rf "$unzipDir" exit 1 fi appName=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleDisplayName' "$plist" 2>/dev/null || \ /usr/libexec/PlistBuddy -c 'Print :CFBundleName' "$plist" 2>/dev/null || echo '未知应用') bundleId=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIdentifier' "$plist" 2>/dev/null || echo '未知') version=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$plist" 2>/dev/null || echo '未知') build=$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$plist" 2>/dev/null || echo '未知') echo "==================================" echo " IPA 文件信息" echo "==================================" echo "App 名称 : $appName" echo "Bundle ID : $bundleId" echo "版本号 : $version" echo "构建号 : $build" echo "路径 : $ipaFile" echo "==================================" while true; do echo -n "是否上传到 App Store Connect?(y/n): " read answer case "$answer" in [Yy]* ) UPLOAD=1; break ;; [Nn]* ) UPLOAD=0; break ;; * ) echo "请输入 y 或 n" ;; esac done if [ "$UPLOAD" -eq 0 ]; then echo "已取消上传" rm -rf "$unzipDir" exit 0 fi transporter="/Applications/Transporter.app/Contents/itms/bin/iTMSTransporter" if [ ! -f "$transporter" ]; then echo "Error: 未找到 Transporter.app" echo "请从 App Store 下载:https://apps.apple.com/app/transporter/id1450874784" rm -rf "$unzipDir" exit 1 fi echo "开始上传..." "$transporter" -m upload -assetFile "$ipaFile" -u "$username" -p "$password" --asc_provider "$provider" -v eXtreme if [ $? -eq 0 ]; then echo "上传成功!" else echo "上传失败!" fi rm -rf "$unzipDir" echo "完成" # 删除自身临时脚本 rm -- "\$0" sleep 2 EOS chmod +x "$tmpScript" # 用 Terminal 执行上传脚本 osascript <<EOF tell application "Terminal" activate do script "bash '$tmpScript' '$ipaFile' '$username' '$password' '$provider'" end tell EOF -
脚本解释:
由于MACOS的自动操作只能接收一个参数,因此需要将参数组拼起来,在脚本里再解析出来,这个是一个大坑,害得我花了好长时间都没有实现正常的多个参数解析的工作。因此只能另辟蹊径,将所有的参数组合起来放到一个参数中。
本脚本支持两种模式 -m
input 模式,手动输入 -u:username,-p:password,-pr:provider
keychain,从mac 系统的钥匙串中获取 -u:com.juming.ipa.uploader.username,-p:com.juming.ipa.uploader.password,-pr:com.juming.ipa.uploader.provider
其他的,具体看脚本代码吧
-
编写调用命令,打开自动操作,选择快速操作,放到自动操作的shell 脚本中,并保存
-
工作流程收到当前 选择 文件或文件夹,位于 访达.app
-
Shell,选择/bin/bash ,传递输入,选择 作为自变量
-
open -a "/Users/jiyuren/Library/Services/uploadIPA2.app" --args "\$1,-m:keychain,-u:com.juming.ipa.uploader.username,-p:com.juming.ipa.uploader.password,-pr:com.juming.ipa.uploader.provider"
- 开启右键菜单,系统-通用-登录项与扩展-访达,勾选您的工作流程,即可实现右键快速操作的菜单。
四、扩展与感悟
-
您也可以给您的AndroidStudio 增加右键菜单上传IPA
-
你也可以结合iRightMenu Pro,配置脚本指定.ipa后缀显示上传IPA菜单
-
如果各位有什么更加简单方便的方法的话,欢迎交流