0%

一次简单的iOS自动化构建尝试

Jenkins.jpg

本文基于Jenkins + XcodeBuild + Fir简单实现了自动化构建的主要流程,更多的枝叶需自己慢慢完善。

之前看过使用Jenkins插件来构建的文章,所以一开始也准备用插件构建,后来才发现那些文章写得虽好,但很多配置已经过时了,所以最后使用脚本来构建。插件会失效,但脚本不会过期。

在开始之前,建议大家先建立一个能够正常archiveexport的空工程。真实的工程代码量很大,多次测试构建相当耗费时间。

一、下载安装Jenkins

Jenkins是基于Java环境的,所以电脑上必须先配置Java环境,然后去Jenkins官网(https://jenkins.io/)下载安装Jenkins。

安装完成后会自动打开http://localhost:8080,如果没有自动打开可以手动打开。打开后如出现找不到服务器的情况,可以尝试打开http://127.0.0.1:8080,两者是一样的。

有些教程还有添加Xcode integration 、Keychains and Provisioning Profiles Plugin之类插件的步骤,我们不需要。因为我们是用xcode脚本构建,所以不需要安装任何插件。

二、构建任务的建立

新建任务

image.png

构建一个自由风格的软件项目

image.png

填写工程相关介绍

image.png

三、源码管理

Git配置

如果选择SSH登录,在进行下图操作之前,要先去配置一下SSH key。
源码管理

配置SSH登录

Jenkins > 凭据 > 系统 > 全局凭据位置下配置SSH登录需要的key。这里需要特别注意,填写的key是私钥id_rsa,而不是公钥id_rsa.pub
配置SSH登录

四、构建过程

重点来了。
点击“添加构建步骤”,选择Execute shell

进入工程目录

进入目录后,根据自己项目实际情况,决定要不要pod install
构建步骤一

1
2
3
4
5
6
#bin/bsah - l
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8
cd $WORKSPACE/Test #进入工程目录
/usr/local/bin/pod install #这里根据自己实际情况,决定要不要pod install

执行打包操作

image.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#clean
xcodebuild clean -workspace Test.xcworkspace \
-scheme Test \

#archive
xcodebuild archive -workspace Test.xcworkspace \
-scheme Test \
-archivePath "$WORKSPACE/Test.xcarchive" \
-configuration Debug \

#export
xcodebuild -exportArchive -archivePath "$WORKSPACE/Test.xcarchive" \
-exportPath "$WORKSPACE/Export/Test" \
-exportOptionsPlist "$WORKSPACE/ExportOptions.plist" \
-configuration Debug \

说明:

-archivePath:.xcarchive文件的存放路径。

-exportPath:导出文件的路径。Export文件夹是自己建的。

-ExportOptions.plist:这个文件的内容其实是ipa的打包信息。手动archiveexport时,这个文件就包含在最终输出的文件夹内,可以copy一份出来使用。

-configuration :默认DebugRelease

这里有个坑要说明一下。archive和ipa文件的导出目录最好位于Jenkins下的那个工程中,我之前选择的是导出到桌面,结果一直报读写权限的问题。

五、上传ipa包到Fir

image.png

要实现自动上传到fir,要先安装fir-cli

1
2
3
4
rvm list   	        # 确保 rvm 正确安装, 如果直接通过系统安装ruby, 可以注释此行
ruby -v # 查看 ruby 的版本, 请确保大于 2.4.0
gem install fir-cli # 现场安装fir-cli , 如果安装过, 则会略过
fir -v # 查看 fir-cli 的版本

成功安装之后,添加下面这个脚本:

1
2
#!/bin/bash --login
fir publish "$WORKSPACE/Export/Test/Test.ipa" -T "61a07dbfe4a4dc862f******b71e7c93"

61a07dbfe4a4dc862f******b71e7c93:Fir的API token

image.png

若上传过程出现:command not found

1、控制台执行 echo $PATH ,复制输出内容。

2、jenkins->系统管理->系统设置。

3、勾选Environment variables,添加键值。键:PATH,值:刚才复制的内容。

image.png

六、配置自动触发器

Jenkins在自动化构建的过程中,更多的是充当监察者的作用。一旦监察到仓库中的内容有任何变化,就自动触发构建打包。
自动触发构建可参考这篇文章:Jenkins之定时构建

至此,Jenkins+xcodebuild+fir环境搭建完成。

七、错误记录

1、Code Signing Error: No profile for team ‘XXX’ matching ‘XXX’ found:

bug1.png
原因:

缺少描述文件。

解决方法:

硬盘/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles路径下添加所需的描述文件。推荐使用Xcode自动管理描述文件的方式,避免出现此类问题。

2、XXX.m normal armv7 objective-c com.apple.compilers.llvm.clang.1_0.compiler

bug2.png
原因:

编辑该.o文件时出错。

解决方法:

我的情况是,在A电脑写代码,在B机器Jenkins打包,A、B两机器的pod版本不一致,导致pod下来的第三方代码也不一致,编译时自然会出错。AB两电脑pod update一下,保持版本一致,重新提交代码即可。

3、error: exportArchive: No certificate for team ‘XXX’ matching ‘XXX’ found. Specify a different signing certificate for “signingCertificate” in your Export Options property list

bug3.png
原因:

exportArchive时证书和描述文件对应不上。

解决方法:

我使用的ExportOptions.plist是Release模式生成的,但是Jenkins exprortArchive时选择的是Debug模式。模式不一致,证书和描述文件自然对应不上。

4、Jenkins打包时提示Multiple commands produce…,但真机测试没问题

原因:

Jenkins打包时默认使用的是New build system,而不管你Xcode里是如何设置的。

解决方法:

archive时添加xcodebuild指令-UseModernBuildSystem=NO,指定不使用当前的编译系统。

5、git clone 报错 Permission denied (publickey,password).git配置ssh key

原因:

Jenkins配置ssh登录时,需要拷贝私钥,而不是公钥

6、jenkins env: ruby_executable_hooks: No such file or directory

原因:

需要安装executable-hooks

解决方法:

sudo gem install --user-install executable-hooks
安装过程中,要留意异常。有可能报path相关的错误,导致某些程序不能执行。此时参照提示,使用vim打开bash_profile文件,把需要的path写进去,然后重新执行命令。安装完成之后,再删掉刚才的path。一定要记得删除,否则后面使用Jenkins构建时会报很多诸如command not found之类的错误。

7、Jenkins requires Java versions [8, 11] but you are running with Java 13 from…

原因:

本地Java版本不适合,需要安装jdk8或jdk11

8、Failed to connect to raw.githubusercontent.com port 443: Connection refused…

原因:

出现这个错误一般是被墙的原因。可以尝试设置DNS为114.114.114.114或者8.8.8.8

9、xcodebuild: error: The workspace named “XXX” does not contain a scheme named “XXX”. The “-list” option can be used to find the names of the schemes in the workspace.

解决方法:

1、工程的scheme和构建脚本的scheme对应不上。例如本次构建,脚本的scheme是AAA,但实际上工程的scheme是BBB。

2、或者:Choose Scheme > Manage Schemes (from the Product Menu).
Ensure the ‘Shared’ box is checked for that scheme。打开Shared选项。这个是别人遇到的情况并提供的答案。

10、Failed to build gem native extension

解决方法:

Mac OS某些版本,有个pkg需要手动安装。
open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg

11、double check问题

1
2
3
Jenkins detected that you appear to be running more than one instance of Jenkins that share the same home directory '/data/jenkins/home’. This greatly confuses Jenkins and you will likely experience strange behaviors, so please correct the situation.
This Jenkins: 723777919 contextPath="" at 25@MYLINUX
Other Jenkins: 47707180 contextPath="/jenkins" at 25@MYLINUX

原因:

Jenkins启动之后,会在home目录下生成.owner文件。里面标识了本次Jenkins实例的唯一标识。

1
47707180 contextPath="/jenkins" at 25@MYLINUX

解决方法:

  1. 直接选择忽略
  2. 然后删除.owner文件,再退出登录
  3. 重新登录。它会重新生成.owner文件

12、可以通过localhost:8080访问,但是无法通过ip访问,例如:172.21.18.83:8080

解决方法:

Jenkins默认只会监听127.0.0.1的请求,我们需要修改httpListenAddress为0.0.0.0,监听所有ip的请求。

  1. 打开对应路径,修改httpListenAddress的值
    1
    2
    ~/Library/LaunchAgents/homebrew.mxcl.jenkins.plist
    /usr/local/Cellar/jenkins/版本号/homebrew.mxcl.jenkins.plist
  2. 关闭并重新开启Jenkins
    1
    2
    brew services stop jenkins
    brew services start jenkins
    注意:不能使用brew services restart jenkins。这个指令会重置配置,导致我们刚才的自定义配置失效。

13、提交ipa包时,validate和update到connect都提示成功,但是在connect上就是看不到构建版本

原因:我的情况是,ExportOptions.plist使用错了。我使用的是Ad-Hoc环境的,而不是AppStore环境。

八、参考资料

Building from the Command Line with Xcode
How can I use the legacy build system with Xcode 10’s xcodebuild?
Jenkins之定时构建