美文网首页
iOS自动打包流程

iOS自动打包流程

作者: AdamShi | 来源:发表于2022-07-08 10:47 被阅读0次

做完了iOS jenkins自动打包,做个小总结,最好申请个MacBook或者MacMini作为专门的打包机.
有些老插件很久不更新了,新版本的jenkins不兼容这些老插件,或者有bug,最后几乎都是用脚本搞定的.
有些问题找了很久,网上的文章很多都是很久以前的,现在不适用了; 而且很多文章看着日期是最近的,结果内容是拷贝其他的老文章; 有的甚至把很久以前过时不能用的文章抄袭过来,还特么的收费,鄙视CSDN....
后面有时间的话还需要研究组件化怎么自动打包...
参考文章: 参考文档

一.开发环境

1.安装Xcode

2.安装homebrew, rvm等工具

3.安装java,配置java环境变量,安装Jenkins

这一步没啥好说的,网上内容很多

二.Jenkins配置

1.全局属性:系统管理-系统配置-全局属性:

key: PATH
value: 在终端中输入echo $PATH将输出内容复制填写。

2.插件

Git Parameter(用于git分支参数化构建)
xcode integration(没用到)
Keychains and Code Signing Identities(没用到,很长时间不更新的老插件, 新版本的jenkins上能安装,但是上传有bug; 2.263.4 版本以前的jenkins才能用)
Environment Injector(没用到,job内部环境变量)

3.参数化构建

git参数

Git Parameter插件: 分支可智能排序,我用的DESCENDING_SMART,按时间倒序,最新的分支在上面

选项参数:

Scheme(项目target), Configuration(Debug,Release), Method(development, app-store)

字符参数:

Tips(简短信息,比如哪块需要重点测,等等)

三.打包方案

1.shell:

脚本打包方式,较为主流,灵活可控,不用侵入工程中

a.生成项目所需的plist文件
b.有用的脚本

#!/bin/sh
#!/bin/bash --login(fir-cli需要用这个)

export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

解锁对login.keychain的访问,codesign可能会用到( 我暂时没用到这些,如果需要使用,自己试试路径啥的对不对)
这两个不知道哪个对,可以都试试
(1).security unlock-keychain -p "password" $HOME/Library/Keychains/login.keychain

(2).

ln -s ~/Library/Keychains/login.keychain-db ~/Library/Keychains/login.keychain
security unlock-keychain -p "login pwd" ~/Library/Keychains/login.keychain
c.获取git最后一次commit提交记录的message信息

网上能查到的信息是一个jenkins插件,但最新版本jenkins不能用; 后来想到git命令估计可以实现,果然有这个命令,cd到工程下,然后执行这个脚本命令
git_change_log=$(git log --pretty=format:“%s” -1)

d.最终脚本

这个脚本不能直接拿去用,只能作为参考,因为是根据我自己项目需要所写的脚本,需要做一些提前设置,比如安装配置一些cli工具,创建plist文件和一些文件夹等等.另外做了脱敏处理,删掉了一部分脚本,去掉了一些项目信息,XXX的地方要根据自己项目,或者是根据自己的电脑用户路径等等做修改.

#!/bin/sh --login
export LANG=en_US.UTF-8

echo "===========构建参数=========="
if test "$Configuration" = "Test"; then
    Configuration_CN="测试环境"
elif test "$Configuration" = "TF"; then
    Configuration_CN="TestFlight环境"
else
    Configuration_CN="正式环境"
fi

if test "$Method" = "development"; then
    Method_CN="普通包"
else
    Method_CN="上线包"
fi

echo "=====分支: ${Branch}"
echo "=====target: ${Scheme}"
echo "=====网络环境: ${Configuration_CN}${Configuration}"
echo "=====包类型: ${Method_CN}${Method}"
echo "=====小提示: ${Tips}"

echo "===========打包前的参数=========="

# 计时 
SECONDS=0

