groovy Jenkinsfile -对于动态阶段,将“when”语句替换为“if”

mv1qrgav  于 2022-11-01  发布在  Jenkins
关注(0)|答案(1)|浏览(200)

考虑具有以下结构的存储库:

parent
  - subdir1
  - subdir2

其中每个subdir都是一个独立的项目,并且有自己的Jenkinsfile。我们希望根据子目录中的任何文件是否发生了更改,有条件地从父管道调用这些项目。对于单个目录,这是非常简单的。

stage('build subdir') {
        when {
            changeset "subdir/**"
        }
        steps {
            load "subdir/Jenkinsfile"
        }
    }

但是这个项目实际上有20个子目录。我已经按照https://www.zippyops.com/loops-in-pipeline20210420103750用一个循环替换了这个,但是没有用。

def final repos = ["subdir1", "subdir2", "subdir3"]

pipeline {
    agent any
    stages {

        stage('Run builds') {
            steps {
                checkout scm
                script {
                    repos.each {repo ->
                        stage(repo) {
                            when {
                                changeset "${repo}/**"
                            }
                            steps {
                                load "${repo}/Jenkinsfile"
                            }
                        }
                    }}}}}

它失败了,因为命令whenstep块下无效。java.lang.NoSuchMethodError: No such DSL method 'when' found among steps...-有什么办法可以避开这个问题吗?
主要用例是减少样板文件,并能够动态添加目录到这个monorepo,而不必每次接触Jenkinsfile。

h5qlskok

h5qlskok1#

当你在Script块中时。你不能再使用像when{}这样的声明性语法。所以这里最好的选择是预处理changeSet并得到一个干净的目录列表。下面是我对这个的看法。为了进一步改进你的流水线,你可能也可以并行运行每个阶段。

pipeline {
    agent any
    stages {

        stage('Run builds') {
            steps {
                checkout scm
                script {
                    def repos = getSubDirectoriesChanged()
                    repos.each {repo ->
                        stage(repo) {
                            steps {
                                load "${repo}/Jenkinsfile"
                            }
                        }
                    }}}}}

def getSubDirectoriesChanged() {
    def filesList = []
    def changeLogSets = currentBuild.changeSets

    // First Lets get all the files that changed. 
    for (int i = 0; i < changeLogSets.size(); i++) {
        def entries = changeLogSets[i].items
        for (int j = 0; j < entries.length; j++) {
            def entry = entries[j]
            def files = new ArrayList(entry.affectedFiles)
                for (int k = 0; k < files.size(); k++) {
                def file = files[k]
                filesList.add(file.path)
            }
        }
    }

    // Let's filter the directories, having a / means it's a directory, there can be multiple files changed
    // in the same directory, so we need to drop the duplicates.
    return filesList.findAll{ it.contains("/") }.collect { it.split('/')[0] }.unique()
}

相关问题