我需要在声明性管道中启动一组动态测试。 为了更好的可视化目的,我想为每个测试创建一个阶段。 有办法吗?
我所知道的创建舞台的唯一方法是:
stage('foo') {
...
}
我已经看过这个示例,但我它不使用声明性语法。
使用比声明性语法更灵活的脚本化语法,尽管声明性语法有更多记录和建议。
例如,可以在循环中创建阶段:
def tests = params.Tests.split(',')
for (int i = 0; i < tests.length; i++) {
stage("Test ${tests[i]}") {
sh '....'
}
}
正如 JamesD 建议的那样,您可以动态创建阶段(但它们将是连续的),如下所示:
def list
pipeline {
agent none
options {buildDiscarder(logRotator(daysToKeepStr: '7', numToKeepStr: '1'))}
stages {
stage('Create List') {
agent {node 'nodename'}
steps {
script {
// you may create your list here, lets say reading from a file after checkout
list = ["Test-1", "Test-2", "Test-3", "Test-4", "Test-5"]
}
}
post {
cleanup {
cleanWs()
}
}
}
stage('Dynamic Stages') {
agent {node 'nodename'}
steps {
script {
for(int i=0; i < list.size(); i++) {
stage(list[i]){
echo "Element: $i"
}
}
}
}
post {
cleanup {
cleanWs()
}
}
}
}
}
这将导致: 动态顺序阶段
如果您不想使用
for
循环,并生成要并行执行的管道,那么这里有一个答案。
def jobs = ["JobA", "JobB", "JobC"]
def parallelStagesMap = jobs.collectEntries {
["${it}" : generateStage(it)]
}
def generateStage(job) {
return {
stage("stage: ${job}") {
echo "This is ${job}."
}
}
}
pipeline {
agent none
stages {
stage('non-parallel stage') {
steps {
echo 'This stage will be executed first.'
}
}
stage('parallel stage') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
Note
所有生成的阶段都将在 1 个节点中执行。
如果您愿意将生成的阶段执行到不同的节点中。
def agents = ['master', 'agent1', 'agent2']
// enter valid agent name in array.
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
}
}
}
}
}
您当然可以添加 1 个以上的参数,并且可以使用
collectEntries
来添加 2 个参数。
请记住功能中的
return
generateStage
是必须的。
声明式管道:
一个简单的静态示例:
stage('Dynamic') {
steps {
script {
stage('NewOne') {
echo('new one echo')
}
}
}
}
动态现实生活示例:
// in a declarative pipeline
stage('Trigger Building') {
when {
environment(name: 'DO_BUILD_PACKAGES', value: 'true')
}
steps {
executeModuleScripts('build') // local method, see at the end of this script
}
}
// at the end of the file or in a shared library
void executeModuleScripts(String operation) {
def allModules = ['module1', 'module2', 'module3', 'module4', 'module11']
allModules.each { module ->
String action = "${operation}:${module}"
echo("---- ${action.toUpperCase()} ----")
String command = "npm run ${action} -ddd"
// here is the trick
script {
stage(module) {
bat(command)
}
}
}
}
您可能想看一下这个示例 - 您可以让一个函数返回一个闭包,该闭包应该能够在其中有一个阶段。
此代码显示了概念,但其中没有阶段。
def transformDeployBuildStep(OS) {
return {
node ('master') {
wrap([$class: 'TimestamperBuildWrapper']) {
...
} } // ts / node
} // closure
} // transformDeployBuildStep
stage("Yum Deploy") {
stepsForParallel = [:]
for (int i = 0; i < TargetOSs.size(); i++) {
def s = TargetOSs.get(i)
def stepName = "CentOS ${s} Deployment"
stepsForParallel[stepName] = transformDeployBuildStep(s)
}
stepsForParallel['failFast'] = false
parallel stepsForParallel
} // stage
只是对 @np2807 和 @Anton Yurchenko 已经介绍的内容的补充:您可以动态创建阶段并通过简单地延迟阶段创建列表(但保留其声明)来并行运行,例如像这样:
def parallelStagesMap
def generateStage(job) {
return {
stage("stage: ${job}") {
echo "This is ${job}."
}
}
}
pipeline {
agent { label 'master' }
stages {
stage('Create List of Stages to run in Parallel') {
steps {
script {
def list = ["Test-1", "Test-2", "Test-3", "Test-4", "Test-5"]
// you may create your list here, lets say reading from a file after checkout
// personally, I like to use scriptler scripts and load the as simple as:
// list = load '/var/lib/jenkins/scriptler/scripts/load-list-script.groovy'
parallelStagesMap = list.collectEntries {
["${it}" : generateStage(it)]
}
}
}
}
stage('Run Stages in Parallel') {
steps {
script {
parallel parallelStagesMap
}
}
}
}
}
我用它来生成我的阶段,其中包含 Jenkins 作业。 build_list 是我想从主要 Jenkins 作业触发的 Jenkins 作业列表,但每个触发的作业都有一个阶段。
build_list = ['job1', 'job2', 'job3']
for(int i=0; i < build_list.size(); i++) {
stage(build_list[i]){
build job: build_list[i], propagate: false
}
}
如果您正在使用 Jenkinsfile,我通过动态创建阶段、并行运行它们以及让 Jenkinsfile UI 显示单独的列来实现它。这假设并行步骤彼此独立(否则不要使用并行),并且您可以将它们嵌套到您想要的深度(取决于您将嵌套用于创建阶段的 for 循环的数量)。
Jenkinsfile Pipeline DSL:如何在作业仪表板 GUI 中显示多列 - 对于所有动态创建的阶段 - 在 PIPELINE 部分中时 请参阅此处了解更多信息。