# 工程名(根据项目自行填写)
WORKSPACE_NAME="XXX"

# TARGET名称(根据项目自行填写)
SCHEME_NAME=${Scheme}

# 设置配置标识,编译环境
configuration=${Configuration}

# 工程源码目录
CODE_PATH="${WORKSPACE}"

# 导包方式
EXPORT_METHOD=${Method}

# 日期
DATE=$(date +%Y-%m-%d_%H-%M-%S)
# xcarchive文件名字
ARCHIVE_NAME="${SCHEME_NAME}_${DATE}_${Configuration}_${Method}.xcarchive"
# 存放ipa的文件夹名称
IPA_FOLDER_NAME="${SCHEME_NAME}_${DATE}_${Configuration}_${Method}"

#路径
ROOT_PATH="/Users/adamshi/Documents/Work/Archive"
# xcarchive文件路径
ARCHIVE_PATH="${ROOT_PATH}/XCArchive/${SCHEME_NAME}/${ARCHIVE_NAME}"
#要上传的ipa文件路径 
IPA_PATH="${ROOT_PATH}/IPA/${SCHEME_NAME}/${IPA_FOLDER_NAME}"
echo "ARCHIVE_PATH: ${ARCHIVE_PATH}"
echo "IPA_PATH: ${IPA_PATH}"


# 导包方式配置文件路径
if test "$EXPORT_METHOD" = "ad-hoc"; then
    EXPORT_METHOD_PLIST_PATH=${ROOT_PATH}/Plist/AdHocExportOptions.plist
elif test "$EXPORT_METHOD" = "app-store"; then
    EXPORT_METHOD_PLIST_PATH=${ROOT_PATH}/Plist/AppStoreExportOptios.plist
elif test "$EXPORT_METHOD" = "enterprise"; then
    EXPORT_METHOD_PLIST_PATH=${ROOT_PATH}/Plist/EnterpriseExportOptions.plist
else
    EXPORT_METHOD_PLIST_PATH=${ROOT_PATH}/Plist/DevelopmentExportOptions.plist
fi

# 指ipa定输出文件夹,如果有删除后再创建,如果没有就直接创建
if test -d ${IPA_PATH}; then
    rm -rf ${IPA_PATH}
    mkdir -pv ${IPA_PATH}
    echo ${IPA_PATH}
else
    mkdir -pv ${IPA_PATH}
fi

# 进入工程源码根目录
cd "${CODE_PATH}"

# 执行pod
#pod install --verbose --no-repo-update

#mkdir -p build

echo "===========开始打包=========="

# 清除工程
echo "++++++++++++++++clean++++++++++++++++"
xcodebuild clean -workspace ${WORKSPACE_NAME}.xcworkspace \
                 -scheme ${SCHEME_NAME} \
                 -configuration ${configuration}
                 

# 将app打包成xcarchive格式文件
echo "+++++++++++++++++archive+++++++++++++++++"
xcodebuild archive -workspace ${WORKSPACE_NAME}.xcworkspace \
                   -scheme ${SCHEME_NAME} \
                   -configuration ${configuration} \
                   -archivePath ${ARCHIVE_PATH}
                  
#xcarchive文件非空判断
if [ -e "${ARCHIVE_PATH}" ];then
    echo "生成xcarchive成功"
else
    echo "生成xcarchive失败,停止构建"
    exit 1
fi


# 将xcarchive格式文件打包成ipa
echo "+++++++++++++++++ipa+++++++++++++++++"
xcodebuild -exportArchive \
           -archivePath ${ARCHIVE_PATH} \
           -exportPath "${IPA_PATH}" \
           -exportOptionsPlist ${EXPORT_METHOD_PLIST_PATH} \
           -allowProvisioningUpdates
           
#IPA文件非空判断
if [ -e "${IPA_PATH}" ];then
    echo "生成IPA成功"
else
    echo "生成IPA失败,停止构建"
    exit 1
fi
                          

echo "===========打包完成后的参数=========="

