基于Docker+Jenkins的Android项目CI/CD流程搭建

简介

Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测试和部署软件。

Jenkins通过Docker部署运行时,Jenkins的容器环境不包含构建Android应用所需的工具(如Android SDK等)。但Jenkins支持在流水线的单个 Stage或整个流水线中使用Docker镜像作为执行环境,方便用户管理构建和测试环境。

本文档介绍在Docker运行Jenkins的环境下,用Jenkins构建Android项目的两种方式——Freestyle project构建任务和Pipeline构建任务。

操作环境

操作系统:CentOS Linux release 7.7.1908
Docker版本:19.03.5
Jenkins Docker镜像:jenkins/jenkins:lts
Jenkins版本:2.263.2

一、Jenkins自由风格项目(Freestyle project)

前置准备工作

由于Jenkins运行在Docker容器环境中,Android的编译环境也就是这个容器,所以需要这个环境有编译Android项目的工具——Android SDK和Gradle。

设置Android SDK

首先需要进入到Jenkins的容器环境中,操作命令:

docker exec -it fe8e26096760 /bin/bash

然后通过命令行安装Android SDK。以下为一个方便设置的脚本:

#!/bin/bash
mkdir /android-sdk && cd /android-sdk
wget https://dl.google.com/android/repository/commandlinetools-linux-6858069_latest.zip
unzip -q commandlinetools-linux-6858069_latest.zip
mkdir latest && mv cmdline-tools/* latest && mv latest cmdline-tools/
yes | cmdline-tools/latest/bin/sdkmanager --licenses
#安装必要的构建工具
yes | cmdline-tools/latest/bin/sdkmanager "build-tools;29.0.3" "platforms;android-29"

Android Gradle插件是通过环境变量来确定Android SDK的位置的,所以需要配置一个名为ANDROID_HOME或ANDROID_SDK_ROOT的环境变量,其值为Android SDK所在的路径。设置方式:
“Manage Jenkins” -> “Configure System” -> “Global properties” -> 勾选上“Environment variables” -> 点击“Add”,输入环境变量名称和值,如图1所示:
在这里插入图片描述
图1

输入完成后,滚动至页面底部,依次点击“Apply” -> “Save”来保存。

设置Gradle(可选)

“Manage Jenkins” -> “Global Tool Configuration” -> Gradle域点击“Gradle installations” -> ”Add Gradle“。输入一个名字,并勾选上“Install automatically”,在下方选择和代码工程中一致的Gradle版本。最后依次点击屏幕左下角“Apply” -> “Save”保存设置。设置结果如图2所示:
图2
图2

创建Freestyle project任务

1、 在Jenkins首页左上角点击“New Item”新建一个任务,进入图4页面。
在这里插入图片描述
图3
2、在该页面中,输入任务名称,类型选择Freestyle project,然后点击左下角“OK”进入配置页面。
在这里插入图片描述
图4
3、点击顶部“Source Code Management”选项卡,滚动到Source Code Management配置部分。类型选择“Git”;然后在Repositories域中,添加代码仓库地址和访问代码仓库的用户凭证;在Branches to build域中,设置用来编译的代码分支,如图5所示。
在这里插入图片描述
图5
4、(可选)点击顶部“Build Trigger”选项卡,滚动到Build Trigger配置部分,设置合适的触发器,比如配置远程http接口调用来触发。如不配置这部分,也可以通过手动来触发。
在这里插入图片描述
图6
5、点击顶部“Build”选项卡,滚动到Build配置部分。点击“Add build step”,在下拉列表中选择“Invoke Gradle script”,如图7所示。
在这里插入图片描述
图7
调用Gradle脚本的方式有两种,如图8所示;

  • Invoke Gradle;在“Gradle Version”点击展开下拉列表,选择要使用的Gradle版本。这里展示的选项就是我们前面在Jenkins系统管理页面“Global Tool Configuration”中设置的全局Gradle工具版本。
  • Use Gradle Wrapper;这种方式是使用源码工程中的Gradle配置,和在Android Studio中编译项目一样。
    不管选择那种方式,都需要在下方的Tasks域中填写需要执行的Gradle构建任务和参数,例如:
clean assembleRelease --no-daemon

在这里插入图片描述
图8
为了使Jenkins的构建环境和开发编译时的环境尽量保持一致,避免Jenkins出现一些不必要的环境问题,推荐这一步选择Use Gradle Wrapper。
6、在最下面的“Post-build Actions”配置部分,点击“Add post-build action”,在下拉列表中选择“Archive the artifacts”,将指定的编译输出文件归档。便于以后我们在Jenkins任务的构建历史中查看某次构建的输出产物,如图9所示。
在这里插入图片描述
图9
这里我们在“Files to archive”域中填写:app/build/outputs/apk/release/*.apk,将编译出的所有APK文件进行归档,如图10所示。
在这里插入图片描述
图10
7、最后,依次点击页面左下角的“Apply” -> “Save”保存设置,一个Freestyle project类型的Jenkins任务就创建好了。

二、Jenkins流水线任务(Pipeline)

前置条件

需要先通过 “Manage Jenkins” -> “Manage Plugins” 页面安装 Docker、Docker Pipeline两个插件。

创建Pipeline任务

1、在Jenkins首页左上角点击“New Item”新建一个任务,进入图11所示页面。
2、在该页面中,输入任务名称,类型选择Pipeline,然后点击左下角“OK”进入配置页面。
在这里插入图片描述
图11
3、(可选)点击顶部“Build Trigger”选项卡,滚动到Build Trigger配置部分,设置合适的触发器,比如配置远程http接口调用来触发。如不配置这部分,也可以通过手动来触发。
在这里插入图片描述
图12
4、点击顶部“Pipeline”选项卡,滚动到Pipeline配置部分。在Definition域,有图13所示的两个选项:
在这里插入图片描述
图13
1)Pipeline script:直接在下方的Script区域手动编写流水线脚本,如图14所示:
在这里插入图片描述
图14
2)Pipeline script from SCM:这是一种推荐的最佳实践,这种方式通过在源码根目录创建一个Jenkinsfile文件来维护流水线脚本内容,Jenkins 从源代码管理系统中检出 Jenkinsfile 文件作为流水线项目构建过程的一部分。
这里我们选择Pipeline script from SCM。在SCM域选择“Git”,然后Repositories域中填上对应的代码仓库地址和访问仓库的用户凭证。在“Branches to build”域中设置用于构建的代码分支,如图15所示。
在这里插入图片描述
图15
5、最后,依次点击页面左下角的“Apply” -> “Save”保存设置,一个Jenkins流水线任务就创建好了。

编写Jenkinsfile文件

接下来我们需要在源码的根目录创建一个Jenkinsfile文件,来定义流水线的具体配置和步骤。这里首先要配置一个能编译Android项目的docker镜像环境。
Jenkinsfile示例:

pipeline{
    agent {
        docker {
            // image 'allbears/jenkins-android:1.0.1'
            image 'cmii/android-build:1.0.0'
            // 共享Gradle下载缓存,使构建任务执行更快
            args '-v $HOME/.gradle:/root/.gradle'
        }
    }
    stages {
        stage('Build'){
            steps {
                sh './gradlew clean assembleDebug --no-daemon'
            }
        }
        stage('Archive') {
            steps {
                archiveArtifacts artifacts: 'app/build/outputs/**/*.apk', fingerprint: true
            }
        }
    }
}

