简体   繁体   English

声明式Jenkins管道中多个节点上的并行签出

[英]Parallel checkout in declarative Jenkins pipeline on multiple nodes

I'm developing a declarative Jenkins pipeline for CI builds, triggered from Gitlab. 我正在为从Gitlab触发的CI构建开发声明式Jenkins管道。 What I have now: 我现在所拥有的:


// variable definitions

pipeline {
    agent none

    parameters {
            string(defaultValue: 'develop',
                description: 'Commit ID or branch name to build', 
                name: 'branch', 
                trim: false)
    }

    stages {
        stage('Checkout') {
            parallel {
                stage ('Windows') {
                    agent {
                        label 'build' && 'windows'
                    }

                    steps {
                        script {

                            def checkout_ext = [[$class: 'CleanCheckout'],
                                                [$class: 'CleanBeforeCheckout']] // calls git clean -fdx and git reset --hard

                            if (env.gitlabActionType == "MERGE"){   
                                  checkout_ext.add([$class: 'PreBuildMerge', 
                                                    options: [ mergeRemote: "origin",
                                                              mergeTarget: "${env.gitlabTargetBranch}"]])
                            }
                        }

                        checkout([
                                $class: 'GitSCM', 
                                branches: [[name: "${params.branch}"]],
                                userRemoteConfigs: [[ url: "${git_url}",                                          credentialsId: "${git_credentials_id}" ]],
                                extensions:   checkout_ext 
                        ])
                    }
                }

                stage('Linux') {
                    agent {
                        label 'build' && 'linux'
                    }
                    steps {
                        script {

                            def checkout_ext = [[$class: 'CleanCheckout'], 
                                                [$class: 'CleanBeforeCheckout']] // calls git clean -fdx and git reset --hard

                            if (env.gitlabActionType == "MERGE"){   
                               checkout_ext.add([$class: 'PreBuildMerge', 
                                                 options: [ mergeRemote: "origin",
                                                 mergeTarget: "${env.gitlabTargetBranch}"]])
                            }
                        }

                        checkout([
                                $class: 'GitSCM', 
                                branches: [[name: "${params.branch}"]],
                                userRemoteConfigs: [[ url: "${git_url}", credentialsId: "${git_credentials_id}"]],
                                extensions:   checkout_ext 
                        ])
                    }
                }
            }
        }
    }
}

Checkout stage is somewhat complex. 结帐阶段有些复杂。 If gitlabActionType is MERGE , then first try to merge into a target branch, to make sure that merge request does not break anything in it. 如果gitlabActionTypeMERGE ,则首先尝试合并到目标分支中,以确保合并请求不会破坏其中的任何内容。

This code is the same for both OSes. 这两个操作系统的代码相同。 I'd like to avoid code duplication, but cannot figure out correct syntax for that. 我想避免代码重复,但是无法找出正确的语法。

I have tried moving definition of checkout steps to the global variable, but have got syntax errors. 我尝试将结帐步骤的定义移至全局变量,但出现语法错误。


def checkout_step = {
    script {
   ...
    }
    checkout (... )
}

pipeline {
...
   stages {
        stage('Checkout') {
            parallel {
                stage ('Windows') {
                    agent {
                        label 'build' && 'windows'
                    }

                    steps {
                        checkout_step
                    }
                }
                stage ('Linux') {
                    agent {
                        label 'build' && 'linux'
                    }

                    steps {
                        checkout_step
                    }
                }
            }
        }
    }
}

If add steps , there's also an error: 如果添加steps ,则还会出现错误:


def checkout_step = steps {
    script {
   ...
    }
    checkout (... )
}

pipeline {
...
   stages {
        stage('Checkout') {
            parallel {
                stage ('Windows') {
                    agent {
                        label 'build' && 'windows'
                    }

                    checkout_step

                }
                stage ('Linux') {
                    agent {
                        label 'build' && 'linux'
                    }

                    checkout_step

                }
            }
        }
    }
}

Have found solution here 在这里找到解决方案


git_url = "git@gitserver.corp.com:group/repo.git"
git_credentials_id = 'aaaaaaa-bbbb-cccc-dddd-eefefefefef'


def checkout_tasks(os_labels) {
    tasks = [:]

    for (int i = 0; i < os_labels.size(); i++) {
        def os = os_labels[i]
        tasks["${os}"] = {
            node("build && ${os}"){

                def checkout_ext = [[$class: 'CleanCheckout'], [$class: 'CleanBeforeCheckout']] // calls git clean -fdx and git reset --hard

                if (env.gitlabActionType == "MERGE"){   
                    checkout_ext.add([
                            $class: 'PreBuildMerge', 
                            options: [ 
                            mergeRemote: "origin", 
                            mergeTarget: "${env.gitlabTargetBranch}" 
                            ]
                    ])
                         /* using this extension requires .gitconfig with section [user for Jenkins]
                            Example
                            [user]
                            email = jenkins@builder
                            name = Jenkins

                          */
                }

                checkout([
                        $class: 'GitSCM', 
                        branches: [[name: "${params.branch}"]],
                        userRemoteConfigs: [[
                            url: "${git_url}", 
                            credentialsId: "${git_credentials_id}"
                        ]],
                        extensions:  checkout_ext 
                ])

            }
        }
    }
    return tasks
}


pipeline {
    agent none

    parameters {
        string(defaultValue: 'develop',
               description: 'Commit ID or branch name to build', 
               name: 'branch', 
               trim: false)
    }

    stages {
        stage('Checkout') {
            steps {
                script {
                    def OSes = ["windows", "linux"]
                    parallel checkout_tasks(OSes)
                }
            }
        }
   }
}

It is important also to declare git_url and git_credentials_id without def , so that functions can read them. 声明不带def git_urlgit_credentials_id也很重要,以便函数可以读取它们。

More details in this question 这个问题的更多细节

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM