Jenkins(二)自动化打包(iOS)

前言

从前文Jenkins(一)初步认识我们已经初步认识了Jenkins。接下来我们将通过一些配置来实现利用Jenkins自动化打包的目的。

摘要
一、进入Jenkins页面
二、创建自由风格的项目并配置源码管理
三、安装自动化打包构建时候所需的插件
四、上传构建过程所需的文件
五、配置构建方式(这里我们选择Xcode构建方式)
六、构建过程中的其他问题
附:直接跳过本篇文章,查看下篇文章:Jenkins(三)其他错误

其他文章
Jenkins(一)初步认识
Jenkins(二)自动化打包(iOS)
Jenkins(三)自动化打包其他错误(iOS)
Jenkins(四)自动化打包帮助(iOS)
iOS 再谈打包(证书、自动化、持续集成等)从开始到结束(精简)

一、进入Jenkins页面

双击jenkins.war,启动jenkins

image.png

随后输入完整地址http://localhost:8080即可进入Jenkins这个就不用重复提了。

二、创建自由风格的项目并配置源码管理

配置完源码管理后,点击“立即构建”,所构建的项目的源码会从所选择的SVN或Git上默认被下载到/Users/Shared/Jenkins/Home/workspace/里。

如果你发现代码一直没下载下来,那原因可能是你本身并没有装Git工具,安装后,重新点击“立即构建”即可下载Git上的代码到/Users/Shared/Jenkins/Home/workspace/里。

详细的请参见Jenkins(一)初步认识中的《二、创建项目并配置源码管理》部分。

三、安装自动化打包构建时候所需的插件

  • 1、安装管理发布证书及相关签名文件的插件。安装完该插件后,才可以将我们的"发布证书及相关签名文件"利用该插件上传,并将它们配置在我们的构建环境中。
  • 2、安装构建方式所选的插件
    下面会依次说明。如已安装请跳过此步。
1、安装管理发布证书及相关签名文件的插件。安装完该插件后,才可以将我们的"发布证书及相关签名文件"利用该插件上传,并将它们配置在我们的构建环境中。

打包内测版时,需要发布证书及相关签名文件,而这些发布证书及相关签名文件的管理需要通过“Keychains and Provisioning Profiles Management”插件管理。
所以我们在系统管理->管理插件,在“可选插件”中选中“Credentials Plugin”和“Keychains and Provisioning Profiles Management”安装管理签名证书的插件。

选择安装管理签名证书的插件.png

安装完之后,刷新界面在构建环境中,会且才会有如下选项
860EC768-234E-4856-BF84-AFE5EE16B1E3.png

这两个选项需要填写的东西如下:
image.png

上图中的这些选项是iOS打包需要的签名文件和证书。如果没有的话,需要进入Keychains and Provisioning Profiles Management页面添加。怎么添加下面会介绍。

2、安装构建方式所选的插件

下载Xcode integration,并安装后,构建选项中才会有Xcode方式。

构建的方式有编写脚本和Xcode两种常用方式。

Xcode构建方式.png

两者构建方式相比,编写脚本的话会更加灵活,但是脚本写起来比较麻烦。这里我选择用Xcode的方式进行构建。 所以需要选择系统管理->管理插件,在“可选插件”中选中“Xcode integration”安装。


安装构建方式所选的插件.png

安装完后,构建配置页面如下:

image.png

如果未设置编译输出目录Build output directory,其默认会在$WORKSPACE中对应项目里的bulids文件夹。

四、上传构建过程所需的文件

1、将我们的"发布证书及相关签名文件"利用该插件上传,这些文件之后在构建的时候需要使用。

①、上传工具在哪?
image.png

82E49797-9B62-40DD-8D69-EA65C1043C7E.png
②、要上传的文件在哪、应该放哪?

常识补充:我们要明白mac系统的弹出框无法显示隐藏的文件,所以如果要上传文件的话,必须将那些隐藏的文件复制一份到另外一个可见的文件夹下。

回归正题:要上传的"发布证书及相关签名文件"位于/Users/用户名/Library下的keychains文件夹MobileDevice文件夹,该路径为隐藏不可见的路径。所以这里我们需要将放在隐藏不可见路径/Users/用户名/Library下的keychains文件夹MobileDevice文件夹,如图

