搭建CI环境:配置Jenkins/GitHub Actions Runner、Android SDK与Build Tools安装、环境变量设置
CI环境搭不好,后面所有自动化测试都是空中楼阁。我自己带团队的时候,遇到最多的新手问题就是:照着文档配完了,但一跑就挂,而且不知道挂在哪。说白了,CI环境搭建不是「装个软件」那么简单,它是一整套工具的协同工作。今天咱们就把它拆开揉碎了讲。
1. 整体架构:CI环境由哪些部分组成?
先看一张图,你心里就有谱了:
嗯,流程其实不复杂:从机器到Runner,再到JDK、SDK、Build Tools,最后环境变量收尾。每一步都环环相扣,有一个断链,编译就跑不起来。
2. 机器 / 镜像准备
我自己习惯用 Linux 作为 Runner 系统。为什么?因为 Android SDK 的工具链全部是 Linux first,Windows 上偶尔会有路径编码的问题,macOS 倒是可以但成本高。如果用的是 GitHub Actions,官方提供的 ubuntu-latest 镜像已经预装了大部分工具,但你得注意版本——它默认的 SDK 可能不是你项目需要的版本。
android-sdk:latest 镜像,我项目里直接拉下来用,省去重复安装的麻烦。
3. Runner / Agent 配置
3.1 GitHub Actions Runner
GitHub Actions 有两种模式:
- GitHub 托管 Runner:配置简单,直接用
runs-on: ubuntu-latest。但是并发数有限,而且你不一定拿得到 root 权限。 - 自托管 Runner:你在自己的机器上跑
./config.sh --url https://github.com/your/repo -- xxxx。我个人更推荐这种,因为你可以控制硬件、缓存加速、还能跑需要 root 的测试。
我曾经踩过一个坑:自托管 Runner 默认用 ubuntu 用户,没有 sudo 权限,导致安装 SDK 时 sdkmanager 写不进去系统目录。解决办法是给 Runner 用户配置 sudo 免密,或者把 SDK 装到用户目录下。
3.2 Jenkins Agent
Jenkins 的话,我用 pipeline 语法配置 agent:
pipeline {
agent {
label 'linux-android'
}
stages {
stage('Setup') {
steps {
// 这里做环境准备
}
}
}
}
Jenkins 的 Agent 可以是固定节点,也可以是动态 Docker 容器。我个人偏向用 Docker,因为不同分支或不同项目可能需要不同的 SDK 版本,容器切换比清理机器快多了。
4. JDK 安装
Android 编译依赖 JDK,而且版本要对。Android Gradle Plugin 8.x 要求 JDK 17,旧版项目可能还在用 JDK 11。你想想看,如果 JDK 版本不对,编译一开始就报 Unsupported class file major version,那只能干瞪眼。
我的做法:在 Runner 上装多个 JDK 版本,然后通过 JAVA_HOME 环境变量切换。比如安装 openjdk-17 和 openjdk-11,然后在 Jenkins pipeline 里:
withEnv(['JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64']) {
sh './gradlew assembleDebug'
}
别问我为什么强调这个——我试过在同一个 Runner 上同时跑两个项目,一个用 JDK 11 一个用 JDK 17,结果 Gradle daemon 冲突,编译全挂了。从此我每个 agent 只跑一个项目,或者用容器隔离。
5. Android SDK 与 Build Tools 安装
这是整个环境搭建里最核心的部分,也是最容易出错的地方。
5.1 安装命令行工具
Google 现在推荐的安装方式是先下载 commandlinetools。步骤如下:
- 从官方下载
commandlinetools-linux-xxx_latest.zip。 - 解压到
/opt/android-sdk(或$HOME/Android/Sdk)。 - 运行
sdkmanager --install "platforms;android-33" "build-tools;33.0.2"。
你看,核心命令就这一条。但是——这里有个陷阱:sdkmanager 默认会检查 Java 环境,而且它自己也是一个 Java 程序。你装了 JDK 但 JAVA_HOME 没设对,它就会直接退出了,连个像样的提示都没有。我曾经在 Jenkins 日志里翻了十分钟才找到原因。
JAVA_HOME 指向 JDK 目录,而不是 JRE。可以用 sdkmanager --list 测试一下能不能正常输出。
5.2 我需要装哪些包?
一个典型的 Android CI 环境需要安装以下内容:
| 组件 | 作用 | 安装命令示例 |
|---|---|---|
| platforms;android-34 | 编译目标平台 API | sdkmanager "platforms;android-34" |
| build-tools;34.0.0 | 构建工具链 (aapt, dx, zipalign) | sdkmanager "build-tools;34.0.0" |
| ndk;26.1.10909125 | NDK (如果你有 C/C++ 代码) | sdkmanager "ndk;26.1.10909125" |
| cmake;3.22.1 | CMake (NDK 构建用) | sdkmanager "cmake;3.22.1" |
嗯,别懒省事把所有平台都装了,那样磁盘空间会爆炸。我一般只装项目 compileSdk 对应版本,以及兼容的 build-tools。项目里 build.gradle 写什么,我就装什么。
6. 环境变量设置
配置环境变量是最后一个环节,也是「功亏一篑」的高发区。
6.1 必须设置的环境变量
无论你用 Jenkins 还是 GitHub Actions,至少需要设置下面三个:
ANDROID_HOME—— 指向 SDK 根目录,比如/opt/android-sdk。ANDROID_SDK_ROOT—— 和上一个功能相同,但 Gradle 优先使用这个。我建议两个都设,免得兼容性问题。PATH—— 把$ANDROID_HOME/tools/bin和$ANDROID_HOME/platform-tools加进去。
我在 Jenkins pipeline 里是这样写的:
withEnv([
'ANDROID_HOME=/opt/android-sdk',
'ANDROID_SDK_ROOT=/opt/android-sdk',
'PATH+SDK=/opt/android-sdk/tools/bin:/opt/android-sdk/platform-tools'
]) {
sh 'sdkmanager --list'
}
6.2 一个经典的「环境变量没生效」案例
我曾经遇到这样一个问题:本地开发编译正常,CI 上一跑就报 Could not find tools.jar。查了半天,发现是 Jenkins 服务以 systemd 方式启动,而 systemd 的 EnvironmentFile 里没有加载 JDK 路径。
解决方案:在 /etc/systemd/system/jenkins.service 里加入 Environment="JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64",然后重启服务。自托管 Runner 同理,要在启动脚本或者 .bashrc 里显式设置。
withEnv 或 env 块显式设置。
7. 快速验证步骤
所有配置完事后,跑一个最小化检查:
java -version—— 检查 JDK 版本。sdkmanager --list—— 检查 SDK 可访问。gradle wrapper --version—— 检查 Gradle。- 执行
./gradlew assembleDebug—— 跑一次完整编译。
嗯,如果前两步正常,第三步出问题就去查 Gradle 版本兼容性。如果前三步都正常但第四步挂了,那大概率是项目自己的依赖问题,跟环境无关了。
8. 工具版本对照速查
为了方便你快速对应,我整理了一个 Android CI 环境常用版本搭配表:
| Android Gradle Plugin | Gradle 版本 | JDK 版本 | Build Tools 推荐 |
|---|---|---|---|
| 8.2 | 8.5+ | 17 | 34.0.0 |
| 7.4 | 7.5+ | 11 或 17 | 33.0.2 |
| 4.2 | 6.7+ | 8 或 11 | 30.0.3 |
这张表你记着就行,项目升级 AGP 时记得同步升级 Gradle wrapper。我见过有人只升级了 AGP,Gradle 还是老版本,结果 DSL 语法不兼容,编译直接报 Unsupported method。
9. 一句话总结
搭建 Android CI 环境,说白了就是:选好机器 → 配好 Runner → 装对 JDK → 下对 SDK → 设好变量。每一步都有坑,但只要你按流程来,验证慢慢过,就不会有翻车的地方。下一次遇到 CI 编译失败,先回到这张流程图上,看哪个环节出了问题。