第三章:Jenkins Pipeline 基础——安装、语法与SDK环境配置
讲到CI流水线,Jenkins几乎成了行业标配。我记得2015年刚接触它时,还是个Java老项目,配置全靠Web界面点来点去。后来Pipeline as Code普及了,才真正把CI从“玄学”变成了“工程学”。这一章,我就带你搭建Jenkins环境,讲清楚Pipeline的核心语法,再顺手把Android SDK配置好。不绕弯子,直接上干货。
本章知识主线:安装Jenkins → 掌握Pipeline语法(声明式为主) → 配置Android SDK环境。三步走完,你就能跑出第一条Android CI流水线。
3.1 Jenkins 安装与初始化
安装方式很多,我推荐用Docker,隔离性好,升级也方便。你想想看,要是直接装在宿主机器上,环境变量一团乱,哪天想换个版本还得去翻安装包,太折腾了。
3.1.1 Docker 安装(我的首选)
直接拉取官方LTS镜像,挂载一个本地卷用于持久化数据:
docker run \
--name jenkins-blue \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins_home:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:lts
个人习惯:我会额外挂载 /var/run/docker.sock,这样Jenkins容器内部就能直接调用宿主机的Docker引擎。为什么?因为在流水线里你经常需要动态创建容器来跑编译,没有这个映射,你就得在容器里再装一个Docker,多此一举。
3.1.2 首次启动配置
启动后,访问 http://localhost:8080。Jenkins会让你输入一个初始密码,在容器里执行:
docker exec jenkins-blue cat /var/jenkins_home/secrets/initialAdminPassword
复制出来,粘贴进去,然后选「安装推荐的插件」。这一步大概等5-10分钟。安装完成后创建一个管理员用户,嗯,这里要注意——密码别太简单,你后面会频繁用它登录。
我曾经踩过的坑:有的团队为了省事,把JENKINS_HOME映射到了宿主机的一个NFS目录,结果插件安装时文件锁冲突,导致界面卡死。所以建议映射到本地SSD盘,或者用命名卷(named volume),别用网络存储。
3.2 Pipeline 语法:声明式 vs 脚本式
Jenkins Pipeline有两种写法:声明式(Declarative)和脚本式(Scripted)。我个人的建议是:新项目一律用声明式。别问为什么,说白了就是——结构清晰、模板化、IDE友好,团队成员一看就懂。脚本式虽然灵活,但写起来容易失控,像一盘散沙。
3.2.1 声明式Pipeline的核心结构
最基本的骨架长这样:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
echo '拉取代码...'
checkout scm
}
}
stage('Build') {
steps {
echo '开始构建...'
sh './gradlew assembleDebug'
}
}
stage('Test') {
steps {
echo '运行单元测试...'
sh './gradlew testDebugUnitTest'
}
}
stage('Archive') {
steps {
echo '归档产物...'
archiveArtifacts artifacts: 'app/build/outputs/**/*.apk'
}
}
}
post {
always {
echo '无论成功失败都会执行'
cleanWs()
}
success {
echo '构建成功'
}
failure {
echo '构建失败,发个告警'
}
}
}
必知概念:
agent:指定运行环境。可以用any,也可以用agent { label 'android' }绑定特定节点。stages:流水线的阶段容器,一个阶段可以包含多个步骤。steps:具体执行的操作,比如运行Shell命令、调用Gradle、归档文件。post:构建结束后的回调,alwayssuccessfailureunstable分别对应不同状态。
3.2.2 声明式 vs 脚本式:一张表看清区别
| 维度 | 声明式(Declarative) | 脚本式(Scripted) |
|---|---|---|
| 语法风格 | 结构化、有固定schema | 自由Groovy代码 |
| 可读性 | 高,新人上手快 | 低,需要熟悉Groovy |
| 错误检查 | 语法校验严格,错误提前暴露 | 运行时才知道对错 |
| 代码复用 | 通过Shared Libraries | 支持函数、闭包 |
| 推荐场景 | 90%的CI场景 | 复杂的自定义逻辑 |
我的一贯做法:主体用声明式,遇到需要动态解析JSON或循环生成Stage时,在script { }块里夹一段脚本式代码。比如动态生成并行测试环境,这样既保持了结构清晰,又不失灵活性。
3.3 配置 Android SDK 环境
Pipeline写好之后,你得让Jenkins知道去哪找Android SDK。环境配置不到位,Gradle编译时会直接报错,连sdk.dir都找不到。你在项目中遇到过这种情况吗?多半是SDK路径没配对。
3.3.1 在Jenkins节点上安装SDK
我习惯在Jenkins主节点(或构建Agent节点)上手动安装Command Line Tools:
cd /opt
wget https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip
unzip commandlinetools-linux-*.zip -d android-sdk
cd android-sdk/cmdline-tools
mv tools latest
# 设置环境变量(写入 /etc/profile 或 /home/jenkins/.bashrc)
export ANDROID_HOME=/opt/android-sdk
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH
# 安装所需SDK组件
sdkmanager "platforms;android-34" "build-tools;34.0.0" "ndk;25.2.9519653"
避坑指南:我曾经在一台CI节点上直接apt install android-sdk,结果系统自带的SDK版本太老,Gradle不兼容。后来一律改用Command Line Tools手动装,版本自己控制。还有,别忘记安装platform-tools——如果你后续要做设备测试,adb必不可少。
3.3.2 在Pipeline中注入SDK路径
有两种方式:一种是写到全局环境变量(Manage Jenkins → Configure System),另一种是直接在Pipeline里指定。我推荐后者,因为同一个Jenkins实例可能跑多个安卓项目,有的用SDK 33,有的用34,灵活点好。
pipeline {
agent any
environment {
ANDROID_HOME = '/opt/android-sdk'
ANDROID_SDK_ROOT = '/opt/android-sdk'
PATH = "${env.ANDROID_HOME}/tools/bin:${env.ANDROID_HOME}/platform-tools:${env.PATH}"
}
stages {
stage('Check Environment') {
steps {
sh '''
echo "ANDROID_HOME: $ANDROID_HOME"
ls $ANDROID_HOME/platforms/
./gradlew --version
'''
}
}
stage('Build') {
steps {
sh './gradlew clean assembleDebug'
}
}
}
}
关键说明:很多新手会把ANDROID_HOME和ANDROID_SDK_ROOT只设一个,其实Gradle查找SDK时两个都会尝试。保持一致的话,能避免诡异的环境感知问题。另外,如果项目中用了local.properties,记得把它加到.gitignore里,不然本地路径会覆盖Jenkins上的路径。
3.3.3 验证环境是否就绪
跑一条简单的Pipeline验证一下,在构建日志里看到类似这样的输出就对了:
[Pipeline] echo
ANDROID_HOME: /opt/android-sdk
[Pipeline] sh
+ ls /opt/android-sdk/platforms/
android-34
[Pipeline] sh
+ ./gradlew --version
------------------------------------------------------------
Gradle 8.4
------------------------------------------------------------
如果sdk.dir找不到、或者Gradle版本不匹配,日志里会直接飘红。建议先手动跑一遍./gradlew assembleDebug确保本地能通过,再把脚本交到Jenkins手上。
本章知识结构一览
下面这张图概括了从Jenkins启动到Android SDK就绪的完整关系和流程:
高效小技巧:把ANDROID_HOME、GRADLE_USER_HOME这些变量放到全局工具配置(Manage Jenkins → Global Tool Configuration)里,然后在Pipeline中用tool name: 'android-sdk-34', type: 'com.cloudbees.jenkins.plugins.customtools.CustomTool'引用,可读性更佳。不过要注意,Custom Tools插件需要额外安装。