Android Jenkins CI集成

Android Jenkins 集成

Jenkins是一个独立的基于Java的程序,随时可以运行,包含Windows,Mac OS X和其他类Unix操作系统的软件包。作为可扩展的自动化服务器,Jenkins可以用作简单的CI服务器,也可以用作任何项目的持续交付中心。

环境准备

Jenins安装

Jenkins安装推荐使用apt命令,这样相比手动下载安装包来配置的好处在于,apt命令安装完的软件相应配置基本都按照文件夹已分类,并在/etc/init.d/xxx文件夹下会创建该软件命名的启动脚本。

Jekins的apt命令安装方式

1
2
3
4
5
6
7
8
9
# 1.向系统添加Jenkins密钥
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
# 2.添加软件源到系统/etc/apt/sources.list
deb https://pkg.jenkins.io/debian-stable binary/
# 3. 使用apt-get命令安装
sudo apt-get update
sudo apt-get install jenkins

安装完成后可能会出现如下报错:

Jenkins启动失败

如上图ERROR:No Java executable found in current PATH:...意思是在启动脚本中没有找到可执行的java路径。

解决:

1 . 打开sudo vi /etc/init.d/jenkins,找到JAVA=`type -p java `java改为你的jdk java的全路径

Jenkins启动脚本修改

2 . 打开sudo vi /etc/default/jenkins,修改jenkins监听端口

修改Jeknins启动端口

3 . 使用service jenkins restart启动Jenkins

4 . 浏览器中通过http://127.0.0.1:8888访问Jenkins

5 . 使用cat命令查看密码,并使用admin账号进行登录cat /home/dev/.jenkins/secrets/initialAdminPassword

如果是自己下载安装包配置,使用Java命令启动Jenins及初始化java -jar jenkins.war --httpPort=8888

系统在初始化时,会下载一些必要的插件,等待下载完成即可使用。

插件管理及系统设置

Jeninks提供了大量的插件,供开发人员使用。如果未找到合适的,可自己开发相应的开源插件。

Android CI需要如下插件(根据个人及公司需要自行选择):

  • Email Extension Plugin(用于构建后邮件通知)
  • Git Parameter Plug-In(提供参数化构建)
  • Gradle Plugin(用户打包编译)
  • Locale plugin(用于汉化Jenkins)
  • Dingding[钉钉] Plugin(用于构建后使用webhook通知)

新建任务及配置

主界面

主界面

选择【系统管理】-【系统设置】

系统设置】

进入系统设置,配置全局变量ANDROID_HOME、汉化、Jenkins Location信息填写

ANDROID_HOME、汉化、Jenkins Location信息填写

配置Git账号信息

配置Git账号信息

配置邮件通知

配置邮件通知
配置邮件通知

配置完成系统环境后,返回【系统管理】选择【全局工具配置】,指定JDK、Gradle及Git的环境信息

全局工具配置
全局工具配置

【系统设置】及【全局工具配置】完成后,就可以创建任务进行配置我们的打包项目了

创建任务

通用配置,选择参数化配置,参数化配置可选择10多种参数类型,但Git Parameter参数需要使用Git Parameter Plugins支持

主界面
主界面

【源码管理】这里指定项目的git地址以及用户名和密码,并指定需要拉取源码的分支路径,这里使用了master主分支

主界面

根据情况而定,如果使用了SSH登录则选择SSH username with private key(具体SSH配置自行百度)

主界面

【构建触发器】构建触发器可配置何时来触发Jenkins自动执行任务,有脚本,定时任务等多种配置

【构建环境】貌似没看到太大做用在此处

【构建】构建需要指定Gradle的版本如果在【全局工具配置】中加入后该处会显示,Tasks即在使用Gradle编译时的命令:

1
2
3
4
5
clean assemble${PRODUCT_FLAVORS}${BUILD_TYPE} --stacktrace --debug
clean:作用是在编译前清除原始build产物
assemble${PRODUCT_FLAVORS}${BUILD_TYPE}:会拼接成为一个buildTask,例如:assembleWandoujiaDebug,该任务可参考AS右侧Gradle-:app-build中的任务列表

构建

【构建后操作】构建后可选择使用邮件通知或webhook通知,这里使用了邮件通知+钉钉的Webhook机器人通知

构建后操作
构建后操作

