开发者社区> 游客hlbqnv5wryii4> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

自建iOS构建流水线建设核心原理剖析

简介: 文章主要从iOS打包机远程构建的角度分析,整体链路脚本涉及的shell、ruby、security指令、xml以及iOS工程化相关知识,文章通过一个远程构建流程简单并重点的讲解了如何规避本地打包环境下的小的修改出包存在的大量人工操作,如何动态化配置证书、版本号等信息以及内测分发方式的避坑点。
+关注继续查看
福利推荐:阿里云、腾讯云、华为云等大品牌云产品全线2折优惠活动来袭,4核8G云服务器899元/3年,新老用户共享优惠,点击这里立即抢购>>>

一、背景

1.1 问题

移动端开发交付项目中,由于交付团队技术沉淀参差不齐,开发流程极不规范,经常出现这打包在本地,甚至是集中在某个外包开发自己,这样的方式存在以下问题:

  1. 不安全:代码、证书、签名泄漏风险
  2. 低效:环境不可靠,稳定,打包效率慢,小的改动打包可能涉及到大量的人工操作
  3. 低质量:受本地环境如缓存、分支、配置等因素影响较大,出包质量参差不齐
  4. 协同性低:基本集中在某个人身上,高度依赖
  5. 版本管理差:个人记录,归档基本不存在
  6. 其他(持续集成、安装分发、权限控制没法做····)

1.2 目标

也是由于存在以上诸多问题,所以,统一的构建流水线是必须的,至少要实现云端统一构建,支持证书管理、版本管理、权限管控、安装分发等能力

1.3 方案

想要实现流水线构建,需要具备以下基本的环境:

  1. 公网访问
  2. 打包机(Android linux环境即可、iOS需要xcode环境)

1.3.1 公网访问

这个是交付项目的客观存在,所以不可能直接面向集团内部资源,我们这里就直接考虑入口在GTS统一工作台的大禹研发域

1.3.2 打包机

  • Android,linux环境即可,我们平时时候的流水线jenkins服务都运行在linux环境上,所以Android没有太大的问题(Android由于难度较低,本文不做分析。)
  • iOS,需要xcode环境,iOS生态是比较封闭的,所以目前调研的有3种方案:
    1. mac机器,需要解决机器的托管以及外网访问问题
    2. mac虚拟技术,有一定的技术壁垒,成本较高
    3. 技术合作

决策:技术合作是成本最低,见效最快的方式。

合作方给我们提供了非常友好的对接方式,他们提供xcode运行环境,剩下的我们自己想怎么玩就怎么玩。

二、设计

想要设计一个移动端流水线,当然不能简单的打个包就行了,我们需要解决的是上面提到的各种问题,以及要基于流水线以及移动端产品的特性而开发一些额外的功能

2.1 功能大图

这里功能简单罗列构建相关核心功能点

项目

说明

证书管理

证书的上传、下载、访问权限管理

版本管理

构建记录

构建code与源码commit映射

产物分发

支持扫码安装

支持访问权限配置

支持有效期配置

构建参数

  1. Version 版本号
  2. 唯一的安装ID,一般用于一机多装
  3. AppName 名称
  4. ad-hoc,dev,enterprise,app store
  5. 环境、日志等其他信息


2.2 环境准备

在正式的开始构建前,这里先解决两个技术点:

2.2.1. 合作方的调用链路;

image

合作方案调用方式

2.2.2 .code specs的访问权限

大部分iOS开发已经是基于pods管理的组件化的方案,所以需要打通私有specs仓库和公共仓库的访问

image

代码以及仓库访问权限管理

2.3 构建思路

构建步骤主要为以下清单:

由于资源都是在自己的服务器上,所以这里的步骤跳过了所需要的资源的拉取以及xcode,pods版本的切换

步骤

项目

说明

1

资源拉取

工程源码、证书、profile文件

2

xcode、pods版本切换

