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

简介: 文章主要从iOS打包机远程构建的角度分析,整体链路脚本涉及的shell、ruby、security指令、xml以及iOS工程化相关知识,文章通过一个远程构建流程简单并重点的讲解了如何规避本地打包环境下的小的修改出包存在的大量人工操作,如何动态化配置证书、版本号等信息以及内测分发方式的避坑点。

一、背景

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. 合作方的调用链路;

合作方案调用方式

2.2.2 .code specs的访问权限

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

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

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)
#检索targetproject.targets.eachdo |target|
#读取config对象config=target.build_configuration_list[configuration]
#对config配置config.build_settings["CODE_SIGN_STYLE"] ="Manual"config.build_settings["PRODUCT_BUNDLE_IDENTIFIER"] =bundle_idconfig.build_settings["DEVELOPMENT_TEAM"] =team_idconfig.build_settings["CODE_SIGN_IDENTITY"] =full_cert_nameconfig.build_settings["PROVISIONING_PROFILE_SPECIFIER"] =profile_nameend

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_pathdone



#2. 执行exportArchivexcodebuild  -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文件解析失败,比如'%'不能有
<?xmlversion="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plistversion="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,托管式的集成方式,甚至不用管理证书,但是涉及到一些扩展或者是修改,灵活性就不那么强了,所以懂了原理之后,想怎么玩看读者自己了。

相关文章
|
2月前
|
安全 Android开发 iOS开发
Android vs. iOS:构建生态差异与技术较量的深度剖析###
本文深入探讨了Android与iOS两大移动操作系统在构建生态系统上的差异,揭示了它们各自的技术优势及面临的挑战。通过对比分析两者的开放性、用户体验、安全性及市场策略,本文旨在揭示这些差异如何塑造了当今智能手机市场的竞争格局,为开发者和用户提供决策参考。 ###
|
4月前
|
敏捷开发 测试技术 持续交付
阿里云云效产品使用合集之如何限制在本地的构建主机创建的流水线的并发数
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
2月前
|
jenkins 测试技术 持续交付
Docker最佳实践:构建高效的CI/CD流水线
【10月更文挑战第17天】在现代软件开发实践中,持续集成(Continuous Integration, CI)和持续部署(Continuous Deployment, CD)已成为提高开发效率和软件质量的重要手段。Docker作为一种容器技术,为构建一致且隔离的开发环境提供了强有力的支撑。本文将探讨如何利用Docker来优化CI/CD流程,包括构建环境的标准化、镜像管理以及与CI/CD工具(如Jenkins、GitLab CI)的集成。
86 5
|
2月前
|
开发工具 Android开发 iOS开发
Android vs iOS:构建移动应用时的关键考量####
本文深入探讨了Android与iOS两大移动平台在开发环境、性能优化、用户体验设计及市场策略方面的差异性,旨在为开发者提供决策依据。通过对比分析,揭示两个平台各自的优势与挑战,帮助开发者根据项目需求做出更明智的选择。 ####
|
2月前
|
运维 jenkins 持续交付
自动化运维之路:构建高效CI/CD流水线
在软件开发的快节奏中,持续集成和持续部署(CI/CD)流水线是提升效率、保障质量的关键。本文将引导你理解CI/CD流水线的重要性,并手把手教你如何搭建一个高效的自动化运维系统。通过实际代码示例,我们将一步步实现从代码提交到自动测试、部署的全流程自动化,确保软件交付过程既快速又可靠。
|
3月前
|
开发框架 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的指南
在移动应用开发的广阔天地中,安卓与iOS两大平台各占半壁江山。本文将深入浅出地对比这两大操作系统的开发环境、工具和用户体验设计,揭示它们在编程语言、开发工具以及市场定位上的根本差异。我们将从开发者的视角出发,逐步剖析如何根据项目需求和目标受众选择适合的平台,同时探讨跨平台开发框架的利与弊,为那些立志于打造下一个热门应用的开发者提供一份实用的指南。
71 5
|
4月前
|
测试技术 虚拟化 iOS开发
iOS自动化测试方案(二):Xcode开发者工具构建WDA应用到iphone
这篇文章是iOS自动化测试方案的第二部分,详细介绍了在Xcode开发者工具中构建WebDriverAgent(WDA)应用到iPhone的全过程,包括环境准备、解决构建过程中可能遇到的错误,以及最终成功安装WDA到设备的方法。
242 0
iOS自动化测试方案(二):Xcode开发者工具构建WDA应用到iphone
|
3月前
|
开发工具 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的关键考量
在数字时代的浪潮中,安卓和iOS这两大操作系统如同双子星座般耀眼夺目,引领着移动应用的潮流。它们各自拥有独特的魅力和深厚的用户基础,为开发者提供了广阔的舞台。然而,正如每枚硬币都有两面,安卓与iOS在开发过程中也展现出了截然不同的特性。本文将深入剖析这两者在开发环境、编程语言、用户体验设计等方面的显著差异,并探讨如何根据目标受众和项目需求做出明智的选择。无论你是初涉移动应用开发的新手,还是寻求拓展技能边界的资深开发者,这篇文章都将为你提供宝贵的见解和实用的建议,帮助你在安卓与iOS的开发之路上更加从容自信地前行。
|
4月前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
180 0
|
4月前
|
Android开发 iOS开发 C#
Xamarin.Forms:从零开始的快速入门指南——打造你的首个跨平台移动应用,轻松学会用C#和XAML构建iOS与Android通用界面的每一个步骤
【8月更文挑战第31天】Xamarin.Forms 是一个强大的框架,让开发者通过单一共享代码库构建跨平台移动应用,支持 iOS、Android 和 Windows。使用 C# 和 XAML,它简化了多平台开发流程并保持一致的用户体验。本指南通过创建一个简单的 “HelloXamarin” 应用演示了 Xamarin.Forms 的基本功能和工作原理。
113 0