注:钉钉的通知插件有2个目前【Dingding[钉钉]Plugin】【Dingding JSON Pusher Plugin】,后者是支持Json数据格式发送的即钉钉支持的所有消息格式,但是亲测不生效。也不知道是自己配置错误的问题。第一个则支持的其实是link消息格式。但是Link消息格式不知道如何指定@人,所以这里使用了另一种解决方法,使用[shell curl]命令进行网络请求测试发送(详见上图【构建-执行shell命令】及钉钉开放平台文档)。

配置完成后,返回主界面,进入创建的工程,选择左面的Build with Parameters进行参数化构建

参数化构建

构建完成后的邮件通知:

参数化构建

构建完成后的钉钉通知:

参数化构建


Jenkins内建环境变量

以下是Jenkins的一些内部环境变量,在你的Jenkins项目中可以找到例如:

http://192.168.10.123:8888/env-vars.html

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
The following variables are available to shell scripts
BRANCH_NAME
For a multibranch project, this will be set to the name of the branch being built, for example in case you wish to deploy to production from master but not from feature branches; if corresponding to some kind of change request, the name is generally arbitrary (refer to CHANGE_ID and CHANGE_TARGET).
CHANGE_ID
For a multibranch project corresponding to some kind of change request, this will be set to the change ID, such as a pull request number, if supported; else unset.
CHANGE_URL
For a multibranch project corresponding to some kind of change request, this will be set to the change URL, if supported; else unset.
CHANGE_TITLE
For a multibranch project corresponding to some kind of change request, this will be set to the title of the change, if supported; else unset.
CHANGE_AUTHOR
For a multibranch project corresponding to some kind of change request, this will be set to the username of the author of the proposed change, if supported; else unset.
CHANGE_AUTHOR_DISPLAY_NAME
For a multibranch project corresponding to some kind of change request, this will be set to the human name of the author, if supported; else unset.
CHANGE_AUTHOR_EMAIL
For a multibranch project corresponding to some kind of change request, this will be set to the email address of the author, if supported; else unset.
CHANGE_TARGET
For a multibranch project corresponding to some kind of change request, this will be set to the target or base branch to which the change could be merged, if supported; else unset.
BUILD_NUMBER
The current build number, such as "153"
BUILD_ID
The current build ID, identical to BUILD_NUMBER for builds created in 1.597+, but a YYYY-MM-DD_hh-mm-ss timestamp for older builds
BUILD_DISPLAY_NAME
The display name of the current build, which is something like "#153" by default.
JOB_NAME
Name of the project of this build, such as "foo" or "foo/bar".
JOB_BASE_NAME
Short Name of the project of this build stripping off folder paths, such as "foo" for "bar/foo".
BUILD_TAG
String of "jenkins-${JOB_NAME}-${BUILD_NUMBER}". All forward slashes ("/") in the JOB_NAME are replaced with dashes ("-"). Convenient to put into a resource file, a jar file, etc for easier identification.
EXECUTOR_NUMBER
The unique number that identifies the current executor (among executors of the same machine) that’s carrying out this build. This is the number you see in the "build executor status", except that the number starts from 0, not 1.
NODE_NAME
Name of the agent if the build is on an agent, or "master" if run on master
NODE_LABELS
Whitespace-separated list of labels that the node is assigned.
WORKSPACE
The absolute path of the directory assigned to the build as a workspace.
JENKINS_HOME
The absolute path of the directory assigned on the master node for Jenkins to store data.
JENKINS_URL
Full URL of Jenkins, like http://server:port/jenkins/ (note: only available if Jenkins URL set in system configuration)
BUILD_URL
Full URL of this build, like http://server:port/jenkins/job/foo/15/ (Jenkins URL must be set)
JOB_URL
Full URL of this job, like http://server:port/jenkins/job/foo/ (Jenkins URL must be set)
GIT_COMMIT
The commit hash being checked out.
GIT_PREVIOUS_COMMIT
The hash of the commit last built on this branch, if any.
GIT_PREVIOUS_SUCCESSFUL_COMMIT
The hash of the commit last successfully built on this branch, if any.
GIT_BRANCH
The remote branch name, if any.
GIT_LOCAL_BRANCH
The local branch name being checked out, if applicable.
GIT_URL
The remote URL. If there are multiple, will be GIT_URL_1, GIT_URL_2, etc.
GIT_COMMITTER_NAME
The configured Git committer name, if any.
GIT_AUTHOR_NAME
The configured Git author name, if any.
GIT_COMMITTER_EMAIL
The configured Git committer email, if any.
GIT_AUTHOR_EMAIL
The configured Git author email, if any.
SVN_REVISION
Subversion revision number that's currently checked out to the workspace, such as "12345"
SVN_URL
Subversion URL that's currently checked out to the workspace.

