Jenkins动态绑定节点设备ID:多物理机USB设备适配方案
一、需求背景
在多物理机节点的Jenkins环境中,不同节点(物理机)会绑定不同的USB设备(如Android手机、NG手表、iOS设备),需实现:
- 流水线根据测试需求(如"仅测Android""测Android+NG"),自动筛选绑定对应设备的节点;
- 无需手动输入设备ID,流水线自动读取当前节点预配置的设备ID,实现"节点-设备"的动态绑定。
二、核心思路
通过节点标签+节点环境变量的组合实现:
- 节点标签:标记节点支持的设备类型(如"Android"表示节点绑定了Android设备,"Android && Ng"表示节点同时绑定Android+NG设备);
- 节点环境变量 :在节点中预配置设备对应的ID(如
android_devices_id存Android设备ID,ng_devices_id存NG设备ID); - 流水线通过"标签筛选节点",并读取该节点的环境变量,自动获取当前节点的设备ID。
三、步骤1:节点标签规划
为不同设备类型的节点定义统一标签规则(标签大小写敏感):
| 节点绑定的设备 | 节点标签(Label) | 说明 |
|---|---|---|
| 仅Android手机 | Android |
流水线需测Android时,筛选该标签节点 |
| Android手机 + NG手表 | Android && Ng |
流水线需同时测Android+NG时,筛选该标签节点 |
| 仅iOS设备 | iOS |
流水线需测iOS时,筛选该标签节点 |
| 仅NG手表 | Ng |
流水线需仅测NG时,筛选该标签节点 |
四、步骤2:节点环境变量配置(绑定设备ID)
在每个节点中配置对应设备的ID(以你的截图配置为例),步骤如下:
-
进入Jenkins管理 → 「管理Jenkins」→ 「节点」→ 选择目标节点(如你的物理机节点)→ 点击「配置」;
-
配置节点标签 :在「标签」输入框中填写步骤1规划的标签(如绑定Android+NG的节点填写
master Android Ng); -
配置设备ID环境变量 :
-
勾选「节点属性」→ 「Environment variables」(环境变量);
-
点击「添加」,按设备类型填写键-值对 (键名需全局统一,方便流水线读取):
设备类型 环境变量键(Key) 环境变量值(Value) 说明 Android手机 android_devices_id你的Android设备ID(如 8cb34c35)节点实际连接的Android设备ID NG手表 ng_devices_id你的NG设备ID(如 2511C0037676)节点实际连接的NG设备ID iOS设备 ios_devices_id你的iOS设备ID 节点实际连接的iOS设备ID
-
-
点击「保存」,完成节点的设备ID与标签配置。
五、步骤3:流水线中动态筛选节点+获取设备ID
流水线通过标签筛选节点,并自动读取当前节点的环境变量,实现设备ID的动态获取。
核心代码逻辑
groovy
pipeline {
agent {
// 步骤1:根据测试需求,筛选对应标签的节点
// 示例:筛选同时绑定Android+NG的节点(标签为Android && Ng)
label 'Android && Ng'
// 若仅需Android节点,改为:label 'Android'
// 若仅需iOS节点,改为:label 'iOS'
}
parameters {
// 可选:参数化选择测试设备类型(自动匹配对应标签)
choice(
name: 'DEVICE_TYPE',
choices: ['Android', 'Android+NG', 'iOS'],
description: '选择测试设备类型'
)
}
stages {
stage('节点与设备ID校验') {
steps {
script {
// 步骤2:根据选择的设备类型,动态调整节点标签(可选,替代agent的固定label)
def targetLabel = ''
if (params.DEVICE_TYPE == 'Android') {
targetLabel = 'Android'
} else if (params.DEVICE_TYPE == 'Android+NG') {
targetLabel = 'Android && Ng'
} else if (params.DEVICE_TYPE == 'iOS') {
targetLabel = 'iOS'
}
// 重新绑定节点(若需参数化选择设备类型,需配合node块)
node(targetLabel) {
echo "当前选中节点:${env.NODE_NAME}"
echo "节点标签:${env.NODE_LABELS}"
// 步骤3:读取当前节点的设备ID(根据设备类型读取对应环境变量)
def deviceIds = [:]
if (params.DEVICE_TYPE.contains('Android')) {
deviceIds.android = env.android_devices_id
if (!deviceIds.android) {
error "当前节点未配置Android设备ID!"
}
}
if (params.DEVICE_TYPE.contains('NG')) {
deviceIds.ng = env.ng_devices_id
if (!deviceIds.ng) {
error "当前节点未配置NG设备ID!"
}
}
if (params.DEVICE_TYPE == 'iOS') {
deviceIds.ios = env.ios_devices_id
if (!deviceIds.ios) {
error "当前节点未配置iOS设备ID!"
}
}
// 输出设备ID(后续测试步骤可直接使用deviceIds中的值)
echo "当前节点绑定的设备ID:${deviceIds}"
}
}
}
}
stage('执行设备测试') {
steps {
script {
node(params.DEVICE_TYPE == 'Android' ? 'Android' : (params.DEVICE_TYPE == 'Android+NG' ? 'Android && Ng' : 'iOS')) {
// 实际测试步骤:直接使用节点的设备ID
def androidId = env.android_devices_id
def ngId = env.ng_devices_id
echo "开始测试Android设备(ID:${androidId})"
// 执行Android测试命令(如adb连接、自动化脚本)
// bat "adb connect ${androidId}"
if (params.DEVICE_TYPE == 'Android+NG') {
echo "开始测试NG设备(ID:${ngId})"
// 执行NG设备测试命令
}
}
}
}
}
}
}
六、场景示例
示例1:仅测试Android设备的流水线
groovy
pipeline {
agent { label 'Android' } // 仅选绑定Android的节点
stages {
stage('测试Android设备') {
steps {
script {
def androidId = env.android_devices_id
echo "当前节点Android设备ID:${androidId}"
// 执行Android测试(如App自动化)
bat "adb devices | findstr ${androidId}" // 验证设备连接
}
}
}
}
}
示例2:测试Android+NG设备的流水线
groovy
pipeline {
agent { label 'Android && Ng' } // 选同时绑定Android+NG的节点
stages {
stage('测试Android+NG设备') {
steps {
script {
def androidId = env.android_devices_id
def ngId = env.ng_devices_id
echo "Android设备ID:${androidId} | NG设备ID:${ngId}"
// 执行跨设备联动测试(如Android与NG手表数据同步)
}
}
}
}
}
七、注意事项
- 标签大小写敏感 :节点标签(如
Android)与流水线中label配置需完全一致(android≠Android); - 环境变量键名统一 :所有节点的同一类设备,需使用相同的环境变量键(如所有Android节点都用
android_devices_id); - 节点在线状态:确保筛选的标签对应的节点处于「在线」状态,否则流水线会卡住等待节点;
- 设备ID准确性 :环境变量中配置的设备ID需与节点实际连接的USB设备ID一致(可通过
adb devices(Android)、专用工具(NG/iOS)验证); - 标签逻辑运算 :
&&表示"且"(节点需同时具备多个标签);- 空格表示"或"(节点具备任一标签即可)。