354C8FC4-0697-4238-ADAE-08835D1F8D3D.png

分别复制一份拷贝到另外一个可见的文件夹(如/Users/Shared/Jenkins/Library/)下,以确保可以显示在上传弹出框中,以用来上传。拷贝后的结构,如图:

71EAB25A-689E-4F8D-BD09-F060C6EFD185.png

③、了解文件上传后,会被放到什么位置。答:上传的文件将会被放到/Users/Shared/Jenkins/Home/kpp_upload下。

举例
如上传前:


上传前.png

点击“选取文件”按钮,弹出上传文件框,分别选取自己的keychain和证书。点击upload进行上传。


image.png

上传后:
上传后.png
④、开始正式上传钥匙串login.keychain(是因为钥匙串中包含签名的证书?),上传过程中需正确设置它的Code Signing Identity填写
616DA338-53DE-4D89-A5A6-4EC00B80C51D.png

这里添加login.keychain的时候要填写的Code Signing Identity是什么呢,它的值又是从哪来呢?答如下图:


Code Signing Identity的值从这来.png
⑤、正式上传描述文件Provisioning Profiles,上传过程中需正确设置它的Provisioning Profiles Directory Path。

说明:在项目中配置.mobileprovision文件后,执行构建,其会从我们这里填写的路径里找以该文件的UUID为文件名的.mobileprovision文件。所以该路径的作用是让构建的时候来查找的。

所以,这里我们填写上面系统描述文件被复制到的路径,即/Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles

完善Provisioning Profiles的Provisioning Profiles Directory Path的填写.png

附:如果未填写会出现如下错误:
FATAL: The path to store mobile provisioning profile files on the master is not configured. Go the plugin main configuration page and give the path.

Provisioning Profiles的Provisioning Profiles Directory Path未填写而导致的错误.png

所以,我们必须得确保我们填的那个目录下有以该文件的UUID为文件名的.mobileprovision文件。要不然会出现如下错误
FATAL: Failed to copy /Users/Shared/Jenkins/Home/kpp_upload/com.dvlproad.CJUIKitDemo.mobileprovision to /Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles/9265146f-df67-4c87-9136-22b09dbfa47b.mobileprovision java.nio.file.AccessDeniedException: /Users/Shared/Jenkins/Library/MobileDevice/Provisioning Profiles/9265146f-df67-4c87-9136-22b09dbfa47b.mobileprovision

60A2C9FB-6C78-45D0-844D-5CE4FD9CEC4F.png

这里虽然提示我们是copy失败,但是实际上/Users/Shared/Jenkins/Home/kpp_upload下的文件只是用于配置的时候选择使用,并不会真的执行Copy使其到我们填的那个目录里。所以,还是那句话,必须得确保我们填的那个目录下有以该文件的UUID为文件名的.mobileprovision文件。否则会出现错误。

五、配置构建方式(这里我们选择Xcode构建方式)

所需进行的配置项有

配置构建方式所需进行的配置项.png

1、配置构建方式之General build settings选项

①、了解 General build settings 选项需要配置的大概内容,结论是:这里我们需要配置Development Team ID,如果是xcworkspace,还必须在此设置Xcode Schema File。

该选项需要配置的大概内容,如图:


image.png
②、如何获取 Development Team ID ,以用来配置 Code signing & OS X keychain options 选项。

Development Team ID如何获取的方式为可在Keychain找到开发者证书iPhone Distribution: **** (329***),括号内的就是Team ID。举例如下图:

Development Team ID的获取.png
③、为 Code signing & OS X keychain options 选项配置Development Team ID。

即在 构建->Code signing & OS X keychain options,中的Development Team ID输入Development Team ID。如下图:


输入Development Team ID.png

如果未配置则会在构建的时候出现
FATAL: No global development team or local team ID was configured.问题,如图

448A351B-9543-4A0A-9CCD-5EFF1EA7C252.png

④、获取mobileprovision文件的UUID

在Terminal下输入下面的命令并回车::

curl https://raw.githubusercontent.com/0xc010d/mobileprovision-read/master/main.m | clang -framework Foundation -framework Security -o /usr/local/bin/mobileprovision-read -x objective-c -

这条命令的作用是下载mobileprovision-read的源码,然后编译,最后把生成的二进制文件mobileprovision-read放入到/usr/local/bin/路径下。

