常用 Groovy 片段与 Snippet Generator
April 13, 2024About 4 min
常用 Groovy 片段与 Snippet Generator
平时写 Pipeline 攒下来的一些 Groovy 片段,大多是用 Jenkins 的 model API 去操作 job / node / 文件。这些片段都要放在 script {} 块里跑。
全局变量 vs 局部变量
Groovy 里用 def(或具体类型)声明的是局部变量,不加 def 直接赋值的才是全局变量。一个常见坑:在被引用的其它库的方法里,不能重新声明全局变量。
def test() {
println(a)
a = "a2"
println(a)
}
// 全局变量
a = "a1" // 不加 def,全局
String b = "b1"
class GlobalVars {
static test1 = "test1"
static String test2 = "test2"
}
// 局部变量
def c = "c1" // 加了 def,局部
pipeline {
agent { node { label "build-node-1"; customWorkspace "E:\\workspace" } }
stages {
stage("test") {
steps {
script {
test()
println(a)
}
}
}
}
}
取消某个 job 的全部构建并禁用/启用 job
import jenkins.model.Jenkins
import org.jenkinsci.plugins.workflow.job.WorkflowJob
stage('Stop all builds and disable a job temporarily') {
steps {
script {
def jobName = 'game-ds-start'
def jenkins = Jenkins.instance
def job = jenkins.getItemByFullName(jobName, WorkflowJob.class)
if (job != null) {
// 取消所有正在运行的构建
job.builds.each { build ->
if (build.isBuilding()) {
build.doStop()
println("${jobName} Build #${build.number} has been cancelled.")
}
}
job.setDisabled(true) // 禁用 job
println("Pipeline job ${jobName} has been disabled.")
job.setDisabled(false) // 启用 job
println("Pipeline job ${jobName} has been enabled.")
} else {
println("Job named ${jobName} not found.")
}
}
}
}
把节点标记为 offline / online
import jenkins.model.*
def node_label = "build-node-x"
pipeline {
agent { node { label "build-node-1" } }
stages {
stage('test') {
steps {
script {
def node = Jenkins.instance.getNode(node_label)
if (node != null) {
node.toComputer().setTemporarilyOffline(true, null) // 下线
node.toComputer().setTemporarilyOffline(false, null) // 上线
}
}
}
}
}
}
遍历节点及 executor 状态
import hudson.model.Node
import jenkins.model.Jenkins
Jenkins jenkins = Jenkins.instance
for (Node node in jenkins.nodes) {
print node.nodeName
if (!node.getComputer().isOffline()) {
print node.getComputer().countBusy() // 繁忙的 executor 数
print node.getComputer().countIdle() // 空闲的 executor 数
print node.getComputer().countExecutors() // executor 总数
}
}
获取触发信息
// 触发当前 build 的用户名
user = currentBuild.getBuildCauses('hudson.model.Cause$UserIdCause')[0].userId.trim()
// 触发当前 build 的上游 job 名
upstream = currentBuild.getBuildCauses(
'org.jenkinsci.plugins.workflow.support.steps.build.BuildUpstreamCause'
)[0].upstreamProject.trim()
触发其它 job 并取回各种信息
def buildJob = build job: 'jobName', wait: true, propagate: false
print buildJob.getResult() // 构建结果
print buildJob.getAbsoluteUrl() // build 地址
print "${buildJob.getAbsoluteUrl()}console" // console 地址
print buildJob.getDurationString() // 运行时长
print buildJob.getBuildVariables()['envName'] // env 变量
print buildJob.rawBuild.getEnvironment()['paramName'] // 构建参数
print buildJob.rawBuild.getBuildStatusSummary().message // 稳定状态描述
文本替换 / 读 ini / 判断日志
// 文本文件内容替换
def inputText = readFile(file: "${filePath}")
inputText = inputText.replaceAll("${original}", "${replacement}")
writeFile(file: "${filePath}", text: inputText)
// 读 ini 文件(需 Pipeline Utility Steps 插件)
def prop = readProperties interpolate: true, file: "${filePath}"
def value = prop['key'].trim()
// 判断当前 build 日志是否含某关键词
currentBuild.rawBuild.log.contains('key words')
模糊查找 workspace 下的文件
def files = findFiles(glob: "path\\**\\*.bat") // 含子目录
// def files = findFiles(glob: "path\\*.bat") // 不含子目录
print files.size()
for (f in files) {
print "${WORKSPACE}\\${f.path}" // E:\test\path\1.bat
print f.path // path\1.bat
print new File(f.path).name // 1.bat
print new File(f.path).parentFile // path
}
读 CSV 指定列
// 取 csv 文件第 col 列(从 0 开始)的所有值
def readCSVFile(String path, int col) {
def values = []
def recordList = readCSV file: path
for (int i = 0; i < recordList.size(); i++) {
values.add(recordList[i].get(col))
}
return values
}
curl 带认证访问 Jenkins
需要登录时用用户名 + API token 认证:
curl -u <user>:<api_token> ${BUILD_URL}consoleText
powershell step 的变量坑
powershell step 里 Groovy 变量和 PowerShell 变量的展开方式不同,容易混:
// 单行
powershell "echo hi"
// 多行,双引号:${} 展开的是 Groovy 变量
a = 1
params.b = "b"
powershell """
echo a=${a} # a=1
echo b=${params.b}
"""
// 多行,单引号:$var 是 PowerShell 自己的变量,Groovy 不展开;
// 要传 Groovy 的值进去用 env
env.a = 1
powershell '''
$a = 2
echo a=$a # a=2(PowerShell 变量)
echo env.a=${env:a} # 取 Groovy 注入的 env
'''
Snippet Generator 常用 step 速查
Jenkins 自带的 Snippet Generator(Pipeline Syntax 页面)能为绝大多数 step 生成代码,不用背参数。下面挑实际常用的列一下,大部分要在 script {} 里用:
| Step | 用途 | 依赖插件 |
|---|---|---|
bat / sh / powershell | 执行批处理 / shell / PowerShell | / / PowerShell plugin |
build | 调起另一个 job | |
catchError / warnError | 捕获错误并设构建/stage 结果 | |
checkout | 从 Git / P4 / SVN 拉代码 | Git、P4 Plugin |
deleteDir / dir / ws | 删目录 / 临时切目录 / 分配工作空间 | |
findFiles | 在 workspace 搜文件 | |
emailext / mail | 发邮件(前者功能更全) | Email Extension Plugin |
ftpPublisher | 经 FTP 发送构建产物 | Publish Over FTP |
input | 等待交互式输入 | |
logParser | 解析构建日志 | Log Parser Plugin |
p4 / p4sync / p4unshelve / p4publish | P4 操作:运行命令、sync、unshelve、publish | P4 Plugin |
readFile / writeFile | 读 / 写文件 | |
readCSV / readJSON / readYaml / readProperties / readManifest | 读各类结构化文件 | |
writeCSV / writeJSON / writeYaml | 写各类结构化文件 | |
retry / timeout / waitUntil / sleep | 重试 / 超时 / 等待条件 / 休眠 | |
unstable | 把 stage 结果强制设为 unstable | |
untar / unzip / zip | 解压 tar / 解压 zip / 打 zip | |
withCredentials | 以加密方式绑定凭据到变量 | Credentials Binding Plugin |
withEnv | 临时设置环境变量 | |
timestamps | 日志带时间戳 |