#最后一次git提交记录的message信息
git_change_log=$(git log --pretty=format:“%s” -1)

#代码工程内商户对应的info.plist路径
scheme_infoplist_path="${CODE_PATH}/${SCHEME_NAME}/${SCHEME_NAME}.plist"
#获取DisplayName(有的target和displayName不一样)
Bundle_Display_Name=$(/usr/libexec/PlistBuddy -c "print :CFBundleDisplayName" "${scheme_infoplist_path}")
echo "Bundle_Display_Name: ${Bundle_Display_Name}"

#xcarchive包内的plist路径
xcarchive_infoplist_path="${ARCHIVE_PATH}/Info.plist"
#BundleID
BundleID=$(/usr/libexec/PlistBuddy -c "print :ApplicationProperties:CFBundleIdentifier" "${xcarchive_infoplist_path}")
#版本号
versionNumber=$(/usr/libexec/PlistBuddy -c "print :ApplicationProperties:CFBundleShortVersionString" "${xcarchive_infoplist_path}")
#build号
buildNumber=$(/usr/libexec/PlistBuddy -c "print :ApplicationProperties:CFBundleVersion" "${xcarchive_infoplist_path}")
echo "BundleID: ${BundleID}"
echo "versionNumber: ${versionNumber}"
echo "buildNumber: ${buildNumber}"

#符号表上传bugly相关参数
dSYM_Path=${ARCHIVE_PATH}/dSYMs/${Bundle_Display_Name}.app.dSYM
bugly_platform="IOS"
if test "$SCHEME_NAME" = "XXX"; then
    bugly_appid="1234567890"
    bugly_appkey="1234567890"
elif test "$SCHEME_NAME" = "YYY"; then
    bugly_appid="abcdefgh"
    bugly_appkey="abcdefgh"
else
    bugly_appid=""
    bugly_appkey=""
fi

echo "==========上传内测托管平台=========="

if test "$EXPORT_METHOD" = "app-store"; then

    echo "==========线上包逻辑=========="
    echo "==========开始上传阿里云=========="
    
    #平台名
    Platform_Name="ipa包已上传阿里云OSS, \n\
                    符号表文件已上传bugly"
    #app icon base64
    Image_Base64=$(base64 ${ROOT_PATH}/Icon/${SCHEME_NAME}.png)

    

    #ipa名字
    Ipa_Name=${SCHEME_NAME}_${DATE}_V${versionNumber}_${Ipa_Configuration_Type}.ipa
    Ipa_Name_UTF8=${SCHEME_NAME}_${DATE}_V${versionNumber}_${Ipa_Configuration_UTF8}.ipa

    #下载地址
    Download_URL="https://shenzhen.aliyuncs.com/iOS/${SCHEME_NAME}/${Ipa_Name_UTF8}"
    echo "阿里云OSS下载地址: ${Download_URL}"
    
    #app-store, 企业签或TF签, 上传alioss
    /Users/adamshi/ossutilmac64 cp ${IPA_PATH}/${Bundle_Display_Name}.ipa oss://file-app/iOS/${SCHEME_NAME}/${Ipa_Name}
    
    echo "==========阿里云上传结束=========="

    echo "==========即将上传符号表到bugly=========="
    
    #上传符号表到bugly
    java -jar /Users/adamshi/Documents/Work/Archive/Bugly/buglyqq-upload-symbol.jar \
         -appid ${bugly_appid} \
         -appkey ${bugly_appkey} \
         -bundleid ${BundleID} \
         -version ${versionNumber} \
         -platform ${bugly_platform} \
         -inputSymbol ${dSYM_Path}
         
    echo "==========符号表已上传bugly=========="
    
