iOS持续集成(四) - Jenkins打包与分发

基本思路是在 Mac 服务器上,搭建 tomcat 服务, jenkins 部署到 tomcat 下,Mac 服务器启动时自动启动 tomcat 服务,jenkins 也就启动了,同时一个 iOS 项目在 jenkins 下会有开发、测试、预发部、Beta、正式发布等环境,其中开发、测试、预发部、Beta为 AdHoc 使用证书,打包后上传到第三方发布平台,正式发布使用 Distribution 证书,打包后上传到 AppStore。

Mac服务器配置

启动ssh远程登录服务

Mac 本身安装了 ssh 服务,默认情况下没有开启 ssh 服务。可以通过 “系统偏好设置” -> “共享” -> “远程登录” 开启 Mac 服务器启动 ssh 服务。也可以在终端执行以下命令开启。

启动 ssh 服务

1
$ sudo launchctl load -w /System/Library/LaunchDaemons/ssh.plist

停止 ssh 服务

1
$ sudo launchctl unload -w /System/Library/LaunchDaemons/ssh.plist

查看 ssh 服务是否启动

1
$ sudo launchctl list | grep ssh

如果输出- 0 com.openssh.sshd,则表示成功启动了.

开启屏幕共享

使用以下命令进行开启屏幕共享:

1
$ sudo  /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -on -clientopts -setvnclegacy -vnclegacy yes -clientopts -setvncpw -vncpw VNCPassword -restart -agent -privs -all

其中 VNCPassword 为你的 VNC 密码。使用以下命令关闭屏幕共享:

1
$ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -deactivate -configure -access -off

如果需要为所有用户开启屏幕共享,则可以使用一下命令:

1
$ sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart -activate -configure -access -off -restart -agent -privs -all -allowAccessFor -allUsers

开始远程控制
Mac 自带支持 VNC,可以直接用系统浏览器 Safari 也可以使用支持 VNC 的第三方软件来进行控制。
使用 Safari 控制的方式为:

打开 Safari,在地址栏里输入 vnc + 远程主机地址,例如:vnc://192.168.168.168,回车后输入远程地址的用户名和密码进行连接。

Tomcat和Jenkins服务部署

