iOS项目自动打包并上传至FTP服务器 Shell脚本

简介

公司自己搭建FTP服务器用于测试人员、公司员工安装IPA包,为简化开发人员工作量,将整个打包、上传流程简化为脚本操作。配置好相关信息后,打开APP,点击生成脚本,粘贴执行生成的脚本即可完成。

工具图标.png
工具截图.png

使用方法

  1. 拷贝Shell文件夹至.xcodeproj同级文件夹,移动 自动打包工具 至.xcodeproj上级目录


    文件放置相对目录.png
  2. 配置Shell文件夹下的各个Plist文件,添加provisioningProfiles下的key-value,key为对应target的bundle id,value为对应模式下provisioningProfile文件名字,如有多个target,需要添加多个键值对


    plist文件配置.png
  3. 确保plist中用到的所有配置文件存在于~/Library/MobileDevice/Provisioning Profiles路径下,如没有在对应文件夹下,在开发者后台下载并移动至上述目录


    配置文件存放位置.png
  4. 修改Shell文件夹下的build.sh脚本文件,修改的参数如下图所示


    脚本文件修改参数1.png
    脚本文件修改参数2.png
    脚本文件修改参数3.png
  5. 找到自动打包工具,右键显示包内容,修改Contents->Resources->build.sh文件内的projectFolderName参数为.xcodeproj所在的文件夹名称

自动打包工具包内容.png
  1. 脚本运行完毕之后,会在scheme_name-IPA文件夹下生成对应的log文件、IPA文件、xcarchive文件等,如果不需要提交到git,可自行删除。


    IPA文件夹文件列表.png

以上操作只需要配置一次,接下来

运行 自动打包工具 -> 选择模式 -> 点击生成按钮 -> control + v -> 回车 等待整个流程的进行,整个过程的LOG可以在终端观察。


终端截图1.png

终端成功截图2.png

流程解析

  1. 主要操作是由Shell文件夹下的build.sh完成的,整个脚本又分为两个部分,打包和上传,打包过程由Pod-Clean-Build-Archive-Export几个步骤构成,之后将IPA包上传至FTP服务器
  2. 自动打包工具的作用是生成一段执行脚本的代码(如sh build.sh debug 1),用户也可直接在Shell下使用上面产生的命令操作,这样做方便一些不了解脚本的用户使用。没有设置成一键打包上传的原因在于,这种可以方便用户在终端查看LOG信息。
  3. 文件的放置位置很关键,整个脚本的运行基于文件所在目录进行操作。

Shell脚本分析

SECONDS=0
# 是否编译工作空间 (例:若是用Cocopods管理的.xcworkspace项目,赋值true; 用Xcode默认创建的.xcodeproj, 赋值false)
is_workspace="true"
# 指定项目的scheme名称
scheme_name="DEMO"
# 设置导出IPA包的名称 如DEMO导出包名为DEMO.ipa
export_iap_name="DEMO"
# 工程中Target对应的配置plist文件名称, Xcode默认的配置文件为Info.plist
info_plist_name="Info"
# 指定要打包编译的方式 : Release,Debug...$1
build_configuration=$1

echo "\n\033[32;1m************************* 您选择了 $build_configuration 模式 ************************* \033[0m\n"

# 导出ipa所需要的plist文件路径 (默认为AdHocExportOptionsPlist.plist)
ExportOptionsPlistPath="./shell/AdHocExportOptionsPlist.plist"
# 返回上一级目录,进入项目工程目录
cd ..
# 获取项目名称
project_name=`find . -name *.xcodeproj | awk -F "[/.]" '{print $(NF-1)}'`
# 获取版本号,内部版本号,bundleID
info_plist_path="$project_name/$info_plist_name.plist"
bundle_version=`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $info_plist_path`
bundle_build_version=`/usr/libexec/PlistBuddy -c "Print CFBundleIdentifier" $info_plist_path`
bundle_identifier=`/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $info_plist_path`