else
    echo "==========测试包逻辑==========="
    echo "==========开始上传fir=========="
    
    Short="${SCHEME_NAME}${configuration}"

    #测试包, 上传fir
    fir publish ${IPA_PATH}/${Bundle_Display_Name}.ipa -H \
                                                       -Q \
                                                       -S \
                                                       -s "${Short}" \
                                                       -T aaaaaaaaaa \
                                                       -c "${SCHEME_NAME}_${BUILD_NUMBER} 
                                                            分支: ${Branch}
                                                            changeLog: ${git_change_log}
                                                            Tips: ${Tips}" 
                                                            
    
    #平台名
    Platform_Name="已上传至Fir"
    #二维码base64
    Image_Base64=$(base64 ${IPA_PATH}/fir-${Bundle_Display_Name}.png)
    Ipa_Configuration_Type="IPA包"
    #ipa名字
    Ipa_Name=${SCHEME_NAME}_${DATE}_V${versionNumber}_${Ipa_Configuration_Type}.ipa
    #下载地址
    Download_URL="http://d.maps9.com/${Short}" 
    
    echo "fir下载地址: ${Download_URL}"
    
    echo "==========上传fir结束=========="
fi

echo "==========删除工程文件=========="
rm -rf $ARCHIVE_PATH
rm -rf $IPA_PATH
echo "已删除构建时生成的xcarchive和IPA文件"

echo "==========开始发送teams通知=========="

#图片url
Image_Base64_URL="data:image/png;base64,${Image_Base64}"
#Image_Base64_URL="https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=Applelogo&step_word=&hs=0&pn=3&spn=0&di=7108135681917976577&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&istype=2&ie=utf-8&oe=utf-8&in=&cl=2&lm=-1&st=-1&cs=2040973445%2C2450782249&os=1098261057%2C2881870715&simid=4105555652%2C494769902&adpicid=0&lpn=0&ln=1341&fr=&fmq=1657265865057_R&fm=result&ic=&s=undefined&hd=1&latest=0&copyright=0&se=&sme=&tab=0&width=&height=&face=undefined&ist=&jit=&cg=&bdtype=0&oriquery=&objurl=https%3A%2F%2Fgimg2.baidu.com%2Fimage_search%2Fsrc%3Dhttp%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F01%2F21%2F32%2F5905a3b241978_610.jpg%26refer%3Dhttp%3A%2F%2Fpic.51yuansu.com%26app%3D2002%26size%3Df9999%2C10000%26q%3Da80%26n%3D0%26g%3D0n%26fmt%3Dauto%3Fsec%3D1659857895%26t%3D26f6c80dd9bbde7af85a66b6b07f69b1&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bc8y7wgf7_z%26e3Bv54AzdH3FfvAzdH3Ffssgphxzzp_z%26e3Bip4s&gsm=4&rpstart=0&rpnum=0&islist=&querylist=&nojc=undefined&dyTabStr=MCwzLDYsMiw0LDEsNSw3LDgsOQ%3D%3D"

echo "teams参数: 
        Ipa_Name: ${Ipa_Name}
        git_change_log:${git_change_log}
        Tips: ${Tips}
        Platform_Name:${Platform_Name}
        Download_URL:${Download_URL}
        Image_Base64_URL:${Image_Base64_URL}"

