Android项目在Gitlab-CI上的使用

Setting up GitLab CI for Android projects

搭建Android环境
下载JDK
下载Android Sdk

由于我们安装的Runner环境一般都是在服务器上,是没有界面操作的,所有需要我们通过无ui 的方式下载更新安卓sdk,
先下载android sdk tools

1
2
- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
- unzip -q android-sdk.zip -d android-sdk-linux

要使用sdk tools下载sdk首先需要接受安卓sdk的协议

1
2
3
- mkdir android-sdk-linux/licenses
- printf "8933bad161af4178b1185d1a37fbf41ea5269c55\nd56f5187479451eabf01fb78af6dfcb131a6481e" > android-sdk-linux/licenses/android-sdk-license
- printf "84831b9409646a918e30573bab4c9c91346d8abd" > android-sdk-linux/licenses/android-sdk-preview-license

下载sdk
1
2
3
4
5
6
/home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager --update > update.log
# SDK检查更新
/home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" "build-tools;${ANDROID_BUILD_TOOLS}" "extras;google;m2repository" "extras;android;m2repository" > installPlatform.log
#下载sdk,support包等
/home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" > installPlatform.log
# 下载constrain包

但是由于众所周知的GFW的问题,在国内下载安卓sdk的速度着实让人崩溃,所以一般需要配置上国内镜像,如下:

1
sdkmanager --proxy=http --proxy_host=mirrors.neusoft.edu.cn --proxy_port=80 --update

具体镜像可以从网上找一下。

配置环境变量
1
2
3
4
5
6
7
# vim /home/gitlab-runner/.bash_profile

export JAVA_HOME=/home/gitlab-runner/CI_runner/jdk1.8.0_181
export ANDROID_HOME=/home/gitlab-runner/CI_runner/android-sdk-linux
export PATH=$PATH:$JAVA_HOME/bin
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools/
编写Gitlab CI脚本

配置完环境之后,就需要编写CI脚本完成自动打包,测试,部署等工作。

简介

配置好 Runner 之后,我们要做的事情就是在项目根目录中添加 .gitlab-ci.yml 文件了。
当我们添加了 .gitlab-ci.yml 文件后,每次提交代码或者合并 MR 都会自动运行构建任务了。

还记得 Pipeline 是怎么触发的吗?Pipeline 也是通过提交代码或者合并 MR 来触发的!
那么 Pipeline 和 .gitlab-ci.yml 有什么关系呢?
其实 .gitlab-ci.yml 就是在定义 Pipeline 而已拉!

基本写法

我们先来看看 .gitlab-ci.yml 是怎么写的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义 stages
stages:
- build
- test
# 定义 job
job1:
stage: test
script:
- echo "I am job1"
- echo "I am in test stage"
# 定义 job
job2:
stage: build
script:
- echo "I am job2"
- echo "I am in build stage"

写起来很简单吧!用 stages 关键字来定义 Pipeline 中的各个构建阶段,然后用一些非关键字来定义 jobs。
每个 job 中可以可以再用 stage 关键字来指定该 job 对应哪个 stage。
job 里面的 script 关键字是最关键的地方了,也是每个 job 中必须要包含的,它表示每个 job 要执行的命令。

回想一下我们之前提到的 Stages 和 Jobs 的关系,然后猜猜上面例子的运行结果?

1
2
3
4
I am job2
I am in build stage
I am job1
I am in test stage

根据我们在 stages 中的定义,build 阶段要在 test 阶段之前运行,所以 stage:build 的 jobs 会先运行,之后才会运行 stage:test 的 jobs。

常用的关键字

下面介绍一些常用的关键字,想要更加详尽的内容请前往 官方文档

  • stages
    定义 Stages,默认有三个 Stages,分别是 build, test, deploy。

  • before_script
    定义任何 Jobs 运行前都会执行的命令。

  • after_script
    定义任何 Jobs 运行完后都会执行的命令。

  • variables && Job.variables
    定义环境变量。
    如果定义了 Job 级别的环境变量的话,该 Job 会优先使用 Job 级别的环境变量。

