从长远来看,重复单一易出错的操作将慢慢被机器所取代,具体到软件开发中就是,每次打包送测等操作是可以交给机器去自动执行的。以前打包给测试的流程是,测试拿了好几个手机过来,开发一一安装,然后送给测试慢慢测试。使用了持续集成之后将变成,开发本地提交代码,Jenkins 等持续集成工具监测到代码变化,自动编译打包,生成开发包,测试直接拿着开发包安装测试即可。

Jenkins安装

Jenkins 做的操作其实很简单,它只是将我们平时做的每一步重复的操作自动化了而已。因此,iOS 中 Jenkins 要做的分为以下几步:

  1. 拉取远端代码
  2. 由于某种条件触发后开始自动编译,打包
  3. 将生成的 ipa 文件上传到指定位置,供测试下载测试

这三步中,每一步 Jenkins 什么都没做,它只是调用了 Mac 中的一些工具,具体的说就是使用了命令行工具。有的做成了可视化的插件,有的还是要通过自己写命令来实现。典型的就是编译和打包的命令是调用 xcodebuild 命令。

登录 Jenkins 官网下载 Jenkins,需要注意的是在下载的时候勾选 Mac 平台下的 PKG 包,毕竟这是专门为 Mac 平台设计的。如下图

下载

下载下来以后,双击即可安装。安装时第一步是输入密码:

输入密码

我们打开 terminal,执行 cat 命令即可(需要管理员权限)。

cat

下面的操作就等它完成即可。

等待完成

安装好后的页面大概是这样

等待完成

2022 年 6 月 29 日更新

现在的安装方式和以前有一些不一样,使用了 brew 安装了,登录官网 Jenkins 下载链接

在命令行输入如下命令:

brew install jenkins-lts

安装完成后命令行中显示如下配置入口:

To restart jenkins-lts after an upgrade:
  brew services restart jenkins-lts
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/openjdk@11/bin/java -Dmail.smtp.starttls.enable=true -jar /usr/local/opt/jenkins-lts/libexec/jenkins.war --httpListenAddress=127.0.0.1 --httpPort=8080

随便选择一个,等待完成,其中会告诉你类似如下密码:

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

2c4b7718a4304d35862f4771f2c23c01

This may also be found at: /Users/kyson/.jenkins/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

打开浏览器,输入 127.0.0.1:8080 ,粘贴进去即可。

配置

我们选择【系统管理】----【系统设置】,看看里面的一些配置信息。这边不截图了,大概说一下原理。

Jenkins安装好后会自己新建一个 Jenkins 用户,估计是出于易于管理的考虑,但对我们的一些操作影响还是蛮大的。也就是说,我们在Jenkins做的任何操作都是基于 Jenkins 这个用户的,“~”代表的也不是管理员用户,而是 Jenkins 用户目录,更多的具体的配置我将在稍后的配置中加以说明。

接下来,我们就可以开始创建项目了,点击【新建】,输入项目名称,这里我输入我的 GitHub 里的一个项目AutoLoadImageView。然后选择【构建一个自由风格的软件项目】,其他我没有试过,如果有兴趣的话你可以尝试一下,点击保存后便进入到详细设置页面,暂时做如下的设置并【保存】即可

点击【立即构建】,然后切到命令行查看,可以发现代码已经拉取到本地了。

立即构建

以上操作其实已经证明跑通了 Jenkins 拉取代码到本地的操作。当然仅仅这样还不能帮我实现自动编译,打包甚至上传的操作,需要我们在配置中做更多的设置,最起码证书和 profile 文件还没有设置。

回到配置页面,点击【构建模块下的execute shell】

我们在出现的shell输入框中输入两个命令,看看我们之前的是否正确:

whoami

pwd

然后保存,并点击【立即构建】

可以看到,当前用户确实是 Jenkins用户,当前的目录就是本项目的目录。

xcodebuild 编译打包命令

Jenkins只是帮我们实现了自动化的过程,但编译打包、IPA文件生成还是需要我们自己操作。在打包之前,我们要了解一个命令 xcodebuild这是apple提供给我们的编译打包命令,具体的参数大家点进去看就可以,我这边说一下最重要的几个参数,下面是一个打包命令的例子。

echo "第四步,执行编译生成.app命令"

xcodebuild archive -workspace $project_name.xcworkspace -scheme $project_name -configuration Release -archivePath archive/$project_name.xcarchive CODE_SIGN_IDENTITY="iPhone Distribution: Shanghai XXX Network Technology Co., LTD (XXXH4WL4JZ)" PROVISIONING_PROFILE_SPECIFIER="distribution_doctor_kevin"
echo "第五步,根据生成的.app文件生成.ipa文件...."

xcodebuild -exportArchive -exportOptionsPlist archieveOpt.plist -archivePath archive/$project_name.xcarchive -exportPath ./ -configuration Release

可以看到,这里 xcodebuild 命令执行了两次,第一次是设置编译打包的参数,第二次是设置输出目录等。$project_name 是笔者先前声明的项目名称变量,也就是说,如果你的项目名称是 A,那么请在上面这段 shell 前加这么一句

# 工程名

project_name="A"

这样一来,下面 shell 脚本中所有出现的 $project_name 都会被替换成 "A"(不包含引号)

其中

1.-workspace 指明的是工作空间的名称,如果指明了这个参数,那就必须要指明-scheme参数

2.-sdk,ENABLE_BITCODE 不多说了,看参数名就知道了

3.CODE_SIGN_IDENTITY 这个比较重要,他指明的是证书标识符。这个是从钥匙串中拷过来的,有一点需要注意的是,我们需要将自己的开发证书先拷贝到系统证书中。这是因为钥匙串中的证书拥有者是管理者,不是 jenkins 用户,jenkins 用户是没有权限操作证书的
证书