#teams发通知
curl -H 'Content-Type: application/json' \
     -d "{
   \"type\":\"message\",
   \"attachments\":[
      {
         \"contentType\":\"application/vnd.microsoft.card.adaptive\",
         \"contentUrl\":null,
         \"content\":{
            \"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
            \"type\": \"AdaptiveCard\",
            \"version\": \"1.0\",
            \"body\": [
                {
                    \"type\": \"FactSet\",
                    \"facts\": [
                        {
                            \"title\": \"Git分支:\",
                            \"value\": \"${Branch}\"
                        },
                        {
                            \"title\": \"Target:\",
                            \"value\": \"${Scheme}\"
                        }
                    ]
                },
                {
                    \"type\": \"FactSet\",
                    \"facts\": [
                        {
                            \"title\": \"网络环境:\",
                            \"value\": \"${Configuration_CN}${Configuration}\"
                        },
                        {
                            \"title\": \"上线包或普通包:\",
                            \"value\": \"${Method_CN}\"
                        }
                    ]
                },
                {
                    \"type\": \"FactSet\",
                    \"facts\": [
                        {
                            \"title\": \"Tips:\",
                            \"value\": \"${Tips}\"
                        },
                        {
                            \"title\": \"Git最后提交内容:\",
                            \"value\": \"${git_change_log}\"
                        }
                    ]
                },
                {
                    \"type\": \"FactSet\",
                    \"facts\": [
                        {
                            \"title\": \"iOS-IPA包名:\",
                            \"value\": \"${Ipa_Name}\"
                        },
                        {
                            \"title\": \"内测托管平台:\",
                            \"value\": \"${Platform_Name}\"
                        }
                    ]
                },
                {
                    \"type\": \"Image\",
                    \"url\": \"${Image_Base64_URL}\",
                    \"size\": \"Stretch\",
                    \"width\": \"200px\",
                    \"height\": \"200px\",
                    \"horizontalAlignment\": \"Center\"
                },
                {
                    \"type\": \"ActionSet\",
                    \"actions\": [
                        {
                            \"type\": \"Action.OpenUrl\",
                            \"id\": \"9cbbcc71-be19-8f72-524d-5aa6c8a096e8\",
                            \"title\": \"去下载\",
                            \"url\": \"${Download_URL}\"
                        }
                    ],
                    \"horizontalAlignment\": \"Left\"
                }
            ],
            \"padding\": \"None\",
            \"@type\": \"AdaptiveCard\",
            \"@context\": \"http://schema.org/extensions\"
        }
      }
   ]
}" \
https://hyperlegend.webhook.office.com/webhookb2/xxxxx

#发送teams通知结束
echo "==========发送teams通知结束=========="


# 输出打包总用时
echo "==========打包总用时: ${SECONDS}s=========="

2.plugin:

xcode integration插件打包,最终没用这个方案

3.fastlane:

类似cocoapods的模式,比较方便,也很强大,但是会有一些配置文件侵入到工程中,也没用这个方案

4.Xcode Server

苹果官方的自动打包方案,集成在xcode里面,比较简单方便,但是好像用的人不多,不如jenkins功能那么全面

四.上传内测平台

1.蒲公英

网上文章较多,不多介绍

2.fir

安装fir-cli工具,添加脚本

3.阿里云oss

安装和配置阿里云oss工具:ossutil和ossbrowser; 添加上传ipa包到oss的脚本

五.符号表上传

1.友盟

2.bugly

下载bugly的jar工具,配置脚本

六.发送通知

1.钉钉

配置webhook

2.企业微信

配置webhook

3.微软Teams(这玩意真难用....)

配置Incoming Webhooks, 调用curl命令

七.节点

把打包机设置成打包子节点,然后在运维的jenkins网站上配置好子节点,就可以多人使用了,开发和测试都可以比较舒服的打包

八.内网穿透,内网映射到外网

如果想远程多人使用,又没有配置节点,可以做内网穿透; 收费版本会稳定,网速也比较好, 但是其实免费版本就够用了,只不过不太稳定...
有几种方式:

(一).ngrok

1.国外官网ngrok

https://ngrok.com/
国外服务器,比较慢,而且会有个中间页,需要做其他配置才能去除中间页; 而且没有免费版

2.小米球ngrok

也是基于ngrok,但是服务器在国内,速度较快; 不过免费版不太稳定,经常报错,报错的话,刷新一下网址就行; VIP是一次性付款,永久使用,还算合适

3.Sunny-Ngrok

https://www.ngrok.cc/
服务器在国内,也有免费版,免费版也是不稳定; 收费版是每月订阅,需要一直付钱,看需要吧

4.natapp

https://natapp.cn/
同上

(二). Frp

国内的:
https://gofrp.org/

(三).其他工具

内网穿透工具比较(ngrok,frp,lanproxy,goproxy,nps)