# 强制删除旧的文件夹
rm -rf ./$scheme_name-IPA
# 指定输出ipa路径
export_path=./$scheme_name-IPA
# 指定输出归档文件地址
export_archive_path="$export_path/$scheme_name.xcarchive"
# 指定输出ipa地址
export_ipa_path="$export_path"
# 指定输出ipa名称 : scheme_name + bundle_version
suffix=`date +"%m%d%H%M"`
ipa_name="$scheme_name-v$bundle_version_$suffix"
version="$bundle_version.$suffix"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $version" "$info_plist_path"
# certifcate
CODE_SIGN_DISTRIBUTION="iPhone Distribution: USERNAME (Q2J5575DBC)"
CODE_SIGN_DEVELOPMENT="iPhone Developer: USERNAME (YXP3A9ACE8)"

以上代码主要为配置项目的基础参数

method = $2
if test -n "$method"
then
if test "$method" = "1" ; then
ExportOptionsPlistPath="./shell/AdHocExportOptionsPlist.plist"
elif [ "$method" = "2" ]; then
ExportOptionsPlistPath="./shell/AppStoreExportOptionsPlist.plist"
elif [ "$method" = "3" ]; then
ExportOptionsPlistPath="./shell/EnterpriseExportOptionsPlist.plist"
elif [ "$method" = "4" ]; then
ExportOptionsPlistPath="./shell/DevelopmentExportOptionsPlist.plist"
else
echo "\n\033[31;1m************************* 您输入的参数无效!!! *************************\033[0m\n"
exit 1
fi
else
UPLOADFIR=false
fi


echo "\033[32m************************* 开始构建项目 ************************* \033[0m\n"
# 指定输出文件目录不存在则创建
if test -d "$export_path" ; then
echo $export_path
else
mkdir -pv $export_path
fi

if $is_workspace ; then
echo "\n\033[32m************************* 开始pod ************************* \033[0m"
pod install --verbose --no-repo-update
echo "\033[32m************************* pod完成 ************************* \033[0m\n"

以上代码为根据外部传入的参数,获取输出打包的类型,ad-hoc/appStore/企业证书等 -> 创建Archive包的输出路径,UPLOADFIR等参数在上传FTP服务器中使用不到,可忽略 -> POD项目

if test $build_configuration="Debug" ; then
echo "\n\033[32;1m************************* 您选择了以 xcworkspace-Debug 模式打包 *************************\033[0m"
# step 1. Clean
xcodebuild clean -workspace $project_name.xcworkspace -scheme $scheme_name -configuration $build_configuration -alltargets
# step 2. Build
xcodebuild -workspace $project_name.xcworkspace -scheme $scheme_name -sdk iphoneos -configuration $build_configuration -CODE_SIGN_IDENTITY=$CODE_SIGN_DEVELOPMENT
# step 3. Archive
xcodebuild archive -workspace $project_name.xcworkspace -scheme $scheme_name -configuration $build_configuration -archivePath $export_archive_path
elif [ $build_configuration="Release" ]; then
echo "\n\033[32;1m************************* 您选择了以 xcworkspace-Release 模式打包 *************************\033[0m"
# step 1. Clean
xcodebuild clean -workspace $project_name.xcworkspace -scheme $scheme_name -configuration $build_configuration -alltargets
# step 2. Build
xcodebuild -workspace $project_name.xcworkspace -scheme $scheme_name -sdk iphoneos -configuration $build_configuration -CODE_SIGN_IDENTITY=$CODE_SIGN_DISTRIBUTION
# step 3. Archive
xcodebuild archive -workspace $project_name.xcworkspace -scheme $scheme_name -configuration $build_configuration -archivePath $export_archive_path
else
echo "\n\033[31;1m************************* 您定义的打包方式的不正确 😢 😢 😢 *************************\033[0m\n"
echo "Usage:\n"
echo "sh build.sh Debug"
echo "sh build.sh Release"
exit 1
fi
else
if test $build_configuration="Debug" ; then
echo "\n\033[32;1m************************* 您选择了以 xcodeproj-Debug 模式打包 *************************\033[0m"
# step 1. Clean
xcodebuild clean -project $project_name.xcodeproj -scheme $scheme_name -configuration $build_configuration -alltargets
# step 2. Build
xcodebuild -project $project_name.xcodeproj -scheme $scheme_name -sdk iphoneos -configuration $build_configuration -CODE_SIGN_IDENTITY=$CODE_SIGN_DEVELOPMENT
# step 3. Archive
xcodebuild archive -project $project_name.xcodeproj -scheme $scheme_name -configuration $build_configuration -archivePath $export_archive_path
elif [ $build_configuration="Release" ]; then
echo "\n\033[32;1m************************* 您选择了以 xcodeproj-Release 模式打包 *************************\033[0m"
# step 1. Clean
xcodebuild clean -project $project_name.xcodeproj -scheme $scheme_name -configuration $build_configuration -alltargets
# step 2. Build
xcodebuild -project $project_name.xcodeproj -scheme $scheme_name -sdk iphoneos -configuration $build_configuration -CODE_SIGN_IDENTITY=$CODE_SIGN_DISTRIBUTION
# step 3. Archive
xcodebuild archive -project $project_name.xcodeproj -scheme $scheme_name -configuration $build_configuration -archivePath $export_archive_path
else
echo "\n\033[31;1m************************* 您定义的打包方式的不正确 😢 😢 😢 *************************\033[0m\n"
echo "Usage:\n"
echo "sh build.sh Debug"
echo "sh build.sh Release"
exit 1
fi
fi

