使用Jenkins进行iOS项目自动化发布

使用Jenkins进行iOS项目自动化发布

前段时间把iOS发布逻辑迁移到fastlane平台,现在发布调一下fastlane脚本就好,对开发人员极度友好。不过后来发现虽然开发人员用得爽了,不过还是要被测试妹子催着打包,于是想釜底抽薪,把这个功能做得更彻底一点,直接让测试妹子自己来打包,这样就把iOS开发同学彻底解放了~

公司内网已经部署了一台linux系统的jenkins服务器,上面集成了一些后端和前端的发布逻辑,所以直接添加一个iOS项目的发布流程就行。Xcode环境只能跑在Mac OS上,所以iOS项目的发布流程势必要做远程服务。

在调研的时候打算在Mac OS上启一个http server,自己写相关的逻辑。后来发现jenkins有远程job互调用的功能,所以方案就变成在Mac OS上也部署一套jenkins,暴露出一些打包服务,然后在公司的jenkins中调用。因为有两套jenkins环境的配置(提供服务的和使用服务的),姑且称之为调用端和执行端。下面就来简单说一下这两部分的具体配置。

主要流程

c-1

执行端

执行端主要就是提供一个http服务,用http协议来触发构建任务。下面是具体步骤:

  1. 在jenkins中新建一个任务,这里选“自由风格的软件项目”

a-0

  1. 然后在General中勾选“参数化构建过程”,这里因为需要接收主调方发送的构建参数,所以要选这一项。因为要通知调用方执行结果,所以构建参数里增加“callbackurl”

a-1

  1. 接着在构建触发器中勾选“触发远程构建”,并填写身份证令牌。这里的身份证令牌和用户无关,仅仅只是这个job的api令牌,这里可以随便填一个,只要不太容易被猜到就行

a-2

  1. 最后在构建中增加“执行shell”选项。这里可以写执行任务的逻辑,我这儿就是简单的切换到工程目录,再调用fastlane打包,结束后回调完成的url

a-3

1
2
3
4
cd ~/projectPath          #项目路径
git checkout branch #切换到指定分支
fastlane inhousepackage #调用fastlane完成打包
curl ${callbackurl} #调用回调url,通知调用方任务完成
  1. 到了这一步就完成了项目配置,不过因为用户认证相关的设置还没有完成,所以这个任务还不能被远程触发。点击右上角用户名可以进入到用户设置页面,点击设置,在“API Token”中添加一个token,使用这个token和用户名就能在其他机器上触发任务

a-5

  1. 完成上面这些设置后,会得到下列信息。主调方有了这些信息就能触发远程构建

    • 用户名(userName)

    • 用户令牌(userToken)

    • 任务令牌(jobToken)
    • 执行任务的机器ip地址,jenkins服务端口号码
    • jenkins任务名字(jobName)
    • 回调url,这个非必须,不过不传的话无法知道任务是否已经结束(callbackurl)
    1
    2
    3
    #最后用上面这些信息拼接成类似下面这样的URL,通过http协议访问就能触发这台机器上的远程任务
    jobTriggerURL = "http://${userName}:${userToken}@${jobServerIPAndPort}/job/${jobName}/buildWithParameters?token=${jobToken}&callbackurl=${callbackurl}"
    curl jobTriggerURL

调用端

当执行端设置好以后,调用端的设置就比较简单了。

  1. 在jenkins中新建一个任务,这里选“流水线”,因为调用端的逻辑用到了一些pipeline插件,而且还有一些逻辑要处理,用流水线可以实现更精确控制

b-1

  1. 在“高级项目选项”中的“流水线”里写下下面的逻辑:

b-2

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
34
35
36
37
38
stage ("Wait remote iOS package job finish.") {
node {
hook = registerWebhook() #这里使用了Webhook Step Plugin插件


ip = sh (
script: "ifconfig en0 | sed -n 's/[\\s\\t]*inet \\([0-9\\.]*\\) .*/\\1/p' | tr -d '\\t\\n'",
returnStdout: true
)


url = sh (
script: "echo \"${hook.getURL()}\" | sed -n 's/localhost:[0-9]*/${ip}:8080/p'",
returnStdout: true
)

#${hook.getURL()}获取的回调url中host部分是localhost,所以需要用本机ip替换


#这里的所有信息都是在执行实际任务的机器上获取的,具体细节看“执行端”部分
user = "username" #用户名字
userToken = "" #用户认证token
jobToken = "triggertoken123" #任务token
jobServerIP = "172.20.24.122:8080"
jobName = "iOS"


#获取到上面的这些信息以后拼接成下面这个样式的url,发送get请求就能触发远程job
#因为有些参数包含特殊字符,所以需要加上--data-urlencode来进行转义
jobTriggerURL = "http://${user}:${userToken}@${jobServerIP}/job/${jobName}/buildWithParameters"
echo "job url:${jobTriggerURL}"
sh("curl --data-urlencode \"token=${jobToken}\" --data-urlencode \"callbackurl=${url}\" ${jobTriggerURL}")


echo "Webhook called with data: ${url}"
data = waitForWebhook hook
}
}

脚本的主要逻辑是调用远程job,然后等待远程任务发送回调请求。这里用到了Webhook Step Plugin插件,它主要作用是获取一个回调URL,并挂起当前执行的脚本,直到回调url被调用以后再继续执行。

经过上面的配置后就能在公司jenkins上进行iOS项目自动化发布了。如果jenkins是在外网,则会麻烦一些,需要连vpn或者在NAT上做一个端口映射才行。