4.PROVISIONING_PROFILE_SPECIFIER 看名字就知道是 profile 文件,同上,我们需要将管理员目录中的 profile 拷贝到 jenkins 的 profile 目录中,其中管理员 profile 目录在:

/Users/kyson/Library/MobileDevice/Provisioning\ Profiles/ (根据实际情况,将kyson改成你的用户目录)

jenkins 的 profile 目录位于(如果没有相应目录则自己建):

/Users/Shared/Jenkins/Library/MobileDevice/Provisioning\ Profiles/

(如果你没有访问Library目录的权限,记得使用chomod命令添加相应的权限)

文件列表

有读者问道不知道自己的证书对应的 profile 是哪个,因为 Provisioning Profiles 目录下有好多的文件,这里笔者也没有什么特别好的方法,推荐的是,先删除掉本地的所有 profile 文件,然后自己到苹果官网下载对应的 profile 文件,安装以后,就可以在 Provisioning Profiles 目录下看到相应的文件名了。虽然有点笨,但很保险,有新的办法还请赐教,谢谢^_^。

5.archive -archivePath ./$project_name.xcarchive

根据需要指定打包路径,其中扩展名记得要是 .xcarchive (其中 $project_name 是笔者在 shell 中声明的一个变量,比如,你的项目的名称是 A,那么对应的打包文件就是 A.xcarchive)

有读者写成了 archive - ./$project_name.xcarchive 请注意,这是错误的。因为 -archivePatharchive 的子命令,archive 命令用于告诉编译器,这里是要执行打包命令,后面的 archivePath 子命令指定打包路径

6.-configuration Release 这个不是必须的,因为默认打的就是 Release 包,倒是如果你想打 Debug 包可以单独设置

7.-destination generic/platform=iOS 也是指明打包的类型

接下来的就是指明打包的路径了

8.-exportArchive -archivePath ./$project_name.xcarchive 同上,不赘述了

9.-exportOptionsPlist archieveOpt.plist 这里的 archieveOpt.plist,是我们要自己新建的 plist 文件,该文件是用于指明打包的类型和 teamid

teamID

key chain

C9YH4WL4*

method

development

可以看到这个plist中有两个字段,一个是 teamID,一个是 method,teamID 很好理解,就是打包使用的证书的 teamID

method 对应的是打包类型,一般有 development,app-store, ad-hoc, enterprise等选项可供选择

10.-exportPath ./ 指明 ipa 的输出目录就在当前目录,可以根据需要进行自行调整

保存以上编辑,点击【立即构建】不出意外的话就能编译打包成功了,可以看到在 Jenkins 的工作目录中多了两个文件,其中一个是 ipa 文件,一个是 xcarchive 文件,这两种文件类型相信大家都不陌生了,xcarchive 包中包含了 dsym 符号表文件和app 文件(xcarchive文件其实是个文件夹),IPA 是我们最终需要的打包文件(其实是个压缩包)。

至此,所有的流程已经圆满成功。

注意点

Jenkins 打包真是个耐性子的活,跟技术关系不大,因此我还会再贴一些小细节。

SSH证书管理

在公司的真实开发过程中很少会将代码上传到 GitHub 的,一般来说是公司内部的 GitLab 服务器,大概的流程是一样的,主要是ssh需要重新生成。原因也不言而喻了:以前的 SSH 针对的是管理员用户,现在如果 Jenkins 用户想要 push 代码到远端,那肯定需要给 Jenkins 用户添加 SSH,方法也是很简单的

Jenkins

首先要切到 Jenkns 用户,然后进入到 .ssh 文件夹,最后调用 ssh-keygen 命令(本人机子已经生成过了,因此有 id_rsa 和 id_rsa.pub 等文件)

keyChain

打包失败,如果出现了如下所示的错误:

Provision Profile doesn't include signing certificate

那就说明第3步没有执行,请检查一下

关于Jenkins

Jenkins的确是一款非常好用的持续集成工具,在使用它的过程中我对它的发展也产生了兴趣,网上搜了一些资料,分享给大家:

Jenkins的前身是Hudson (软件)项目。Hudson 2004年夏天始创于 Sun Microsystems,2005年2月首次发布于java.net。

2007年前后,Hudson 被称为相对 CruiseControl 和其他开源的构建服务器(Build Server)更好的选择。2008 年 5 月的 JavaOne 大会上,Hudson 成为 “Duke选择奖” 开发人员解决方案分类的得主。

在 2010 年 11 月,就由谁主导 Hudson,该项目的主要贡献者和 Oracle 之间展开谈判。尽管在多个方面达成一致,争议集中在是否把 Hudson 注册为商标,后来 Oracle 声明对 Hudson 的名字拥有权利,并在 2010 年 12 月申请将其注册为商标。因此,2011 年 1 月 11 日,社区号召投票将项目名称从 “Hudson” 变更为 “Jenkins”。 2011 年 1 月 29 日,社区投票以压倒多数批准通过该提案,创建 Jenkins 项目。

2011 年 2 月 1 日,Oracle 表示他们打算继续 Hudson 的开发,并认为 Jenkins 是 Hudson 的复刻,而非重命名。 Jenkins 和 Hudson 之后继续作为两个独立的项目,均声称对方是自己的复刻。截至 2013 年 12 月,在 GitHub 上的Jenkins 组织有 567 项目成员及约 1100 公共库(public repository),而 Hudson 组织有 32 个项目成员和 17 个公共库。

在2011年,创建者川口耕介收到了O'Reilly开源奖,奖励其在Hudson/Jenkins项目上的工作。2014年,川口耕介成为CloudBees的首席技术官。