问题描述
在使用Jenkins(版本2.204.2)的声明式流水线时,用户想要在不同的机器上并行运行以映射方式生成的阶段。虽然过去可以通过在script
块中混合使用来实现,但从文档和其他StackOverflow问题中,用户无法弄清楚为什么这种格式不起作用。用户已经尽可能地简化了问题,尝试在流水线之外静态创建映射,以弄清楚所需的语法。
问题代码示例:
#!/usr/bin/env groovy
def map = [:]
map['Passed Stage'] = {
stage("Passed Map Inner Stage"){
agent{ label "nodeLabel" }
steps{
echo "PASSED MAP STEP"
}
}
}
pipeline {
agent { label "nodeLabel" }
stages {
stage("Non map stage"){
agent{ label "nodeLabel" }
steps{
echo "NON MAP STEP"
}
}
stage("Direct Map Outer Parallel Stage"){
parallel{
direct:
stage("Direct Map Inner Stage"){
agent{ label "nodeLabel" }
steps{
echo "DIRECT MAP STEP"
}
}
}
}
stage("Passed Map Outer Parallel Stage"){
parallel{ map }
}
}
}
前两个阶段方法可以工作,但如果注释掉映射的那一部分,”Passed Map Outer Parallel Stage” 阶段总是失败,报错如下:
Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 33: Expected a stage @ line 33, column 23.
parallel{ map }
^
WorkflowScript: 33: No stages specified @ line 33, column 13.
parallel{ map }
^
WorkflowScript: 33: No stages specified @ line 33, column 13.
parallel{ map }
^
3 errors
阶段的格式从我整天的阅读中看起来没有问题,而且将相同的阶段直接传递给 parallel
在映射之外也是可以正常工作的。用户不明白自己漏掉了什么,为什么 parallel
不接受他的映射?声明式的 parallel
只接受静态传递的阶段吗?是Jenkins版本过低吗?
解决方案
使用脚本块解决声明式的并行问题
在声明式流水线中,parallel
的用法和在 script
块中的脚本并行是不同的。你的问题在于在映射方式下使用了parallel
,但是声明式流水线的parallel
期望在块中调用stage
函数。
下面是如何解决这个问题的方案:
pipeline {
agent { label "nodeLabel" }
stages {
stage("Non map stage"){
agent{ label "nodeLabel" }
steps{
echo "NON MAP STEP"
}
}
stage("Direct Map Outer Parallel Stage"){
parallel{
direct:
stage("Direct Map Inner Stage"){
agent{ label "nodeLabel" }
steps{
echo "DIRECT MAP STEP"
}
}
}
}
stage("Passed Map Outer Parallel Stage"){
steps {
script {
parallel map
}
}
}
}
}
在上述解决方案中,我们对 “Passed Map Outer Parallel Stage” 阶段使用了 steps
块,并在其中使用 script
块来调用 parallel
函数并传递映射。
此外,确保你的Jenkins版本支持使用这种方式。
脚本管理启动顺序
如果你想要更精细地控制并行启动的顺序,你可以使用脚本或者一些工具来实现。下面是一个简单的bash脚本示例,用于在容器A启动后启动容器B:
#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b
在这个示例中,我们使用docker run
命令启动容器A,然后使用一个循环来等待容器A完全启动。一旦容器A就绪,我们再使用docker run
命令启动容器B。
总结
在使用Jenkins的声明式流水线中,处理并行阶段的方式与在script
块中处理的方式不同。对于并行阶段,你需要在steps
块中使用script
块,并在其中调用parallel
函数并传递映射。另外,你还可以使用脚本或工具来精细控制容器的启动顺序。在进行操作时,务必注意你的Jenkins版本是否支持所使用的功能。