jenkins自动化构建最佳实践 for Android

需求:

每个人的需求可能不太一样,我的需求比较简单,因为我是一个人前后端全栈开发,目前不涉及到研发团队部分所以工作环境比较简单。

但是分发的工作不是我去做的,特别是针对国内的各大平台上架事宜,是由我的合作伙伴去做。另外就是外包活接的比较多,给甲方发包也比较频繁。

曾经我的发包模式,就是将apk打个压缩包,然后发群里,各种项目交叉发包和版本追溯也确实有点烦人。

因此我不得不花点时间去配置一个自动化构建系统,以解决我当前的混乱的发布流程。

方案:

我使用war的方式部署jenkins以便后期无缝转移其他平台。

安装教程

1
2
wget https://ftp-nyc.osuosl.org/pub/jenkins/war-stable/latest/jenkins.war
java -jar jenkins.war --httpPort=8000

注意:默认情况下工作目录在 ~/.jenkins ,更改默认工作路径需要配置个环境变量,然后再重启下服务即可

1
export JENKINS_HOME=/home/JenkinsWorkspace

需要用到的插件

Maven Integration 构建maven项目用的
Email Extension 构建完成发送邮件通知用
Post build task 构建完成执行脚本用的
Role-based Authorization Strategy 配置用户项目访问权限用的

具体的我找到两篇教程供参考

Jenkins 邮箱配置
Jenkins 权限配置

*重点说下邮件模板的配置,我的原则是Jenkins的配置不能有侵入性,项目工程既能Jenkins编译同时也兼顾本地编译或者其他编译环境。

下面解决如何在构建通知邮件中,获取项目的版本信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在gradle脚本中,添加日志输出:

println("*****************************************************")
println("vSTARTSTART")
println("v"+versionName+"("+versionCode+")")
println("vENDEND")
println("STARTSTART")
println("appName:xxx")
println("packageName:"+applicationId)
println("versionCode:"+versionCode)
println("versionName:"+versionName)
println("gitHash:"+gitHash())
println("buildTime:"+buildTime())
println("notes:N/A")
println("ENDEND")
println("*****************************************************")

Jenkins邮件正文中通过正则匹配的方式截取log输出:
${BUILD_LOG_EXCERPT, start ="^STARTSTART", end ="^ENDEND"}

邮件模板主题:

1
构建通知:xxx项目 ${BUILD_LOG_EXCERPT, start ="^vSTARTSTART", end ="^vENDEND"} - Build # $BUILD_NUMBER - $BUILD_STATUS!

邮件模板正文:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<!DOCTYPE html>
<html>

<head><meta charset="UTF-8"><title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title></head>

<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">

<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">

<tr>
<td><h2><font color="#20B2AA">构建结果 - ${BUILD_STATUS}</font></h2></td>
</tr>

<!--版本发布:-->
<tr>
<td><b><font color="#0B610B">版本发布:</font></b>
<hr size="2" width="100%" align="center" />
</td>
</tr>
<tr>
<td>
<pre>
${BUILD_LOG_EXCERPT, start ="^STARTSTART", end ="^ENDEND"}
下载链接(内网):<a href="${BUILD_URL}">${BUILD_URL}</a>
下载链接(外网):<a href="http://***/${BUILD_NUMBER}/">http://***/${BUILD_NUMBER}/</a>
</pre>
</td>
</tr>


<!-- 构建信息:-->
<tr>
<td>
<b><font color="#0B610B">构建信息:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称&nbsp;:&nbsp;${PROJECT_NAME}</li>
<li>构建编号&nbsp;:&nbsp;${BUILD_NUMBER}</li>
<li>Git&nbsp;branch:&nbsp;${GIT_BRANCH}</li>
<li>Git&nbsp;revision:&nbsp;${GIT_REVISION, length=7} &nbsp; full: ${GIT_REVISION}</li>
<li>发布者:&nbsp;${CAUSE}</li>
<li>构建日志:&nbsp;<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录&nbsp;:&nbsp;<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
</td>
</tr>




<!--提交信息-->
<tr>
<td><b><font color="#0B610B">Changes Since Last Successful Build:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
</ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br />%m</pre>",pathFormat="&nbsp;&nbsp;&nbsp;&nbsp;%p"} </td>
</tr>

<!--测试信息-->
<tr>
<td><b><font color="#0B610B">Failed Test Results:</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td><pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
<br /></td>
</tr>

<tr>
<td>(本邮件是Jenkins构建项目完成之后自动下发的,请勿回复!)</td>
</tr>

</table></body></html>

构建机的选择

构建机,这个比较重要,因为我有iOS编译需求,所以这里选择一台闲置的macbook(mbp2012)作为构建机器。这台电脑7*24为我服务,除了作为构建机使用外,还装了虚拟机也是我主要的本地测试环境,因此我升级了16g内存以及ssd,虽然有点老性能也基本够用我的原则就是只要能开机就一直用着。
备注:2012款的macbook已经不能当做iOS编译机使用了,因为新版的xcode需要macos11(bigsur)以上的版本才行,而macos11只支持2013款以后的机型。

内网穿透

内网穿透 由于是本地部署需要外网访问。偶然的机会我发现阿里提供了个免费的内网穿透工具,这个可以用于临时测试用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
如果你还没有公网域名,在本部分,你可以使用钉钉内网穿透工具,映射一个本地的公网域名使用。

1.打开命令行工具,执行以下命令,下载内网穿透工具。

git clone https://github.com/open-dingtalk/pierced.git

2.执行以下命令,启动内网穿透。

Windows执行以下命令:

cd windows_64
ding -config=ding.cfg -subdomain=abcde 8080

MAC执行以下命令:

cd mac_64
chmod 777 ./ding
./ding -config=./ding.cfg -subdomain=abcde 8080

注意 启动内网穿透时,请不要直接使用abcde字符串,如果需要使用默认端口8080,需确保在同一内网环境下该字符串唯一且未重复使用,如果重复,启动后可能会出现访问端口不一致问题。

3.启动完客户端后,你访问http://abcde.vaiwan.com/xxxxx都会映射到http://127.0.0.1:8080/xxxxx。

4.重启后端服务。

结果与发布:

发包流程可以根据实际情况去处理,同一个项目可以多拷贝几份构建ITEM以满足不同的需求,

比如 每日构建, 每次git提交构建,以及正式发包构建。等等。

由于我是单兵作战,所以只有发部新包的时候手动构建。这样只要在邮件列表的人就会收到以下邮件,然后根据需要再去下载即可。我只关注的我自己的工作流,至于别人的流程我并不关注。

  • 版本命名
versionCode versionName
211112(yyMMDD) 1.0.1(根据版本情况自定义)

versionCode. 客户端是不可见的,主要用于版本升级,比如热更强更,以及上架的时候也会要求;主要针对研发标识版本的。

versionName. 客户端可见,通常更有意义的版本表述的方式,如 v1.1 beta 等;主要是为了方便传播与表述。我也习惯用 1.0.yy.mmDD 这种方式定义版本名称。

  • 包体命名

app-com.xxx-360-release-v1.0.1(211028)-20211115-162621-.apk

app com.xxx 360 release v1.0.1(211028) 20211115-162621
app 包名 渠道名 正式包 版本名(版本号) 编译时间(yyyyMMDD-HHMMSS)
Fred范方青 wechat
项目合作请联系我私人微信: fredtv23
0%