Android GitLab CI + Docker 工程实践

关键词:Android 、CI、Runner、GitLab、Docker、macOShtml

最新版 GitLab 已经集成 GitLab CI,能够经过 GitLab Runner 执行相关任务并将执行结果返回给 GitLab。linux

GitLab CI 与 Runner 的关系?android

GitLab 每个项目都自带一个 GitLab CI 系统,而 GitLab Runner 就是配合 GItLab CI 执行任务存在的。例如一个项目默认分支 push 了 commit,GitLab CI 就会收到通知,而后根据配置下发任务给指定的 Runner,Runner 执行完毕再将结果反馈给 CI。一个项目对应一个 CI,一个 CI 可对应多个 Runner。git

配置 GitLab Runner

GitLab Runner | GitLabdocker

安装 GitLab Runner(macOS)

  1. 下载二进制文件
sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
复制代码
  1. 赋予执行权限
sudo chmod +x /usr/local/bin/gitlab-runner
复制代码

注册 GitLab Runner(macOS)

Registering Runners | GitLabshell

在注册一个 Runner 以前,先要得到 token。缓存

两种类型 Runner 的区别?ruby

GitLab Runner 有专用 Runner 和共享 Runner 两种类型。共享 Runner 是 GitLab 提供的,无需自行安装注册就能使用,但可能须要排队等待,并且有使用限制。专用 Runner 是由用户自行安装注册的,能够项目专用,也能够多项目共享使用,能够看做私有 Runner。bash

在对应 Project -> Settings -> CI / CD -> Runners -> Specific Runners 里能够找到服务器

下面注册流程要用

  1. 执行一下命令
gitlab-runner register
复制代码
  1. 输入 GitLab 实例 URL
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
https://gitlab.com
复制代码
  1. 输入刚刚获取的 token
Please enter the gitlab-ci token for this runner
xxx
复制代码
  1. 输入 Runner 的描述
Please enter the gitlab-ci description for this runner
[hostame] android-runner
复制代码
  1. 输入 Runner tags

Tags 主要用于区别不一样任务,不一样环境等

Please enter the gitlab-ci tags for this runner (comma separated):
my-tag,another-tag
复制代码
  1. 输入 Runner 执行方式
Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell:
docker
复制代码

具体怎么选择,能够看看官网文档 Executors | GitLab
选择 Docker 的话,注意先安装 Get Started with Docker | Docker 环境。

  1. 若是上面选的 Docker 做为执行方式,还需指定 Docker image
Please enter the Docker image (eg. ruby:2.1):
alpine:latest
复制代码

这里能够先填个默认的,后面 GitLab CI 配置文件里还能够自定义。

安装并启动服务

cd ~
gitlab-runner install
gitlab-runner start
复制代码

Runner 已经安装完成,在系统重启以后将会运行。

运行以后就能在刚刚得到 token 的页面下方看到 Runner 实例了。

制做 Android Build Docker Image

这里只须要编写一个 Dockerfile 就定制所需的 image。

# FROM 指令用于指定后续构建 image 所使用的基础 image
# 这里指定 openjdk 做为基础 image,便再也不须要配置 JDK 环境了
FROM openjdk:8-jdk

# ARG 用于指定传递给构建运行时的变量
# sdk-tools 的版本,版本号在 https://developer.android.com/studio/index.html 页面查看
ARG SDK_TOOLS_VERSION=4333796
# build-tools 的版本
ARG BUILD_TOOLS_VERSION=27.0.3
# 指定 compileSdkVersion 的值
ARG COMPILE_SDK_VERSION=27

# WORDDIR 用于在容器内设置一个工做目录,以后的一些命令都会在这个目录下执行
WORKDIR /project 
# ENV 用于设置一个环境变量,以后的命令可使用
# 指定 Android SDK 的路径
ENV ANDROID_HOME /project/sdk

