目前市面上持续集成的方案很多:例如,Jenkins, Fastlane,Xcode server等,这些持续集成的方案大同小异,他们之间的性能差异笔者没有做大量的横向分析,只是大体比较了一下打包时间.总结来说,持续集成主要是三个步骤:1.拉取代码;2.编译打包;3.分发数据(打包结果),下面将通过两种方案(Jenkins和Xcode server)来分析一下这三个过程.
Jenkins集成方案
Jenkins作为免费集成方案,其社区拥有大量插件,非常友好,所以用户也众多.
首先来安装Jenkins,Jenkins官网提供了多个系统环境的软件包,我选择的是macOs系统,选择下载安装,步骤如下图:
下载Jenkins
安装Jenkins
安装Jenkins.png
设置管理员账号密码
安装完成后,一般mac环境集成了Apache服务器会自动配置启动8080端口,Jenkins的初始化页面也会在安装完成后自动弹出.此时只要找到图中红色标记路径cat或者vi看一下里面的秘钥,进入Jenkins初始化设置工作.这个过程会设置管理员账号密码等.
获取初始密码Jenkins.png
Jenkins插件安装
初始化完成后,就可以利用管理员账号登录.登录后通常可以安装一些常用插件,一般有默认插件和自定义插件,选择默认插件即可.
Jenkins安装插件.png
基本的环境搭建完成后,就可以实施上面的三个过程了.其实Jenkins的主要工作流程,可以通过下图来直观看出来.
Jenkins工作流程.png
步骤1 拉取代码
git仓库分支配置.png
拉取代码过程比较简单,主要是从指定仓库中克隆代码到Jenkins的工作目录.
步骤2 编译打包
编译打包命令主要有xcodebuild,xcrun,xctool(facebook)等,前两个是官方的,后一个是Facebook出品,xctool里面集成了个性化定制,需要的可以细研究一下,文中只是对xcodebuild做出使用分析.
xcodebuild编译过程也主要分三个过程:
- clean xcodebuild -workspace MyWorkspace.xcworkspace -scheme SchemeName - archive xcodebuild archive -workspace MyWorkspace.xcworkspace -scheme SchemeName - export ipa xcodebuild -exportArchive -archivePath MyMobileApp.xcarchive -exportPath ExportDestination.ipa -exportOptionsPlist 'exportPlist.plist'
这里多说两句:由于IDE变化,导致编辑脚本稍微有一些出入,主要是在编译的第三步(- export ipa),这步Xcode 8.0需要指定描述文件,Xcode 9.0需要指定exportOptionsPlist(这个是主要包含一些证书, ipa模式等键值表).下面贴出打包执行脚本的全部命令(Xcode 9.0):
export ETT_APP_NAME=app名称 export ETT_WORKSPACE_NAME=工作区名称 export ETT_SCHEME=scheme名称 export ETT_PROVISIONING_PROFILE=描述文件(Xcode9.0用不到) export ETT_BUILD_TYPE=编译类型(用于区分发布还是AdHoc模式,可以忽略) export ETT_CONFIGURATION=编译配置(主要根据自己的多环境进行配置,比如Release,Debug等) ############################################################################################################### export ETT_JENKINS_TIME=$(date +%m%d) export ETT_GIT_COMMIT=${GIT_COMMIT:0:7} export ETT_GIT_REV=`git rev-list HEAD | wc -l | awk '{print $1}'` export ETT_VERSION_PRO=`/usr/bin/agvtool mvers -terse1` export ETT_VERSION_NUMBER=$ETT_VERSION_PRO$ETT_BUILD_TYPE export ETT_BUILD_VERSION=$ETT_GIT_REV.$BUILD_NUMBER export ETT_BUILD_ID=$ETT_VERSION_NUMBER-$ETT_JENKINS_TIME-$ETT_GIT_REV-$BUILD_NUMBER-G$ETT_GIT_COMMIT export NEXUS_JENKINS_NAME=打包后上传账号 export NEXUS_JENKINS_PASSWD=密码 export ExportOptionsPlistPath=/Users/用户/Downloads/zhengshu/ExportOptions.plist export XCODE=/usr/bin export ETT_DIST_ROOT_PATH=工作区路径 export ETT_DIST_PATH=$ETT_DIST_ROOT_PATH/$BUILD_NUMBER export ETT_ARCHIVE_PATH=$ETT_DIST_PATH/$ETT_APP_NAME.xcarchive export ETT_WORK_SPACE=$WORKSPACE/$ETT_WORKSPACE_NAME.xcworkspace export ETT_FILE_NAME=$ETT_APP_NAME-$ETT_BUILD_ID export ETT_IPA_NAME=$ETT_FILE_NAME.ipa export ETT_EXPORT_PATH=$ETT_DIST_PATH/$ETT_IPA_NAME export ETT_PACKAGE_NAME=$ETT_FILE_NAME.tar.gz export ETT_PACKAGE_PATH=$ETT_DIST_PATH/$ETT_PACKAGE_NAME export ETT_NEXUS_FILE_NAME=$ETT_APP_NAME-$ETT_JENKINS_TIME-$BUILD_NUMBER-$ETT_GIT_COMMIT.tar.gz export ETT_UPLOAD_DSYM_SRC=$ETT_WORKSPACE_NAME.app.dSYM export ETT_UPLOAD_DSYM_FILE=$ETT_FILE_NAME-dSYM.zip export ETT_UPLOAD_DSYM_PATH=$ETT_DIST_PATH/$ETT_UPLOAD_DSYM_FILE if [ ! -d "$ETT_DIST_ROOT_PATH" ]; then mkdir $ETT_DIST_ROOT_PATH fi if [ ! -d "$ETT_DIST_PATH" ]; then mkdir $ETT_DIST_PATH fi #/usr/bin/agvtool vers -terse #/usr/bin/agvtool mvers -terse1 /usr/bin/agvtool new-marketing-version $ETT_VERSION_PRO /usr/bin/agvtool new-version -all $ETT_VERSION_PRO.$ETT_BUILD_VERSION #/usr/bin/agvtool vers -terse #/usr/bin/agvtool mvers -terse1 $XCODE/xcodebuild clean build BITCODE_GENERATION_MODE=bitcode OTHER_CFLAGS="-fembed-bitcode" archive -archivePath "$ETT_ARCHIVE_PATH" -workspace $ETT_WORK_SPACE -destination generic/platform=iOS -scheme $ETT_SCHEME -configuration "$ETT_CONFIGURATION" BUILD_NUMBER="$ETT_BUILD_ID" CONFIGURATION_BUILD_DIR=$ETT_DIST_PATH UPLOAD_dSYM_FILE=$ETT_UPLOAD_DSYM_FILE $XCODE/xcodebuild -exportArchive -archivePath $ETT_ARCHIVE_PATH -exportPath $ETT_EXPORT_PATH -exportOptionsPlist $ExportOptionsPlistPath -allowProvisioningUpdates
步骤3 分发数据(发布打包)
这个过程可以直接发布,也可以上传到自己指定的服务器,第三方托管服务器等.我们直接在执行打包脚本的最后面,将打包处理的ipa文件以及符号化文件打包后直接上传到指定服务器:
cd $ETT_DIST_PATH zip -r $ETT_UPLOAD_DSYM_PATH $ETT_UPLOAD_DSYM_SRC tar -C $ETT_DIST_PATH -zcvf $ETT_PACKAGE_PATH $ETT_IPA_NAME $ETT_UPLOAD_DSYM_FILE curl -v -u $NEXUS_JENKINS_NAME:$NEXUS_JENKINS_PASSWD --upload-file $ETT_PACKAGE_PATH 服务器路径$ETT_APP_NAME/ios/$ETT_VERSION_PRO$ETT_BUILD_TYPE/$ETT_NEXUS_FILE_NAME
到这里,Jenkins的简单集成过程算完成了,里面涉及到一些环境变量和参数的设置,笔者因为还涉及到Swift和OC混合打包,问题稍多一点.因为业务需求不一样,需要自己去单独设置,有疑问的地方可以一起沟通一下.
Xcode Server集成方案
这个方案,将会把上面三个过程穿插进去,不在单列出来.网上有其他方案是macOS Server + Xcode Server集成方案,本文只是简单介绍一下通过Xcode Server集成
打开Xcode Server
打开Xcode Server.png
配置Xcode Server管理员账号
配置Xcode Server管理员账号.png
创建Bot(值守机器人)
配置完成后,然后通过Xcode->Product->Create Bot
创建值守机器人.png
配置仓库分支
配置代码仓库,Xcode集成了Git所以针对你的项目仓库直接添加分支即可.
配置仓库分支.png
编译打包参数配置
分支添加完成后,就可配置编译的一些选项:scheme,ExportOptionsPlist,Configuration等.
编译打包参数配置.png
构建触发器
构建触发器.png
构建触发器.png
添加签名文件
下一步添加证书,描述文件等,作者这里选择的是自动签名模式,如果需要可自己指定签名证书,描述文件等,这里不再细说.
添加签名文件.png
添加环境变量
添加环境变量.png
下一步就是添加编译之前和编译打包之后的动作
添加打包后的脚本命令
添加打包后的脚本命令.png
这里你可以把打包结果上传到指定位置,脚本可自行查找.
集成打包
机器人创建完成后会自动运行编译打包一次,下次打包可以直接通过点击Integrate触发打包.
集成打包.png
总结
两种方案,整个过程走下来并不是很复杂.这里提醒一下,由于Jenkins打包通过脚本命令执行编译打包,这个又依赖于一些环境变量和参数,如果一些插件和参数变了,IDE更新了,系统更新了等等原因,这些很容易造成打包失败,笔者经历多次了,一般就是先把命令拿到终端里面编译打包试一下,排除编译命令问题,然后在调试Jenkins环境.总结下来就是遇到问题时不要着急,慢慢分析,一点一点调试,总会解决的.
最后打个广告:
模仿推特客户端(纯Swift开发,develop分支):
https://github.com/waitwalker/MyTwitter
针对这个客户端简单用Python写了几个接口:
https://github.com/waitwalker/MyTwitterAPI
文章地址:https://www.jianshu.com/p/42ed698c57ad,因为一直在写code,文章比较糙,还没来及整理,抱歉!
作者:偶尔登南山
链接:https://www.jianshu.com/p/f72f10a921b9