Jenkins流水线语法
declarative pipelines vs scripted pipelines#
这其实是两种语法,declarative pipelines 有详细文档说明,文档末尾提到了 scripted pipelines,但是没有详细说明。
在动态生成 pipeline 时,代码需要返回 scripted pipelines。
def agents = ['master', 'agent1', 'agent2']
def generateStage(nodeLabel) {
return {
stage("Runs on ${nodeLabel}") {
node(nodeLabel) {
echo "Running on ${nodeLabel}"
}
}
}
}
def parallelStagesMap = agents.collectEntries {
["${it}" : generateStage(it)]
}
pipeline {
agent none
stages {
stage('non-parallel stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
上面代码中根据 agents 数组动态生成任务并执行,下面 pipeline 代码块中的内容是 declarative pipelines 语法,而函数 generateStage 中生成的任务需要使用 scripted pipelines 语法,否则会报错。
不得不说这个设计很容易把人搞晕。
在指定的节点上执行任务#
在 declarative pipelines 语法中,通过使用 agent 来指定节点。
在 scripted pipelines 语法中,使用 node 来指定节点(见上面动态生成的代码示例)。
普通的 groovy 脚本不会在节点上执行!#
stage('Test') {
agent { label 'db1' }
steps {
sh 'uname -a'
println "uname -a".execute().text
}
}
如果执行上面的代码,会发现 sh 中的 shell 脚本是在节点 db1 上运行的,但是第二句 println “uname -a”.execute().text 是在 master 节点上运行的!
非常坑的设定,网上也有人提出了这个问题:https://stackoverflow.com/questions/43748826/jenkins-declarative-pipeline-run-groovy-script-on-slave-agent
在 pipeline step 语法中有 withGroovy 的说明,使用时需要安装 plugin,但是该 plugin 文档上说其当前版本不支持 pipeline 语法。
最后在 Jenkins Script Console 的说明文档中找到一个可以实现的例子:
import hudson.util.RemotingDiagnostics
import jenkins.model.Jenkins
String agentName = 'your agent name'
//groovy script you want executed on an agent
groovy_script = '''
println System.getenv("PATH")
println "uname -a".execute().text
'''.trim()
String result
Jenkins.instance.slaves.find { agent ->
agent.name == agentName
}.with { agent ->
result = RemotingDiagnostics.executeGroovy(groovy_script, agent.channel)
}
println result
代码虽然复杂,好歹能实现功能,封装一下应该使用就更简单了。