查看UUID的命令是:

mobileprovision-read -f test.mobileprovision-o UUID

测试可用。

详情查看:命令行获取mobileprovision文件的UUID

从apple网下载的描述文件通过本命令可查看到该UUID,通过进入描述文件的系统存放路径/Users/lichaoqian/Library/MobileDevice/Provisioning Profiles可以检验该UUID的描述文件有没有被添加进来。

2、配置构建方式之Code signing & OS X keychain options选项

image.png

如果为Unlock Keychain,则会出现如下错误
......
.....(省略号代表省略很多)
/Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app: errSecInternalComponent
Command /usr/bin/codesign failed with exit code 1

** BUILD FAILED **

The following build commands failed:
CodeSign /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app
(1 failure)
Build step 'Xcode' marked build as failure
Finished: FAILURE

3、配置构建方式之Advanced Xcode build options选项

Jenkins Xcode新版本

ia

以下是旧版本的
需要设置的选项有如下图两处,如果未设置,或者设置成下图这样子会造成错误

Advanced Xcode build options设置错误.png
所以,配置`Advanced Xcode build options`我们需要
①、配置项目文件`Xcode Workspace File`(必须)
②、配置`Xcode Schema File`(必须)
③、配置`Build output directory`(可填默认的 `${WORKSPACE}/build`)
①、配置项目文件Xcode Workspace File

上图的错误1:使用用cocoapods时候,Workspace File因多填写了个后缀名而造成了找不到文件的错误

使用用cocoapods时候,Workspace File因多填写了个后缀名而造成了找不到文件的错误.png

Xcode Workspace File的正确填写
这里Xcode Workspace File 填写就不多说了,填的是xcworkspace文件所在的目录,所以这里去掉后缀名即可,
即最后为$WORKSPACE/CJUIKitDemo/CJUIKit

②、配置Xcode Schema File

上图的错误2:使用用cocoapods时候,Schema File未填写而造成的错误

使用用cocoapods时候,Schema File未填写而造成的错误.png

Xcode Schema File的正确填写
Xcode Schema File的填写一般也为项目名,具体可自己查看Schema。

Xcode Schema File 填写了,但填写错误的常见情况
如果发现补充填写完后,还是有问题,如发现有如下问题,如图:

40348F8F-C546-46F8-90C5-6CB8F069B2F6.png

即错误为xcodebuild: error: The workspace named "CJUIKitDemo" does not contain a scheme named "CJUIKitDemo".这是因为没找到指定scheme引起。工程代码提交时,未将.xcodeproj中的xcschemes提交。

解决办法:将Manage Scheme后面工程的分享框勾上即可。

5209490F-E95E-403B-AFCE-2C47420C28D3.png

勾选Shared后,在.xcodeproj中就会产生xcshareddata目录

A2B8198C-F2FE-48B5-BC21-2BAE195F5683.png

随后,将xcshareddata目录提交到SVN/Git上,重新构建即可。(补充:.xcodeproj中的xcuserdata目录可不提交到SVN/Git上,因为这个目录是临时生成的,没什么用。)