其他配置

  • 邮箱配置

不使用模板:
例如邮件配置可以指定为以下形式,

1
2
3
4
5
6
7
8
9
10
11
12
邮件由Jenkins自动发出(请勿回复!)<br />
项目名称:$PROJECT_NAME <br />
构建编号:# $BUILD_NUMBER <br />
构建状态:$BUILD_STATUS <br/>
触发原因:$CAUSE <br/>
日志地址:$BUILD_URL console <br/>
构建地址:<a href="$BUILD_URL">$BUILD_URL</a> <br/>
Apk地址:"http://192.168.10.123:8080/edu-release-v1.0.0.apk"
开发人员:<br/>
<a href="mailto:zhangsandev@gmail.com">张三</a> $nbsp;$nbsp;
<a href="mailto:lisidev@gmail.com">李四</a>

使用模板:
Jenkins默认自带groovy-html.template可以在邮件配置中使用
${SCRIPT,template="groovy-html.template"}进行配置,如果需要自己指定样式及模板,可将模板放置在.jenkins/email-template文件夹下(没有该文件夹手动创建)邮件配置中引用该模板即可。
groovy-html.template模板内容如下(我替换了一些英文为汉字):

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
<STYLE>
BODY, TABLE, TD, TH, P {
font-family: Calibri, Verdana, Helvetica, sans serif;
font-size: 12px;
color: black;
}
.console {
font-family: Courier New;
}
.filesChanged {
width: 10%;
padding-left: 10px;
}
.section {
width: 100%;
border: thin black dotted;
}
.td-title-main {
color: white;
font-size: 200%;
padding-left: 5px;
font-weight: bold;
}
.td-title {
color: white;
font-size: 120%;
font-weight: bold;
padding-left: 5px;
text-transform: uppercase;
}
.td-title-tests {
font-weight: bold;
font-size: 120%;
}
.td-header-maven-module {
font-weight: bold;
font-size: 120%;
}
.td-maven-artifact {
padding-left: 5px;
}
.tr-title {
background-color: <%= (build.result == null || build.result.toString() == 'SUCCESS') ? '#27AE60' : build.result.toString() == 'FAILURE' ? '#E74C3C' : '#f4e242' %>;
}
.test {
padding-left: 20px;
}
.test-fixed {
color: #27AE60;
}
.test-failed {
color: #E74C3C;
}
</STYLE>
<BODY>
<!-- BUILD RESULT -->
<table class="section">
<tr class="tr-title">
<td class="td-title-main" colspan=2>
BUILD ${build.result ?: 'COMPLETED'}
</td>
</tr>
<tr>
<td>构建路径:</td>
<td><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></td>
</tr>
<tr>
<td>项目名称:</td>
<td>${project.name}</td>
</tr>
<tr>
<td>构建日期:</td>
<td>${it.timestampString}</td>
</tr>
<tr>
<td>构建用时:</td>
<td>${build.durationString}</td>
</tr>
<tr>
<td>触发原因:</td>
<td><% build.causes.each() { cause -> %> ${cause.shortDescription} <% } %></td>
</tr>
<tr>
<td>开发人员</td>
<td>
<a href="mailto:wangxiaoliang@danyuantech.com">王晓亮</a> &nbsp;&nbsp:
<a href="mailto:gaopengfei@danyuantech.com">高鹏飞</a>
</td>
</tr>
<tr>
<td>Apk下载:</td>
<td><a href="http://192.168.10.123:8080/download/android/edu">下载</a></td>
</tr>
</table>
<br/>
<!-- CHANGE SET -->
<%
def changeSets = build.changeSets
if(changeSets != null) {
def hadChanges = false %>
<table class="section">
<tr class="tr-title">
<td class="td-title" colspan="2">变更记录</td>
</tr>
<% changeSets.each() {
cs_list -> cs_list.each() {
cs -> hadChanges = true %>
<tr>
<td>
修订版本
<%= cs.metaClass.hasProperty('commitId') ? cs.commitId : cs.metaClass.hasProperty('revision') ? cs.revision : cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %>
by <B><%= cs.author %></B>
</td>
<td>${cs.msgAnnotated}</td>
</tr>
<% cs.affectedFiles.each() {
p -> %>
<tr>
<td class="filesChanged">${p.editType.name}</td>
<td>${p.path}</td>
</tr>
<% }
}
}
if ( !hadChanges ) { %>
<tr>
<td colspan="2">No Changes</td>
</tr>
<% } %>
</table>
<br/>
<% } %>
<!-- ARTIFACTS -->
<%
def artifacts = build.artifacts
if ( artifacts != null && artifacts.size() > 0 ) { %>
<table class="section">
<tr class="tr-title">
<td class="td-title">BUILD ARTIFACTS</td>
</tr>
<% artifacts.each() {
f -> %>
<tr>
<td>
<a href="${rooturl}${build.url}artifact/${f}">${f}</a>
</td>
</tr>
<% } %>
</table>
<br/>
<% } %>
<!-- MAVEN ARTIFACTS -->
<%
try {
def mbuilds = build.moduleBuilds
if ( mbuilds != null ) { %>
<table class="section">
<tr class="tr-title">
<td class="td-title">BUILD ARTIFACTS</td>
</tr>
<%
try {
mbuilds.each() {
m -> %>
<tr>
<td class="td-header-maven-module">${m.key.displayName}</td>
</tr>
<%
m.value.each() {
mvnbld -> def artifactz = mvnbld.artifacts
if ( artifactz != null && artifactz.size() > 0) { %>
<tr>
<td class="td-maven-artifact">
<% artifactz.each() {
f -> %>
<a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a><br/>
<% } %>
</td>
</tr>
<% }
}
}
} catch(e) {
// we don't do anything
} %>
</table>
<br/>
<% }
} catch(e) {
// we don't do anything
} %>
<!-- JUnit TEMPLATE -->
<%
def junitResultList = it.JUnitTestResult
try {
def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
junitResultList.add( cucumberTestResultAction.getResult() )
} catch(e) {
//cucumberTestResultAction not exist in this build
}
if ( junitResultList.size() > 0 ) { %>
<table class="section">
<tr class="tr-title">
<td class="td-title" colspan="5">${junitResultList.first().displayName}</td>
</tr>
<tr>
<td class="td-title-tests">Name</td>
<td class="td-title-tests">Failed</td>
<td class="td-title-tests">Passed</td>
<td class="td-title-tests">Skipped</td>
<td class="td-title-tests">Total</td>
</tr>
<% junitResultList.each {
junitResult -> junitResult.getChildren().each {
packageResult -> %>
<tr>
<td>${packageResult.getName()}</td>
<td>${packageResult.getFailCount()}</td>
<td>${packageResult.getPassCount()}</td>
<td>${packageResult.getSkipCount()}</td>
<td>${packageResult.getPassCount() + packageResult.getFailCount() + packageResult.getSkipCount()}</td>
</tr>
<% packageResult.getPassedTests().findAll({it.getStatus().toString() == "FIXED";}).each{
test -> %>
<tr>
<td class="test test-fixed" colspan="5">
${test.getFullName()} ${test.getStatus()}
</td>
</tr>
<% } %>
<% packageResult.getFailedTests().sort({a,b -> a.getAge() <=> b.getAge()}).each{
failed_test -> %>
<tr>
<td class="test test-failed" colspan="5">
${failed_test.getFullName()} (Age: ${failed_test.getAge()})
</td>
</tr>
<% }
}
} %>
</table>
<br/>
<% } %>
<!-- CONSOLE OUTPUT -->
<%
if ( build.result == hudson.model.Result.FAILURE ) { %>
<table class="section" cellpadding="0" cellspacing="0">
<tr class="tr-title">
<td class="td-title">控制台输出</td>
</tr>
<% build.getLog(100).each() {
line -> %>
<tr>
<td class="console">${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}</td>
</tr>
<% } %>
</table>
<br/>
<% } %>
</BODY>
  • 构建后配置-归档成品:该配置只适用于将成品生成到workspaces下,其他路径不生效,归档成品后会在工程页面展示成品信息

  • 构建后发布到蒲公英:文档

  • 补充:以下为一份完整的构建后360加固+蒲公英发布+钉钉通知的shell脚本

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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/bin/bash
# Android 360加固脚本 + 蒲公英上传 + 钉钉WebHook通知
# ########################################################CONFIGRATION START#################################################################
# Application Name
APP_NAME="应用名"
# DingTalkNotify banner url
NOTIFY_BANNER_URL="http://images.imeina.cn/images/banner-android-qingxiuzi.jpg"
# Pgyer ApiKey
PGYER_API_KEY="修改成你应用的蒲公英API_KEY"
PGYER_APP_URL="https://www.pgyer.com/应用蒲公英地址"
# DingTalk WebHook AccessToken
DINGDING_ACCESS_TOKEN="钉钉机器人access_token"
# Set CHANGE_LOG default value
if [[ -z ${CHANGE_LOG} ]]; then
CHANGE_LOG="暂无"
fi
# 360 jiagu config
BASE_JAR=360加固jar包完整路径 #/opt/360jiagu/jiagu/jiagu.jar
USERNAME=填写360加固账号
PASSWORD=密码
MULPKG_FILE_PATH=360加固多渠道模板信息 #/opt/360jiagu/jiagu/multi-channel.txt
# #########################################################CONFIGRATION END###################################################################
# Apk source dir && apk target dir
APK_SOURCE_DIR_PATH=${OUTPUT_FILE_BASE_PATH}
APK_TARGET_DIR_PATH=${OUTPUT_FILE_BASE_PATH}360jiagu
# Get the latest ProductionEnv apk file by change time
APK_SOURCE_NAME=`ls ${APK_SOURCE_DIR_PATH} -lt |grep release.apk | head -n 1 | awk '{print $9}'`
APK_SOURCE_PATH="${APK_SOURCE_DIR_PATH}${APK_SOURCE_NAME}"
echo "APK_SOURCE_DIR_PATH: ${APK_SOURCE_DIR_PATH}"
echo "APK_TARGET_DIR_PATH: ${APK_TARGET_DIR_PATH}"
echo "APK_SOURCE_NAME: ${APK_SOURCE_NAME}"
echo "APK_SOURCE_PATH: ${APK_SOURCE_PATH}"
# DingTalk beta notify commond
function dingTalkBetaNotify(){
echo ${APP_NAME} ${NOTIFY_BANNER_URL} ${VERSION_NAME} $1 $2 ${CHANGE_LOG}
echo ${1} ${2}
curl 'https://oapi.dingtalk.com/robot/send?access_token='${DINGDING_ACCESS_TOKEN} \
-H 'Content-Type: application/json' \
-d '{"actionCard":{"title":"《'${APP_NAME}'》Android内测版更新","text":"![banner]('${NOTIFY_BANNER_URL}') \n\n《'${APP_NAME}'》Android内测版更新!\n\n 应用名称:'${APP_NAME}' \n\n 版本信息:V'${VERSION_NAME}' \n\n 应用大小:'${1}' \n\n 更新时间:'${2}' \n\n 更新日志:\n\n '${CHANGE_LOG}'","hideAvatar":"0","btnOrientation":"0","btns":[{"title":"去下载","actionURL":"'${PGYER_APP_URL}'"}]},"msgtype":"actionCard"}'
}
# DingTalk release notify commond
function dingTalkReleaseNotify(){
curl 'https://oapi.dingtalk.com/robot/send?access_token='${DINGDING_ACCESS_TOKEN} \
-H 'Content-Type: application/json' \
-d '{"msgtype":"markdown","markdown":{"title":"《'${APP_NAME}'》Android正式版构建通知","text":"![banner]('${NOTIFY_BANNER_URL}') \n\n ### Android正式版更新!\n\n 应用名称:'${APP_NAME}' \n\n 版本信息:V'${VERSION_NAME}' \n\n 更新日志:\n\n '${CHANGE_LOG}' \n\n @18500223348 @18210409844 \n\n 请前往[文件服务器](http://192.168.10.123/download) 下载最新版本!"},"at":{"atMobiles":["18500223348", "18210409844"],"isAtAll":false}}'
exit 0
}
# Pgyer upload commond
function uploadToPgyer(){
response=$(curl 'https://www.pgyer.com/apiv2/app/upload' -F 'file=@'${APK_SOURCE_PATH} -F '_api_key='${PGYER_API_KEY} -F 'buildUpdateDescription='${CHANGE_LOG})
echo ${response}
# If upload success,dingTalk notify...
if [[ -n ${response} && $(echo ${response} | jq '.code') = 0 ]]; then
APP_LENGTH=$(echo ${response} | jq '.data.buildFileSize')
UPDATE_TIME=$(echo ${response} | jq '.data.buildUpdated')
echo "APP_NAME:${APP_NAME} APP_LENGTH:${APP_LENGTH} UPDATE_TIME:${UPDATE_TIME}"
dingTalkBetaNotify ${APP_LENGTH//\"/} ${UPDATE_TIME//\"/}
fi
exit 0;
}
echo "开始判断..."
# If APK_SOURCE_PATH exist and APK_SOURCE_NAME contains "productionEnv" char execute jiagu
if [[ -e ${APK_SOURCE_PATH} && ${APK_SOURCE_NAME} =~ "productionEnv" && ${PRODUCT_FLAVORS} = "ProductionEnv" ]]; then
echo "--------->This build is ProductionEnv,Running 360jiagu...<---------"
elif [[ -e ${APK_SOURCE_PATH} && ${APK_SOURCE_NAME} =~ "tEnv" && ${PRODUCT_FLAVORS} = "TEnv" ]]; then
echo "--------->This build is TEnv,Upload apk to pgyer...<---------"
uploadToPgyer
else
exit 0;
fi
echo "判断结束..."
if [[ ! -d ${APK_TARGET_DIR_PATH} ]]; then
echo "--------->APK_TARGET_DIR_PATH not exist!Mkdir...<---------"
mkdir ${APK_TARGET_DIR_PATH}
fi
echo "--------->360jiagu running...<---------"
java -jar ${BASE_JAR} -version
# Auto login
echo "--------->360jiagu auto login...<---------"
java -jar ${BASE_JAR} -login ${USERNAME} ${PASSWORD}
# Import signinfo
KEYSTORE_PROPERTIES_PATH=${WORKSPACE}/keystore.properties
echo "KEYSTORE_PROPERTIES_PATH: ${KEYSTORE_PROPERTIES_PATH}"
if [[ ! -r ${KEYSTORE_PROPERTIES_PATH} ]]; then
echo "--------->keystore.properties not exist or can not read,exit...<---------"
echo "${KEYSTORE_PROPERTIES_PATH}"
exit 0
fi
# Read edu.jks KeyStore Alias AliasPwd field.
KEYSTORE_PATH=$(echo ${WORKSPACE}/*.jks)
KEYSTORE_PWD=`cat ${KEYSTORE_PROPERTIES_PATH} |grep keyPassword= | awk -F= '{print $2}'`
ALIAS=`cat ${KEYSTORE_PROPERTIES_PATH} |grep keyAlias= | awk -F= '{print $2}'`
ALIAS_PWD=`cat ${KEYSTORE_PROPERTIES_PATH} |grep storePassword= | awk -F= '{print $2}'`
echo "KEYSTORE_PATH: ${KEYSTORE_PATH}"
echo "KEYSTORE_PWD: ${KEYSTORE_PWD}"
echo "ALIAS: ${ALIAS}"
echo "ALIAS_PWD: ${ALIAS_PWD}"
# Import sign file
java -jar ${BASE_JAR} -importsign ${KEYSTORE_PATH} ${KEYSTORE_PWD} ${ALIAS} ${ALIAS_PWD}
# Import mulpkg
java -jar ${BASE_JAR} -importmulpkg ${MULPKG_FILE_PATH}
# Show mulpkg info
echo "--------->360jiagu mulpkg info<---------"
java -jar ${BASE_JAR} -showmulpkg
# Execute jiagu task
java -jar ${BASE_JAR} -jiagu ${APK_SOURCE_PATH} ${APK_TARGET_DIR_PATH} -autosign -automulpkg
echo "--------->360jiagu complete...<---------"
dingTalkReleaseNotify

参考文章:

如果帮到了你,想打赏支持,喏~