# RUN 用于在容器中执行命令
# 安装 Android SDK 和后续构建所需的工具
RUN mkdir sdk && \ wget https://dl.google.com/android/repository/sdk-tools-linux-${SDK_TOOLS_VERSION}.zip && \ unzip -qd sdk sdk-tools-linux-${SDK_TOOLS_VERSION}.zip && \ rm -f sdk-tools-linux-${SDK_TOOLS_VERSION}.zip && \ (yes | ./sdk/tools/bin/sdkmanager --no_https --update) && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "build-tools;${BUILD_TOOLS_VERSION}") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "platform-tools") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "platforms;android-${COMPILE_SDK_VERSION}") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "extras;google;m2repository") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "extras;android;m2repository") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "extras;m2repository;com;android;support;constraint;constraint-layout-solver;1.0.2") && \ (yes | ./sdk/tools/bin/sdkmanager --no_https "extras;m2repository;com;android;support;constraint;constraint-layout;1.0.2")     apt-get update -y && apt-get install -y bash git openssh-client && \
    rm -rf /var/lib/apt/lists/* && \
复制代码

最好新建一个空文件夹,将 Dockerfile 放到里面,而后进到该文件夹,执行 build。

docker build -t yourself.namespace/android-build:latest -f Dockerfile --build-arg http_proxy="http://docker.for.mac.localhost:port" --build-arg https_proxy="http://docker.for.mac.localhost:port" .
复制代码

--build-arg 用来指定代理服务器,若是代理服务在 Docker 宿主机上,可使用 docker.for.mac.localhost 从 Docker 环境访问宿主机。

因为没有将构建的 image push 到仓库,然后续使用到该 image 的时候,须要更新 Runner 的配置,不然会找不到 image。固然,也能够选择将 image push 到仓库。(The Docker executor | GitLab

GItLab Runner 支持 Docker Volume,这样能够把 Android 和 Gradle 的缓存目录做为 Volume,避免了每次运行都要从新下载。(Advanced configuration | GitLab

更新 Runner 配置,Runner 默认的配置文件路径是 ~/.gitlab-runner/config.toml

concurrent = 1
check_interval = 0

[[runners]]
  name = "android-runner"
  url = "https://gitlab.com/"
  token = "xxxxxxxxxxxxxxxxxxxxxxx"
  executor = "docker"
  [runners.docker]
    tls_verify = false
    image = "maven"
    privileged = false
    disable_cache = false
    volumes = ["/cache", "/root/.gradle", "/root/.android"]
    shm_size = 0
    pull_policy = "if-not-present"
  [runners.cache]
复制代码

[runners.docker] 下新增 pull_policy = "if-not-present" ,这样会优先在本地查找 image,本地没有找到再尝试 pull。

[runners.docker]volumes 里新增 /root/.gradle/root/.android 便可缓存。

修改以后重启 GItLab Runner,便可生效

cd ~
gitlab-runner restart
复制代码

配置 GitLab CI

Configuration of your jobs with .gitlab-ci.yml | GitLab

GItLab CI 的行为由配置文件 .gitlab-ci.yml 控制,该文件位于项目根目录下。

# 指定全局 job 使用的 Docker Image
image: yourself.namespace/android-build:latest

# 定义全局变量
# 指定网络代理
variables:
 HTTP_PROXY: "http://docker.for.mac.localhost:port"
 HTTPS_PROXY: "http://docker.for.mac.localhost:port"

# 预先执行脚本
# 写入 gradle 配置,具体配置根据项目配置来
before_script:
 - echo -e "systemProp.https.proxyHost=docker.for.mac.localhost\nsystemProp.https.proxyPort=port\nsystemProp.http.proxyHost=docker.for.mac.localhost\nsystemProp.http.proxyPort= port\nandroid.useDeprecatedNdk=true\norg.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" > gradle.properties # 定义任务执行阶段 # 在这里仅执行 build 任务 stages:
 - build

# build job
build:
 stage: build # 指定任务阶段
 tags: # 指定执行任务的 Runner
 - my-tag
 only: # 仅 git tag 更新时执行任务
 - tags
 script: # 任务执行脚本,执行构建脚本
 - ./gradlew --stacktrace assembleRelease
 artifacts: # 任务构建输出,指定须要保留的文件,以后能够在 GitLab Web 端下载
 paths:
 - app/build/outputs/
复制代码

配置文件编写完后,推送到 GitLab,从 GitLab Web 端建立一个 tag,CI 就会自动运行了。

测试效果

  1. 新建一个 Tag

  2. CI 就会自动运行了

  3. 等待任务执行完毕,就能够下载到构建输出文件了

相关文章
相关标签/搜索