iOS持续集成(Jenkins+Fastlane+蒲公英+钉钉群通知)

   

前言

   
    第一次接触持续集成,是以前在银行做项目的时候,当时APP团队人员较多,测试阶段频繁的打包测试,手动打包效率很低,团队大佬搭建了Jenkins持续集成,当时觉得这玩意儿真好使,提交完代码,轻轻点一下构建,几分钟以后,新包就打好了,对于当初只做上层应用开发的我,感觉好高大上。

    五月底换了新公司,进了新的项目组,团队负责两个系统APP的开发、运维,6个人研发团队,规模不大不小。开发阶段打包频率不高,一旦到了交付测试阶段,每天打包的频率很高。每个迭代周期测试时间5~7天,从手动打包的方式来看,两个APP、两个平台(iOS、Android),单个APP打包发布时间8min左右, 如果按平均每天各自打包5次来算(5次算是保守的),每天打包消耗的时间2h40min, 整个测试阶段打包最少也要消耗13h20min。可以看出消耗时间是也不少,如果这些时间可以省下来,小伙伴们完全可以做些其他有意义的事情。

    我所在的中心,后台部署是在Jenkins上进行的,然而APP持续集成是真空的。鉴于自己是从事iOS开发的,就先从iOS持续集成开始吧,安卓稍后再弄。以下是持续集成的一些经历~

    中心已经有了一台Jenkins服务器,就没必要再新搭一台了,但是iOS打包要基于Mac、Xcode,当然AppCode也可以,因平时用的少,此处不做介绍。Jenkins的服务器是Linux系统,Jenkins可以配置Slave(奴隶)服务器,实现分布式部署。于是决定在Jenkins的主节点下建一个从节点,用一台Mac来做Slave(奴隶)服务器,其实我更喜欢把这台Mac叫做节点机。

   

1、准备工作

1、配置MacOS slave,具体步骤如下:

1.1 、在偏好设置 ->共享 中开启 远程登录,参照下图:
image.png
1.2、创建节点

Jenkins -> 系统管理 -> 节点管理 -> 新建节点,输入节点名称,并勾选 固定节点,点击OK。

image.png
1.3、配置节点
image.png

需要注意的是,这里的远程工作目录,权限为ssh链接的用户可读写。

1.4、添加Credentials

这里我选择是的SSH Username with private key。

image.png
1.5、配置节点属性
image.png

此处需要注意的是:PATH环境变量,需要在Mac 终端输入echo $PATH,然后将值copy过去

image.png

Keychains and Provisioning Profiles路径要填写正确。没有这个选项的安装Keychains and Provisioning Profiles Management插件。

1.6、保存
image.png

以上即添加Mac Slave成功,且Mac Slave在线。若连不上,请反复确认远程工作目录的权限、以及网络。

节点启动失败后,确认权限、网络都正常,可以尝试重启节点代理。

image.png

2、Jenkins系统配置

2.1、配置证书、描述文件

在 Jenkins > 系统管理 > Keychains and Provisioning Profiles Management,配置证书、描述文件。如下:

image.png

注意:login.keychain 在目录/Users/xxx/Library/Keychains/login.keychain下,Password是自己Mac的登录密码

2.2、Jenkins > 系统管理 > 系统设置 中设置 Xcode和keychain
image.png

注意:Keychain的路径:/Users/xxx/Library/Keychains/login.keychain,也可以这么写${HOME}/Library/Keychains/login.keychain,密码为Mac登录密码。

3、配置iOS项目

3.1、新建任务
image.png
3.2、General
image.png

注意:指定Mac Slave服务器来作为构建Xcode工程的Slave服务器,Xcode打包构建将在该节点上进行。

3.3、配置源码

此处配置代码从git上拉取

image.png

注意:Credentials为git用户名、密码,点击添加,去新建一个。

image.png
3.4、构建环境
image.png
3.5、构建

打包并发布到蒲公英

image.png