# 检查是否构建成功
# xcarchive 实际是一个文件夹不是一个文件所以使用 -d 判断
if test -d "$export_archive_path" ; then
echo "\n\033[32;1m************************* 项目构建成功 🚀 🚀 🚀 *************************\033[0m\n"
else
echo "\n\033[31;1m************************* 项目构建失败 😢 😢 😢 *************************\033[0m\n"
exit 1
fi

echo "\033[32m************************* 开始导出ipa文件 ************************* \033[0m"
xcodebuild -exportArchive -archivePath $export_archive_path -exportPath $export_ipa_path -exportOptionsPlist $ExportOptionsPlistPath
# 修改ipa文件名称
mv $export_ipa_path/$scheme_name.ipa $export_ipa_path/$export_iap_name.ipa

# 检查文件是否存在
if test -f "$export_ipa_path/$export_iap_name.ipa" ; then
echo "\n\033[32;1m************************* 导出 $ipa_name.ipa 包成功 🎉 🎉 🎉 *************************\033[0m\n"
fi

以上代码为根据外部传入Debug/Release参数配置打包类型,然后进行项目的clean、build、archive、exportIPA包等操作

#SFTP配置信息
#用户名
USER="XXXXX"
#密码
PASSWORD="XXXXX"
#待上传文件根目录
SRCDIR="$export_ipa_path/$export_iap_name.ipa"
#IP
IP=133.33.33.33
#端口
PORT=21

#修改folderName为上传的FTP目录
curl -u $USER:$PASSWORD -T $SRCDIR ftp://$IP/FOLDERNAME/FOLDERNAME/

exit 0

以上代码为上传导出的IPA包至FTP服务器的具体目录下

遇到的问题

  • 打包的时候产生错误,因为plist中用到的所有配置文件未存在于~/Library/MobileDevice/Provisioning Profiles路径下
  • 自动打包工具放置位置错误会导致调用脚本文件失败
  • 起初上传脚本使用的为ftp命令,但是在最新版的MAC系统此命令被禁用,后修改为crul命令

工具以及相关文件GitHub地址

脚本文件中有一些不必要的参数和语句可自行删除,打包工具目前根据公司项目只配置了ad-hoc和Appstore,如果需要企业证书,可自己使用脚本命令运行build.sh进行操作。

因为涉及一些公司相关文件,所以很多图片相关信息都进行了打码处理,有不懂的可以私聊或者评论文章,我会在看到后第一时间回复。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容