九.提高打包编译速度

ccache

十.遇到的问题和坑

2022-10-12 17:49:29.074 xcodebuild[31843:10154938]  DVTPortal: Service '<DVTPortalViewDeveloperService: 0x600003729100; action='viewDeveloper'>' encountered an unexpected result code from the portal ('1100')
2022-10-12 17:49:29.074 xcodebuild[31843:10154938]  DVTPortal: Error:
Error Domain=DVTPortalServiceErrorDomain Code=1100 "Your session has expired. Please log in." UserInfo={payload={
    creationTimestamp = "2022-10-12T09:49:29Z";
    httpCode = 200;
    protocolVersion = QH65B2;
    requestUrl = "[https://developerservices2.apple.com/services/QH65B2/viewDeveloper.action](https://developerservices2.apple.com/services/QH65B2/viewDeveloper.action)";
    responseId = "3f0a5d82-c60b-4332-bd82-fcff6b2a6d17";
    resultCode = 1100;
    resultString = "Your session has expired. Please log in.";
    userLocale = "en_US";
    userString = "Your session has expired. Please log in.";
}, NSLocalizedDescription=Your session has expired. Please log in.}

遇到这样的报错,说是登录过期,请重新登录.
解决办法:
我试过前两种方法,都是好不了多长时间,可能又会出现; 然后我试了第三种方法,目前解决了,没再出现这个问题

1.重新下载证书文件

Xcode-Preferences-Accounts-选中账号,点击Download Manuel Profiles.重新下载证书文件

2.重新登录

Xcode-Preferences-Accounts退出账号,然后重新登录,然后下载证书文件

3.重新获取权限

先把xcode账户退出登录 - 把xcode退出-终端执行如下命令

defaults write com.apple.dt.Xcode DVTDeveloperAccountUseKeychainService_2 -bool NO

打开xcode,重新登录账户,然后下载相关证书; 打包过程中会重新申请权限,点始终允许
来源: Using Automatic Code Signing from the Command Line via SSH Session

4.打包命令添加解锁逻辑

security unlock-keychain -p PASSWORD

来源: Constant "Your session has expired" (error 1100)

5.打开两步验证

Xcode export/upload error: Your session has expired. Please log in

相关文章

  • iOS - fastlane自动化打包

    iOS自动化打包,我推荐fastlane 方案。fastlane 的原理又是如何?实现自动化打包,又有什么流程? ...

  • 利用Jenkins实现iOS自动化打包

    之前做iOS自动化打包这一块,找了很多资料,一直没有特别全的iOS打包流程。所以,花费了很多力气来处理iOS打包遇...

  • iOS-自动打包及分发(二)

    iOS-自动打包及分发(一)iOS-自动打包及分发(二)iOS-自动打包及分发(三) 本篇介绍:自动打包及分发xc...

  • iOS效率神器fastlane自动打包

    iOS效率神器fastlane自动打包 iOS效率神器fastlane自动打包

  • Xcode自动打包

    [iOS]从零开始写个自动打包IPA脚本 【iOS打ipa包】:使用终端实现自动打包 iOS自动打包并发布脚本

  • iOS自动打包流程

    由于公司业务所以上网查询了一些关于iOS自动打包流程. 一种是以shell脚本为主的打包,一种是以jenkins作...

  • iOS自动打包流程

    做完了iOS jenkins自动打包,做个小总结,最好申请个MacBook或者Macmini作为专门的打包机.有些...

  • iOS 自动化打包

    iOS 自动化打包 [iOS, 自动化, 打包, Python, fastlane] iOS在项目开发中少不了打包...

  • iOS使用fastlane自动化打包

    iOS使用fastlane自动化打包 iOS使用fastlane自动化打包

  • Python的iOS自动化打包

    Python的iOS自动化打包 Python的iOS自动化打包

网友评论

      本文标题:iOS自动打包流程

      本文链接:https://www.haomeiwen.com/subject/lqzmbrtx.html