从上图可以看出使用自动化出包,可以优化掉好几个需要人工介入的步骤,优化开发流程,节省开发者的时间。
自动打包的原理概不累述了,测试过程中如果有问题,可以用终端 cd
到项目目录,单独执行出问题的语句,再把错误的输出丢到搜索引擎,只要相信你遇到的问题别人肯定也会遇到,就一定能得到解决。如果有例外,那我相信——能弄出史无前例的问题的你,一定也厉害到可以史无前例的予以解决~当然也可以试着给我留言,说不定三个臭皮匠果真赛过诸葛亮。
脚本内容基本是基于网络上内容,做了整合,修复了一些可能会导致打包失败的错误。将打印添加颜色输出,以及添加了一些注释。
一、参考
延伸知识:多渠道自动打包
二、脚本源码 已做脱敏处理。
自动打包并上传 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 SECONDS=0 project_name=xxxxx scheme_name=xxxxx info_plist_name="Info" development_mode=Release fir_token="xxxxx" apple_account="xxxxx" apple_password="xxxxx" project_path=$(cd `dirname $0 `; pwd ) archive_path=${project_path} /PackageArchived build_path=${project_path} /AutoBuild exportOptionsPlistPath=${project_path} /exportTest.plist DATE=`date '+%Y-%m-%d-%H-%m-%S' ` exportIpaPath=${archive_path} /${development_mode-$DATE} version=$(sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' ${project_name} .xcodeproj/project.pbxproj) ipa_name="$scheme_name -v$version " if [ ! -d "$archive_path " ];then mkdir -p "$archive_path " ; else rm -rf "$archive_path " mkdir -p "$archive_path " fi if [ -d "$build_path " ]; then rm -rf "$build_path " mkdir -p "$build_path " fi echo "\033[34;1m请选择打包方式(输入序号,按回车即可) \033[0m" echo "\033[32;1m1:app-store \033[0m" echo "\033[32;1m2:ad-hoc \033[0m" read numberwhile ([[ $number != 1 ]] && [[ $number != 2 ]])do echo "\033[31m错误! 请输入 1 或者 2\033[0m" echo "\033[34;1m请选择打包方式(输入序号,按回车即可) \033[0m" echo "\033[32;1m1:app-store \033[0m" echo "\033[32;1m2:ad-hoc \033[0m" read numberdone if [ $number == 1 ];then development_mode=Release exportOptionsPlistPath=${project_path} /exportAppstore.plist else development_mode=Debug exportOptionsPlistPath=${project_path} /exportTest.plist fi echo '\033[33;1m///-----------\033[0m' echo '\033[33;1m/// 正在清理工程\033[0m' echo '\033[33;1m///-----------\033[0m' xcodebuild \ clean -configuration ${development_mode} -quiet || exit echo '\033[32;1m///--------\033[0m' echo '\033[32;1m/// 清理完成\033[0m' echo '\033[32;1m///--------\033[0m' echo '' echo '\033[33;1m///-------------\033[0m' echo "\033[33;1m/// 正在编译工程: ${development_mode} \033[0m" echo '\033[33;1m///-------------\033[0m' xcodebuild \ archive -workspace ${project_path} /${project_name} .xcworkspace \ -scheme ${scheme_name} \ -configuration ${development_mode} \ -archivePath ${build_path} /${project_name} .xcarchive -quiet || exit echo '\033[32;1m///-------------\033[0m' echo '\033[32;1m/// 编译完成 \033[0m' echo '\033[32;1m///-------------\033[0m' echo '' echo '\033[33m///-------------\033[0m' echo '\033[33m/// 开始ipa打包\033[0m' echo '\033[33m///-------------\033[0m' xcodebuild -exportArchive -archivePath ${build_path} /${project_name} .xcarchive \ -configuration ${development_mode} \ -exportPath ${exportIpaPath} \ -exportOptionsPlist ${exportOptionsPlistPath} \ -allowProvisioningUpdates \ -quiet || exit mv $exportIpaPath /$scheme_name .ipa $exportIpaPath /$ipa_name .ipaif [ -e $exportIpaPath /$ipa_name .ipa ]; then echo '\033[32;1m///-------------\033[0m' echo "\033[32;1m导出 ${ipa_name} .ipa 包成功 🎉🎉🎉 \033[0m" echo '\033[32;1m///-------------\033[0m' open $exportIpaPath rm -rf "$build_path " else echo '\033[31;1m///-------------\033[0m' echo "\033[31;1m导出 ${ipa_name} .ipa 包失败 💔💔💔 \033[0m" echo '\033[31;1m///-------------\033[0m' exit 1fi echo '\033[36;1m///-------------\033[0m' echo "\033[36;1m/// 打包 ipa 完成。总耗时:${SECONDS} s \033[0m" echo '\033[36;1m///-------------\033[0m' echo '' echo '\033[33m///-------------\033[0m' echo '\033[33m/// 开始发布ipa包 \033[0m' echo '\033[33m///-------------\033[0m' if [ $number == 1 ];then altoolPath="/Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/Frameworks/AppStoreService.framework/Versions/A/Support/altool" "$altoolPath " --validate-app -f ${exportIpaPath} /${ipa_name} .ipa -u $apple_account -p $apple_password -t ios --output-format xml"$altoolPath " --upload-app -f ${exportIpaPath} /${ipa_name} .ipa -u $apple_account -p $apple_password -t ios --output-format xmlelse fir login -T $fir_token fir publish $exportIpaPath /$ipa_name .ipa --skip-update-icon echo '\033[33m///-------------\033[0m' echo '\033[33m/// 开始发送邮件给测试人员 \033[0m' echo '\033[33m///-------------\033[0m' python sendEmail.py "测试版本 (iOS)xxxxx v(${version} ) 上传成功" "赶紧下载体验吧:xxxxx" fi exit 0
上传成功成功后发送邮件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 import sysimport smtplibimport iofrom email.mime.text import MIMETextfrom email.header import Headerfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipartsender = 'lvkai@cutecatos.com;' to_receiver = ['xxxxx' ,'xxxxx' ] cc_receiver = ['xxxxx' ] smtpserver = 'smtp.exmail.qq.com' smtpport = 465 //smtp 配置,需要到邮箱账户设置界面自行获取 username = 'xxxxx' password = 'xxxxx' def send_mail (title, content ): try : subject = title msg = MIMEMultipart("related" ) if not isinstance (title,unicode): title = unicode(title, 'utf-8' ) msg['Subject' ] = title msg['From' ] = sender msg['To' ] = ";" .join(to_receiver) msg['Cc' ] = ";" .join(cc_receiver) msg["Accept-Language" ]="zh-CN" msg["Accept-Charset" ]="ISO-8859-1,utf-8" msgText = MIMEText(content,'plain' ,'utf-8' ) msg.attach(msgText) to_addrs=to_receiver+cc_receiver smtp = smtplib.SMTP_SSL(smtpserver,smtpport) smtp.login(username, password) smtp.sendmail(sender, to_addrs, msg.as_string()) smtp.quit() return True except Exception, e: print str (e) return False if send_mail(sys.argv[1 ], sys.argv[2 ]): print "🎉🎉🎉发送成功!" else : print "❌❌❌发送失败!"
三、问题 上传工具路径不对问题 解决方法来源:xcode11 构建上传问题
从原来的
1 /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool
变为了
1 /Applications/Xcode.app/Contents/SharedFrameworks/ContentDeliveryServices.framework/Versions/A/Frameworks/AppStoreService.framework/Versions/A/Support/altool
$(MARKETING_VERSION) 获取版本号失败 解决方法来源:How to handle $(MARKETING_VERSION) of Xcode 11 by CI
使用一下语句获取
1 2 3 4 5 6 7 version=$(sed -n '/MARKETING_VERSION/{s/MARKETING_VERSION = //;s/;//;s/^[[:space:]]*//;p;q;}' {your project name}.xcodeproj/project.pbxproj) if [ -z "${version} " ]; then echo "[ERROR] failed to get MARKETING_VERSION" exit 1 fi
错误信息:
1 2 3 4 5 Error: Errors uploading 'xxx.ipa' : ( "Error Domain=ITunesSoftwareServiceErrorDomain Code=-22014 \"We are unable to create an authentication session.\" UserInfo={NSLocalizedDescription=We are unable to create an authentication session., NSLocalizedFailureReason=Unable to validate your application.}" )
解决方式:到 https://appleid.apple.com 生成一个专用密码就行了,然后用这个密码改到上面去,再次执行。即:xcrun altool --upload-app -f a/b/xxx.ipa -u [xxxx@qq.com](mailto:xxxx@qq.com) -p 生成的专用密码