根据工程实际情况选择

3

证书安装

核心:证书文件,必须在当前机器安装才能使用

4

profile描述文件安装

核心:描述文件,必须在当前机器安装才能使用

5

xcodeproj修改配置

核心:修改version,bundleId,app_name,证书、描述文件等信息

6

额外的插件安装

比如mPaaS,需要安装mPaaS相关的资源,这个也是基于项目使用了mPaaS插件,所以也就增加了这个的扩展,一般项目可以在配置单默认关闭即可

7

pods update/install

核心:依赖拉取

8

archive

核心:xocdebuild 构建

9

exportArchive

核心:导出ipa

10

deploy

核心:安装分发配置

三、核心点剖析

安全需要,为了讲清楚核心点,以下代码为部分核心代码,并非完整代码,额外需要处理大量的判断逻辑比如:cert和profile以及bundleId、打包类型一致性;证书、描述文件大量时候的删除重装逻辑等。

3.1 证书安装

iOS构建的证书是安装在OSX系统的钥匙链里面,需要使用系统的`security`指令执行创建和访问配置:

#1. 创建
security create-keychain -p $keychain_password $keychain_name
#2. 解锁
security unlock-keychain -p $keychain_password $keychain_name
#3. 导入
security import $p12_path -k $keychain_name -P $p12_password -A
#4. 设置访问权限
security set-key-partition-list -S apple-tool:,apple: -k $keychain_password $keychain_name
#5. 更改钥匙串配置
security set-keychain-settings $keychain_name


3.2 privosion profile描述文件安装

这个描述文件安装就比较简单,复制到指定目录

`${HOME}/Library/MobileDevice/Provisioning\ Profiles`即可,同时修改文件名为profile对应的uuid
cp $profile_file ${HOME}/Library/MobileDevice/Provisioning\ Profiles/${INSTALL_PROFILE_UUID}.mobileprovision

3.3 xcodeproj修改配置

这一步是个难点,也是个核心大头,由于xcode工程配置用的ruby脚本管理,所以这里的配置也是由ruby进行修改,大体流程如下:

  1. 找到对应target
  2. 修改cert和profile
  3. 修改bundle_id、app_name、build、version_code
  4. 修改签名机制手动挡
#读出project信息
project = Xcodeproj::Project.open(project_path)
#检索target
project.targets.each do |target|
  #读取config对象
  config = target.build_configuration_list[configuration]
  #对config配置
  config.build_settings["CODE_SIGN_STYLE"] = "Manual"
  config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] = bundle_id
  config.build_settings["DEVELOPMENT_TEAM"] = team_id
  config.build_settings["CODE_SIGN_IDENTITY"] = full_cert_name
  config.build_settings["PROVISIONING_PROFILE_SPECIFIER"] = profile_name
end

3.4 pod install

podspec 有墙的因素,导致很多github specs以及墙外资源经常性拉取失败,所以在pods install这个阶段做了三种优化:

  1. 使用自建/国内specs镜像
  2. Pods目录上传到代码库,跳过pods install阶段
  3. 使用缓存机制,对Pods资源缓存

3.5 Archive

3.5.1 首先clean

# 编译前清理工程
xcodebuild clean -workspace ${workspace_name}.xcworkspace \
                 -scheme ${scheme_name} \
                 -configuration ${build_configuration}

3.5.2 执行archive

xcodebuild archive -workspace ${workspace_name}.xcworkspace \
                   -scheme ${scheme_name} \
                   -configuration ${build_configuration} \
                   -archivePath ${export_archive_path} \
                   CHANNEL=true \
                   GCC_PREPROCESSOR_DEFINITIONS='$(inherited) CUST_NUM1=99'

可以通过GCC_PREPROCESSOR_DEFINITIONS配置自定义的运行时变量

3.6 exportArchive ipa阶段

执行真正的exportArchive前,需要根据参数`生成export_options_plist文件`