配置完成后,将Jenkinsfile提交到Gitlab代码仓库。

流水线Docker相关补充

关于Docker环境

由于流水线任务是在Jenkins的容器环境中执行的,如果流水线中再设置docker镜像作为Android构建环境,那么就需要运行Jenkins的容器环境有docker命令,才能启动新的容器进行编译。可以使用docker exec -it CONTAINER_ID /bin/bash的方式,进入Jenkins的容器环境进行查看。
经测试,包含Jenkins 2.263.2版本的jenkins/jenkins:lts镜像没有安装Docker ;带有Jenkins 2.277.2版本的jenkinsci/blueocean镜像预装了Docker。如果实际部署的Jenkins镜像没有安装Docker,可以参考官方文档 Install Docker Engine 进行安装。

关于Docker镜像

在流水线的编译Android项目阶段,需要一个包含Android SDK等工具的编译环境。我们可以选择一些公开的Docker镜像,比如:allbears/jenkins-android;也可以根据需要自己编写Dockerfile来生成Docker镜像,核心就是要包含java环境和Android SDK。下面是一个Dockerfile示例,基于Ubuntu基础镜像制作。Dockerfile示例:

FROM ubuntu:18.04

MAINTAINER shenyong <shenyong@cmii.chinamobile.com>

# (可选)更换一个国内的 Ubuntu 软件源,可以加速安装
RUN mv /etc/apt/sources.list /etc/apt/sources.list.bak
COPY sources.list /etc/apt/sources.list

# 安装 Java 环境
RUN apt-get update
RUN apt-get install openjdk-8-jdk -y --fix-missing
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
ENV PATH $JAVA_HOME/bin:$PATH

