iOS持续集成构建

作者: 偶尔登南山 | 来源:发表于2018-03-06 09:31 被阅读958次

            目前市面上持续集成的方案很多:例如,Jenkins, Fastlane,Xcode server等,这些持续集成的方案大同小异,他们之间的性能差异笔者没有做大量的横向分析,只是大体比较了一下打包时间.总结来说,持续集成主要是三个步骤:1.拉取代码;2.编译打包;3.分发数据(打包结果),下面将通过两种方案(Jenkins和Xcode server)来分析一下这三个过程.

    Jenkins集成方案

            Jenkins作为免费集成方案,其社区拥有大量插件,非常友好,所以用户也众多.
    首先来安装Jenkins,Jenkins官网提供了多个系统环境的软件包,我选择的是macOs系统,选择下载安装,步骤如下图:

    下载Jenkins

    下载Jenkins.png

    安装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,文章比较糙,还没来及整理,抱歉!

    相关文章

      网友评论

        本文标题:iOS持续集成构建

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