首先下载好 tomcat 包和 jenkins.war 包,我使用的 tomcat 版本是 9.0.8。将下载的 tomcat 包解压到 /Library/Tomcat 路径下, 需要注意的是,这里需要使用 chmod 命令修改一下 tomcat 的 bin 目录下的 .sh 权限。执行: chmod u+x /Library/Tomcat/apache-tomcat-9.0.8/bin/*.sh。将 jenkins.war 包复制到 tomcat 下的 webapps 文件夹下。这样 tomcat 和 jenkins 服务就部署好了。

配置 tomcat 启动脚本

/usr/local/bin/ 下添加 tomcat 启动文件。 执行 vim /usr/local/bin/tomcat,并输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#!/bin/bash

case $1 in
start)
sh /Library/Tomcat/apache-tomcat-9.0.8/bin/startup.sh
;;
stop)
sh /Library/Tomcat/apache-tomcat-9.0.8/bin/shutdown.sh
;;
restart)
sh /Library/Tomcat/apache-tomcat-9.0.8/bin/shutdown.sh
sh /Library/Tomcat/apache-tomcat-9.0.8/bin/startup.sh
;;
*)
echo "Usage: start|stop|restart"
;;
esac

exit 0

保存后退出,使用 chmod 命令修改一下 /usr/local/bin/tomcat 的权限。执行: chmod u+x /usr/local/bin/tomcat,现在就可以执行 tomcat start 启动 tomcat 服务了。此时会出现:

1
2
3
4
5
6
Using CATALINA_BASE:   /Library/Tomcat/apache-tomcat-9.0.8
Using CATALINA_HOME: /Library/Tomcat/apache-tomcat-9.0.8
Using CATALINA_TMPDIR: /Library/Tomcat/apache-tomcat-9.0.8/temp
Using JRE_HOME: /Library/Java/JavaAppletPlugin.plugin/Contents/Home
Using CLASSPATH: /Library/Tomcat/apache-tomcat-9.0.8/bin/bootstrap.jar:/Library/Tomcat/apache-tomcat-9.0.8/bin/tomcat-juli.jar
Tomcat started.

说明 tomcat 已经启动了。 打开 http://localhost:8080/jenkins 就可以发现 jenkins 已经启动了,jenkins 欢迎界面后会有一个初始化 jenkins 账户的页面,设置之后就用该账号登录 jenkins 。关于 jenkins 账户设置及管理这里就不再深入了。

设置Tomcat开机启动

上面 tomcat 和 jenkins 已经部署好了,以后服务器每次重新启动后需要执行 tomcat start,来启动 tomcat,始终会有点麻烦,于是考虑将 tomcat 设置成开机自动启动。

/Library/LaunchDaemons 路径下添加 org.apache.tomcat.plist 文件。

1
2
$ cd /Library/LaunchDaemons
$ sudo vim org.apache.tomcat.plist

添加下面内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="2.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<false/>
<key>UserName</key>
<string>XiaXianBing</string>
<key>Label</key>
<string>org.apache.tomcat</string>
<key>KeepAlive</key>
<dict>
<key>NetworkState</key>
<true/>
</dict>
<key>ProgramArguments</key>
<array>
<string>/Library/Tomcat/apache-tomcat-9.0.8/bin/catalina.sh</string>
<string>run</string>
</array>
<key>EnvironmentVariables</key>
<dict>
<key>JAVA_HOME</key>
<string>/Library/Java/JavaAppletPlugin.plugin/Contents/Home</string>
</dict>
<key>RunAtLoad</key>
<true/>
<key>StandardOutPath</key>
<string>/Library/Tomcat/apache-tomcat-9.0.8/logs/stdout.log</string>
<key>StandardErrorPath</key>
<string>/Library/Tomcat/apache-tomcat-9.0.8/logs/stderr.log</string>
</dict>
</plist>

保存并退出。测试启动服务:

1
2
3
$ cd /Library/LaunchDaemons
$ launchctl load org.apache.tomcat.plist
$ launchctl start org.apache.tomcat.plist

如果报一下错误: /Library/LaunchDaemons/org.apache.tomcat.plist: Path had bad ownership/permissions,是因为权限不够,执行 sudo chown root org.apache.tomcat.plist 即可,再次启动就好了。

Jenkins配置

jenkins 插件安装

进入 jenkins 后,首先需要安装所需的插件。在 系统管理 -> 管理插件 -> 可选插件 下,通过过滤,安装 Xcode、 Gitlab 和蒲公英相关插件(因为使用的是Gitlab来管理的源码,另外选择上传测试包到第三方发布平台蒲公英上,其中主要的插件是 Xcode integrationGitlab PluginGitlab Hook PluginUpload to pgyer),插件安装完之后,我们就可以开始配置一个构建项目了。

添加 Keychain

~/Library/keychains/ 文件夹下将 login.keychain-db 复制到桌面并将名称改为login.keychain

在 jenkins 下 系统管理 -> Keychains and Provisioning Profiles Management -> 选择该文件,点击 Upload 添加该文件后,设置登录密码。

构建

jenkins 构建第一个项目

点击 新建Item,输入构建项目名称,选择 构建一个自由风格的软件项目,在源码管理下,选择 Git 选项,并在 Repositories 下设置好项目源码的 Repository URL, 第一次使用需要在 Credentials 处添加一个新的 Credentials。在 Branches to build 下选择好 git 分支。

构建环境 下,勾选上 Keychains and Code Signing Identities,以及其下的,Overwrite existing keychainsDelete copied keychains after build

构建 下,点击增加构建步骤,选择 Execute shell,直接输入以下内容,分别执行的是:

  1. 进入 build 路径 clean 一下你的工程。
  2. archive 导出 .xcarchive 文件。
  3. 导出 .ipa 包。

特别注意: ExportOptions.plist 中, compileBitcode 为 YES 时,jenkins 打包失败。设置为 NO 时成功(这应该是 Jenkins 的一个 bug,打包提交 AppStore 时需要特别注意)。

其中在导出 .ipa 包时,需要在 jenkins 下设置好 ExportOptions.plist 文件存放路径(ExportOptions.plist 可以手动 Archive 项目生成,之后复制到该文件下即可)。

1
2
3
4
5
xcodebuild clean -workspace ${WORKSPACE}/Photographer.xcworkspace -scheme PhotographerTest -configuration Release

xcodebuild archive -workspace ${WORKSPACE}/Photographer.xcworkspace -scheme PhotographerTest -archivePath ${WORKSPACE}/builds/PhotographerTest

xcodebuild -exportArchive -archivePath ${WORKSPACE}/builds/PhotographerTest.xcarchive -exportPath ${WORKSPACE}/builds/PhotographerTest -exportOptionsPlist ${WORKSPACE}/../Profile/PhotographerTest/ExportOptions.plist -allowProvisioningUpdates

完成之后,根据项目构建目的,构建后操作这里有两个不同的操作,分别作为发布到第三方发布平台,或者发布到 AppStore 提交审核。

发布到第三方发布平台(蒲公英)
构建后操作 下,点击增加后操作步骤,选择 Upload to pgyer with apiV2,设置好 蒲公英账号的 api_key,以及编译打包后的路径及名称。

发布到 AppStore
这里使用 shell 脚本,提交到 AppStore。在 构建后操作 下,点击增加后操作步骤,选择 Execute shell,输入以下内容:

1
2
3
4
5
6
7
8
9
10
11
/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool --validate-app \
-f ${WORKSPACE}/builds/Photographer/Photographer.ipa \
-u AppleID \
-p Password \
-t ios --output-format xml

/Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool --upload-app \
-f ${WORKSPACE}/builds/Photographer/Photographer.ipa \
-u AppleID \
-p Password \
-t ios --output-format xml

其中 AppleID 为具有管理权限的 AppleID 名称, Password 为相对应的密码。到这里构建项目就完成了,点击立即构建即可开始构建并发布了。

蒲公英获取UDID和版本更新

另外,蒲公英提供了一个方便获取开发设备 UDID 的链接 https://www.pgyer.com/udid,通过 iOS 设备上打开这个链接,根据提示就能获得设备的 UDID,发送给开发者加入开发者账号中。

同是蒲公英也提供了检查测试版本及更新的接口,可在代码内检测测试版本号和更新测试版本,详情可到蒲公英文档中心查看。

Jenkins报错汇总

ARCHIVE FAILED报如下错误:

1
2
3
Check dependencies
Code Signing Error: No signing certificate "iOS Distribution" found: No "iOS Distribution" signing certificate matching team ID "XXX" with a private key was found.
Code Signing Error: Code signing is required for product type 'Application' in SDK 'iOS 11.4'

在我本机Jenkins上运行的好好的,部署到服务器上后就一直报这个错误,纠结了好久,最后找到解决方案: 将 iOS Distribution 证书从 钥匙串 -> 登录 下拖到 系统 下就好了。

Command CodeSign failed with a nonzero exit code报错

1
2
3
4
Signing Identity:     "iPhone Distribution: WeiCun(Shanghai) Network Technology Co., Ltd (T3QLT73ZBK)"
Provisioning Profile: "match AdHoc com.vphoto.photographerfat.vboxwidget" (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
errSecInternalComponent
Command CodeSign failed with a nonzero exit code

XCode -> Product -> Clean 之后重启电脑即可。

备注


坚持原创技术分享,您的支持将鼓励我继续创作!
----------- 本文结束, 感谢您的阅读 -----------