# 安装 Android SDK
RUN mkdir /android-sdk
WORKDIR /android-sdk
RUN apt-get install unzip -y --fix-missing
COPY commandlinetools-linux-6858069_latest.zip /android-sdk
RUN unzip -q commandlinetools-linux-6858069_latest.zip && rm *.zip
RUN mkdir latest && mv cmdline-tools/* latest && mv latest cmdline-tools/
ENV ANDROID_HOME /android-sdk
ENV CMDLINE_TOOLS_PATH $ANDROID_HOME/cmdline-tools/latest/bin
ENV PATH $CMDLINE_TOOLS_PATH:$ANDROID_HOME/tools/bin:$ANDROID_HOME/platform-tools:$PATH
RUN yes | $CMDLINE_TOOLS_PATH/sdkmanager --licenses
RUN yes | $CMDLINE_TOOLS_PATH/sdkmanager "build-tools;29.0.3" "platforms;android-29"

# 安装其他需要的命令
RUN apt-get install curl -y --fix-missing

RUN mkdir -p /opt/workspace
WORKDIR /opt/workspace

CMD /bin/echo "--docker image for android build--"

内测分发示例(可选)

在完成编译后,我们可以把编译的APK上传到指定的网络位置,方便团队成员和测试人员将应用安装到手机上。以使用国内的蒲公英内测分发平台为例,在平台注册用户后,使用一条curl命令即可通过蒲公英平台API将应用进行内测发布。

  • 在Freestyle project任务中,可以参考:
  • 在Pipeline任务中,可以使用curl命令上传。更进一步,因为蒲公英API会返回下载APK的二维码图片链接,我们可以通过设置Jenkins构建描述(需要先在Jenkins中安装 description setter 插件),将这个二维码图片直接显示在Jenkins页面上。Pipeline脚本示例:
pipeline{
    agent {
        // ...
    }
    stages {
        // ...
        stage('Publish') {
            steps {
                sh 'chmod +x jenkins-ci/upload_to_pgy.sh'
                sh 'jenkins-ci/upload_to_pgy.sh'
                script {
                    currentBuild.description = readFile("desc_html")
                }
            }
        }
    }
}

jenkins-ci/upload_to_pgy.sh:

#!/bin/bash

PGY_USER_KEY="5cde6d48d7xxxxxxxx5eac862632dea0"
PGY_API_KEY="d655b8d9a1bxxxxxxxxaafc882940c96"

cp app/build/outputs/apk/release/app-release.apk .
curl -F "file=@app-release.apk" \
 -F "uKey=$PGY_USER_KEY" \
 -F "_api_key=$PGY_API_KEY" \
 https://www.pgyer.com/apiv1/app/upload > pgy.json

name=$(grep -Eo "\"appName\":\"\w+\"" pgy.json | sed 's/"//g' | cut -d : -f 2)
version=$(grep -Eo "\"appVersion\":\"([[:digit:]]|\.)+\"" pgy.json | sed 's/"//g' | cut -d : -f 2)
shorturl=$(grep -Eo "\"appShortcutUrl\":\"\w+\"" pgy.json | sed 's/"//g' | cut -d : -f 2)
qrcodeurl=$(sed 's/\\\//\//g' pgy.json | sed 's/.*\(https.*\)"}}/\1/')

echo "<img src=\"$qrcodeurl\" width=\"100\" height=\"100\"><br><a href=\"https://www.pgyer.com/$shorturl\">${name} v${version}</a>" > desc_html

图16、图17展示了Pipeline任务构建成功并分发到蒲公英平台的页面。
在这里插入图片描述
图16
在这里插入图片描述
图17

运行Jenkins构建任务

通过设置的构建触发条件或在Jenkins任务页面点击“Build Now”来执行任务,顺利执行完成以后,结果如图18所示:
在这里插入图片描述
图18

Jenkins构建结果示例

图19展示了一个流水线任务页面的展示内容。
在这里插入图片描述
图19
图20展示了在一次构建历史详情页面显示的归档APK文件,和我们引入的内测分发平台APK下载二维码和跳转链接,方便使用手机扫码下载。
在这里插入图片描述
图20

问题汇总

问题汇总
1、KotlinNullPointerException问题
如果没有正确设置 Android SDK 的环境变量,执行Jenkins任务将会出现 KotlinNullPointerException错误:

A problem occurred configuring project ':app'.
> kotlin.KotlinNullPointerException (no error message)

解决方法:参考设置Android SDK部分,检查设置。

2、Invalid agent type “docker” specified问题
如果没有先安装好插件,就运行使用了Docker的流水线任务,将会出现 Invalid agent type "docker" specified错误:

WorkflowScript: 3: Invalid agent type "docker" specified. Must be one of [any, label, none] @ line 3, column 9.
           docker {
           ^

解决方法:检查Docker、Docker Pipeline插件是否成功安装,可以通过safeRestart重启Jenkins服务。

3、docker: not found 问题:
如果Jenkins容器环境没有安装Docker,执行Jenkins构建任务将会出现 docker: not found错误:

[Pipeline] sh
+ docker inspect -f . allbears/jenkins-android:1.0.1
/var/jenkins_home/workspace/Android-Pipline_Test@tmp/durable-a7b81bd2/script.sh: 1: /var/jenkins_home/workspace/Android-Pipline_Test@tmp/durable-a7b81bd2/script.sh: docker: not found

解决方法:在Jenkins运行容器中安装Docker、或使用预装了Docker的Jenkins镜像版本。

参考文档

1.Jenkins 用户手册
2.Pipeline Steps Reference
3.Jenkins 中文社区 - 使用 Jenkins 构建 Android 应用
4.http://www.dockerinfo.net/document
5.Docker+Jenkins+Gradle+GitLab在Linux服务端自动化构建Android包

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值