#1. 根据参数生成export_options_plist文件
/usr/libexec/PlistBuddy -c  "Add :compileBitcode bool ${compileBitcode}"  $export_options_plist_path
/usr/libexec/PlistBuddy -c  "Add :method string ${method}"  $export_options_plist_path
/usr/libexec/PlistBuddy -c  "Add :provisioningProfiles:"  $export_options_plist_path
### 这里是做了个扩展点
echo "$extension_export_plist" | while read line
do
/usr/libexec/PlistBuddy -c  "$line"  $export_options_plist_path
done



#2. 执行exportArchive
xcodebuild  -exportArchive \
            -archivePath ${export_archive_path} \
            -exportPath ${export_ipa_path} \
            -exportOptionsPlist ${export_options_plist_path} \
            -allowProvisioningUpdates

3.7 Deply 内测分发

这个阶段又叫内测分发,iOS 打包产物想要安装到iOS设备上,比Android复杂很多,除了testflight和App Store正常安装外,日常测试也是需要安装,我们这里做了分发功能,通过扫描二维码即可安装(遵循设备注册和企业包灯等的安装限制)

核心点:

itms-services:///?action=download-manifest&url=https://resource.dayu.work/build-packages/xxx/ios-test.plist


启用一个itms-services标签,指向一个plist描述文件,plist格式如下,有几个点必须注意,严格遵守:

  1. itms-services标签下的url链接协议必须是https
  2. itms-services标签下的url链接不能有特殊字符,否则会导致plist文件解析失败,比如'%'不能有
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>items</key>
    <array>
      <dict>
        <key>assets</key>
        <array>
          <dict>
            <key>kind</key>
            <string>software-package</string>
            <key>url</key>
            <string>https://xxxx.com/xxxxxxx/download</string>
          </dict>
        </array>
        <key>metadata</key>
        <dict>
          <key>bundle-identifier</key>
          <string>com.dayu.buildios</string>
          <key>bundle-version</key>
          <string>1.0.0-MTL-SNAPSHOT</string>
          <key>kind</key>
          <string>software</string>
          <key>title</key>
          <string>流水线测试包</string>
        </dict>
      </dict>
    </array>
  </dict>
</plist>


总结

本篇文章主要是对IOS构建做了一个从xcodebuild 基础命令的,包括流水线构建流程做了个剖析,感兴趣的可以自行尝试,目前市面也有很多比较成熟的产品,比如fastlane,托管式的集成方式,甚至不用管理证书,但是涉及到一些扩展或者是修改,灵活性就不那么强了,所以懂了原理之后,想怎么玩看读者自己了。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(二)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
0 0
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建(一)
iOS开发CoreGraphics核心图形框架之九——PDF文件的渲染与创建
0 0
iOS开发CoreGraphics核心图形框架之八——层聚合
iOS开发CoreGraphics核心图形框架之八——层聚合
0 0
iOS开发CoreGraphics核心图形框架之六——梯度渐变(二)
iOS开发CoreGraphics核心图形框架之六——梯度渐变
0 0
iOS开发CoreGraphics核心图形框架之六——梯度渐变(一)
iOS开发CoreGraphics核心图形框架之六——梯度渐变
0 0
iOS开发CoreGraphics核心图形框架之五——Patterns模型的应用
iOS开发CoreGraphics核心图形框架之五——Patterns模型的应用
0 0
iOS开发CoreGraphics核心图形框架之四——变换函数
iOS开发CoreGraphics核心图形框架之四——变换函数
0 0
iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间
iOS开发CoreGraphics核心图形框架之三——颜色与色彩空间
0 0
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文(二)
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文
0 0
文章
问答
文章排行榜
最热
最新
相关电子书
更多
Facebook iOS App技术演化十年之路
立即下载
From Java_Android to Swift iOS
立即下载
深入剖析 iOS 性能优化
立即下载


http://www.vxiaotou.com