③、配置Build output directory(可填默认的 ${WORKSPACE}/build

=== BUILD TARGET MBProgressHUD OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies

CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a normal armv7\ arm64
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo/Pods
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/CJUIKitDemo-gqrgqeoigrvayahkawwllwksjemk/Build/Intermediates.noindex/Pods.build/Release-iphoneos/MBProgressHUD.build/Objects-normal/armv7/libMBProgressHUD.a /Users/Shared/Jenkins/Library/Developer/Xcode/DerivedData/CJUIKitDemo-gqrgqeoigrvayahkawwllwksjemk/Build/Intermediates.noindex/Pods.build/Release-iphoneos/MBProgressHUD.build/Objects-normal/arm64/libMBProgressHUD.a -o /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: can't create output file: /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a (No such file or directory)

=== BUILD TARGET CJFile OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies
.......
(以下省略,直接跳到结果)
.......
** BUILD FAILED **

The following build commands failed:
CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/MBProgressHUD/libMBProgressHUD.a normal armv7\ arm64
CreateUniversalBinary /Users/lichaoqian/Project/jenkinsWorkspace/Release-iphoneos/CJFile/libCJFile.a normal armv7\ arm64
(2 failures)
Build step 'Xcode' marked build as failure
Finished: FAILURE

从描述中的error:可知是我们在Build output directory中填写/Users/lichaoqian/Project/jenkinsWorkspace 错了。将其改为默认的 ${WORKSPACE}/build重新构建即可解决本错误。
附:此操作会在该项目中创建一个build目录存放编译的输出内容,如图:

image.png

如此,基本大部分的问题都已解决了。

构建成功的样子为

Check dependencies

=== BUILD TARGET Pods-CJUIKitDemo OF PROJECT Pods WITH CONFIGURATION Release ===

Check dependencies

=== BUILD TARGET CJUIKitDemo OF PROJECT CJUIKitDemo WITH CONFIGURATION Release ===

Check dependencies

Validate /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
export PRODUCT_TYPE=com.apple.product-type.application
builtin-validationUtility /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app

** BUILD SUCCEEDED **

Finished: SUCCESS

此时你去上面的路径/Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app中即可看到有.app生成了。

六、ipa的输出

上面只是BUILD SUCCEEDED,要输出ipa还要打开Pack application, build and sign .ipa?,该选项按默认即可。

image.png

但是如果只是单纯的打开,就去构建会出现如下错误:

Touch /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app.dSYM
cd /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/CJUIKitDemo
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/usr/bin/touch -c /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/Release-iphoneos/CJUIKitDemo.app.dSYM

** ARCHIVE SUCCEEDED **

Cleaning up previously generated .ipa files
Cleaning up previously generated .dSYM.zip files
Packaging IPA
[CJUIKitDemo] /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleVersion" /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive/Info.plist [CJUIKitDemo] /usr/libexec/PlistBuddy -c "Print :ApplicationProperties:CFBundleShortVersionString" /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive/Info.plist
Packaging CJUIKitDemo.xcarchive => /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo-1.0-1.ipa
[CJUIKitDemo] $ /usr/bin/xcodebuild -exportArchive -archivePath /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo.xcarchive -exportPath /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build -exportOptionsPlist /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/ad-hocFZ5YDHE5JZExportOptions.plist -allowProvisioningUpdates
2018-06-21 02:14:51.320 xcodebuild[7671:202008] [MT] IDEDistribution: -[IDEDistributionLogging _createLoggingBundleAtPath:]: Created bundle at path '/var/folders/4j/wvf5xqh93631jch00c4qwkrw00008b/T/CJUIKitDemo_2018-06-21_02-14-51.316.xcdistributionlogs'.
2018-06-21 02:14:51.863 xcodebuild[7671:202008] [MT] IDEDistribution: Step failed: <IDEDistributionSigningAssetsStep: 0x7f879484e5d0>: Error Domain=IDEDistributionSigningAssetStepErrorDomain Code=0 "Locating signing assets failed." UserInfo={NSLocalizedDescription=Locating signing assets failed., IDEDistributionSigningAssetStepUnderlyingErrors=(
"Error Domain=IDEProvisioningErrorDomain Code=9 ""CJUIKitDemo.app" requires a provisioning profile." UserInfo={NSLocalizedDescription="CJUIKitDemo.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}"
)}
error: exportArchive: "CJUIKitDemo.app" requires a provisioning profile.

Error Domain=IDEProvisioningErrorDomain Code=9 ""CJUIKitDemo.app" requires a provisioning profile." UserInfo={NSLocalizedDescription="CJUIKitDemo.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}

** EXPORT FAILED **

Failed to build /Users/Shared/Jenkins/Home/workspace/CJUIKitDemo/build/CJUIKitDemo-1.0-1.ipa
Build step 'Xcode' marked build as failure
Finished: FAILURE

六、构建过程中的其他问题

No profiles for 'com.dvlproad.CJUIKitDemo' were found: Xcode couldn't find a provisioning profile matching 'com.dvlproad.CJUIKitDemo'. Code signing is required for product type 'Application' in SDK 'iOS 10.3'

0CB98B45-021E-45CF-B692-40E479BE6331.png

其他参考:[iOS 通过Jenkins 自动构建ipa]
搭建iOS自动化打包平台(利用Jenkins持续集成iOS项目)
学会使用 Jenkins 搭建 iOS 持续集成环境
Jenkins

七、常见问题参考

Jenkins整合XCode详解
Jenkins问题

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容