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. 等待任務執行完畢,就能夠下載到構建輸出文件了

相關文章
相關標籤/搜索