这里用到了fastlane来打包,fastlane是一套自动化打包的工具集,用 Ruby 写的,用于 iOS 和 Android 的自动化打包和发布等工作。gym是其中的打包命令。
fastlane 的官网看这里, fastlane 的 github 看这里

安装fastlane

使用Homebrew安装:
$ brew cask install fastlane

或者Rubygems安装:
$ sudo gem install fastlane -NV
或者
$  sudo gem install fastlane --verbose

具体构建脚本如下

# 构建  
#!/bin/bash -l  
export LANG="en_US.UTF-8"  
export LANGUAGE="en_US.UTF-8"  
export LC_ALL="en_US.UTF-8"  
  
pod install --verbose --no-repo-update 

# 打包环境 (核心)
#config="Release"
config="Debug"

# 导出安装包方式
#export_method="app-store"  
#export_method="ad-hoc"  
export_method="development"  
#export_method="enterprise"  

# ipa 包名
ipa_name="xxx"

#指定ipa输出地址
ipa_path="${WORKSPACE}/build/products"

fastlane gym --workspace Project.xcworkspace --scheme Project --clean --configuration ${config} --export_method ${export_method} --output_name ${ipa_name} --output_directory ${ipa_path}

echo "===上传至蒲公英平台==="

# 蒲公英userkey
pgyerUserKey="xxx"

# 蒲公英apiKey
pgyerApiKey="xxx"

# 更新版本
buildUpdateDescription="测试环境"

# 安装类型 2:密码安装,3:邀请安装
buildInstallType="2"

# 安装密码
buildPassword="xxx"

#open ${ipa_path}

packageTime="打包时间:【`date \"+%Y-%m-%d %H:%M:%S\"`】---"
echo $packageTime
echo "===开始上传蒲公英平台==="

if [ -e ${ipa_path}/${ipa_name}.ipa ]; then
    RESULT=$(curl -F "_api_key=${pgyerApiKey}" \
    -F "buildInstallType=${buildInstallType}" \
    -F "buildPassword=${buildPassword}" \
    -F "buildUpdateDescription=${buildUpdateDescription}" \
    -F "file=@${ipa_path}/${ipa_name}.ipa" \
    https://www.pgyer.com/apiv2/app/upload)
    echo ${RESULT}
    if [ "${RESULT}" ]; then
        echo "===上传蒲公英平台成功==="
        
        # 打包结果同步到钉钉群
        curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
            -H 'Content-Type: application/json' \
            -d '{"msgtype": "text", 
                 "text": {
                      "content": "xxx iOS App更新(测试环境) \n\n下载地址:https://www.pgyer.com/xxx \n安装密码:xxx"
                }
               }'
   else
        echo "===上传蒲公英平台失败==="
        
        # 打包结果同步到钉钉群,失败自动@相关负责人
        curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
            -H 'Content-Type: application/json' \
            -d '{"msgtype": "text", 
                 "text": {
                      "content": "xxx iOS App(测试环境),打包失败 \n上传蒲公英平台失败"
                 },
                 "at": {
                    "atMobiles": [
                              "18000000000"
                    ],
                    "isAtAll": false
                 }
                }'
    fi
else
    echo "===上传蒲公英平台失败==="
    
    # 打包结果同步到钉钉群,失败自动@相关负责人
    curl 'https://oapi.dingtalk.com/robot/send?access_token=xxx' \
        -H 'Content-Type: application/json' \
        -d '{"msgtype": "text", 
             "text": {
                  "content": " xxx iOS App(测试环境),打包失败 \n上传蒲公英平台失败"
             },
             "at": {
                "atMobiles": [
                          "18000000000"
                    ],
                "isAtAll": false
                 }
            }'
fi

# xcode中archive路径
#archive_path="/Users/wpapp/Library/Developer/Xcode/Archives"
 
#echo "===移除Xcode中Archives记录==="

# 删除Archives文件夹
#rm -r $archive_path

# 清空Archives文件夹中的文件,保留Archives文件夹
#rm -rf $archive_path/*