我自己在项目中用到的例子
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
image: openjdk:8-jdk

cache:
paths:
- .m2/
- .gradle/

variables:
ANDROID_COMPILE_SDK: "27"
ANDROID_BUILD_TOOLS: "27.0.3"
ANDROID_SDK_TOOLS: "27.1.1"
APP_NAME: "长白山先锋"


before_script:
# - apt-get --quiet update --yes
# - apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
#
# - wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
# - unzip -q android-sdk.zip -d android-sdk-linux

# - mkdir android-sdk-linux/licenses
# - printf "8933bad161af4178b1185d1a37fbf41ea5269c55\nd56f5187479451eabf01fb78af6dfcb131a6481e" > android-sdk-linux/licenses/android-sdk-license
# - printf "84831b9409646a918e30573bab4c9c91346d8abd" > android-sdk-linux/licenses/android-sdk-preview-license
- echo $PATH
- whoami
- echo $PWD
- /home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager --update > update.log
- /home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager "platforms;android-${ANDROID_COMPILE_SDK}" "build-tools;${ANDROID_BUILD_TOOLS}" "extras;google;m2repository" "extras;android;m2repository" > installPlatform.log
- /home/gitlab-runner/CI_runner/android-sdk-linux/tools/bin/sdkmanager "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2" > installPlatform.log

# - export ANDROID_HOME=$PWD/android-sdk-linux
# - export PATH=$PATH:$PWD/android-sdk-linux/platform-tools/
- chmod +x ./gradlew

stages:
- build
# - test
- deploy

build:
stage: build
only:
- v3_0502
script:
# - ./gradlew assembleRelease
- ./gradlew assembleRelease
artifacts:
paths:
- $PWD/apk/

#unitTests:
# stage: test
# script:
# - ./gradlew test

deploy:
stage: deploy
script:
- echo $PATH
- rm -rfv /data/apps/${APP_NAME}
- mkdir /data/apps/${APP_NAME}
- cp $PWD/apk/*.apk /data/apps/${APP_NAME}
- lftp -u ftpuser_name,passwd -p port -e "mirror -R --delete --only-newer /data/apps/${APP_NAME} /ftp/apk ;quit;" sftp://xxx.xxx.xxx.xxx

# 把本地/data/apps/${APP_NAME}目录的文件拷贝到服务器/ftp/apk目录下,并且删除服务器/ftp/apk目录下的其他文件

问题 1
如果在代码提交之后,CI在下载代码的时候,报以下错误:

1
2
Peer's certificate issuer has been marked as not trusted by the user.
ERROR: Job failed: exit status 1

只需要在runner服务器上修改如下就行

1
2
3
4
# vim /etc/profile
#在最后一行加入

export GIT_SSL_NO_VERIFY=1

问题 2
在build结束的时候,runner会把生成的包当成artifacts上传到CI服务器上,如下所示文件

1
2
3
artifacts:
paths:
- $PWD/apk/

但是gitlba 默认只给每个项目100M的附件空间,所以如果你项目生成的文件比较多,有可能会报一下错误

1
2
ERROR: Uploading artifacts to coordinator... too large archive  id=1004 responseStatus=413 Request Entity Too Large status=413 Request Entity Too Large token=y9oZhbeX
FATAL: Too large

这时候只需调整如图所示图片即可

问题 3
修改runner 任务artifacts上传存储路径

1
2
3
4
5
6
vim /etc/gitlab/gitlab.rb

### For storing GitLab application uploads, eg. LFS objects, build artifacts
###! Docs: https://docs.gitlab.com/ce/development/shared_files.html
# gitlab_rails['shared_path'] = '/var/opt/gitlab/gitlab-rails/shared'
gitlab_rails['shared_path'] = '/data/gitlab_shared'

然后执行

1
然后执行sudo gitlab-ctl reconfigure

参考资料
分享到