# 判断Archives文件夹是否为空
#if [ "`ls -A ${archive_path}`" = "" ];
#then 
#        echo "Archive记录清除成功"
#else
#        echo "Archive记录清除失败"
#fi

注意:上传蒲公英的API有两个,分别是API 1.0、API 2.0。API 1.0蒲公英已不再维护,此处选择用API 2.0上传。必填参数一定要填,前段时间蒲公英出现系统技术失误后,安装密码有选填变成了必填。
两种API的具体参数,请参考 API 1.0API 2.0

IPA包上传蒲公英,此处采用的是脚本,也可以用Jenkins集成的蒲公英上传插件

image.png

蒲公英上传的API,上面有描述,这里不再赘述。

配置钉钉群通知

使用 Webhook 地址,向钉钉群推送消息。
操作步骤:钉钉群设置-智能群助手-添加机器人,选择自定义机器人,如图:


image.png

配置机器人:


image.png

安全设置目前有3种方式:

(1)方式一,自定义关键词

    最多可以设置10个关键词,消息中至少包含其中1个关键词才可以发送成功。

    例如:添加了一个自定义关键词:监控报警
则这个机器人所发送的消息,必须包含 监控报警 这个词,才能发送成功。

(2)方式二,加签

    第一步,把timestamp+"\n"+密钥当做签名字符串,使用HmacSHA256算法计算签名,然后进行Base64 encode,最后再把签名参数再进行urlEncode,得到最终的签名(需要使用UTF-8字符集)。

    第二步,把 timestamp和第一步得到的签名值拼接到URL中。

(3)方式三,IP地址(段)

    设定后,只有来自IP地址范围内的请求才会被正常处理。支持两种设置方式:IP、IP段,暂不支持IPv6地址白名单,格式如下:


image.png

    注意:安全设置的上述三种方式,需要至少设置其中一种,以进行安全保护。校验不通过的消息将会发送失败,错误如下:

// 消息内容中不包含任何关键词
{
  "errcode":310000,
  "errmsg":"keywords not in content"
}

// timestamp 无效
{
  "errcode":310000,
  "errmsg":"invalid timestamp"
}

// 签名不匹配
{
  "errcode":310000,
  "errmsg":"sign not match"
}

// IP地址不在白名单
{
  "errcode":310000,
  "errmsg":"ip X.X.X.X not in whitelist"
}

   
   
此处选用方式一,自定义关键词来进行配置


image.png

钉钉群通知,详细配置请查看文档

构建成功效果图

状态集:

image.png

控制台输出:

image.png

钉钉群通知


image.png
image.png

   

问题记录
问题1:

Unable to locate Xcode. Please make sure to have Xcode installed on your machine

解决方法:

在Xcode中没有设置“Command Line Tools”:打开Xcode偏好设置,选择"Location"选项卡,选择相应的“Command Line Tools”即可

问题2:

Alternatively you can provide the provisioning profile mapping manually

image.png
解决方法:

先在xcode上archive一次包,把证书更新下来,就OK了。原因:通过xcode管理证书,并未把所有证书同步到本地,archive导出IPA的时候,会同步打包所需的证书到本地。

问题三:

构建成功,钉钉却收不到通知

解决方法:

钉钉机器人安全配置,选用自定义关键词,钉钉通知脚本中,通知内容未包含关键词,导致构建成功,钉钉群却收不到通知。

至此,iOS持续集成结束。
   

总结

   
    iOS持续集成,更多在于对Slave(奴隶)服务器/从节点的理解,在从节点上建一个Jenkins工作目录,这个目录Jenkins必须要有读写的权限,之前在这里吃了亏,配了Linux服务器(主节点)Jenkins的工作目录,导致代码没拉到Mac上,没法构建。构建的时候一定要先解锁keychain,再构建。
   
    下一篇:Android 持续集成(Jenkins+Gradle+360加固+蒲公英+钉钉群通知)

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

推荐阅读更多精彩内容