Pipeline 实现根据Git提交信息触发执行相应Job

实现功能:

1、使用Generic Webhook Trigger 获取 gitlab Webhook中开发的commit信息
2、获取Webhook中的ref、modified、added、removed等信息,经处理后,根据分支、文件路径(模块路径),判断执行哪个Job(相应模块的Job)
3、Generic Webhook Trigger 的token 使用变量进行配置

原本需求

为单仓库多模块项目的打包发布提供一种解决方案。
多模块共用一个git仓库,想实现 提交哪个模块就构建哪个模块。
传统的webhook只能根据push\merge等动作进行触发,但触发的job是全量构建,不满足需求。

用到的插件及版本

Generic Webhook Trigger 1.72

完整Pipeline

文末有注意事项

pipeline{
    agent{
        label "master"
    }
    triggers {
        GenericTrigger(
            // 需要手动执行一下,第二次才能被触发
            genericVariables: [
            [key: 'MODIFIED', value: '$.commits[*].modified', expressionType: 'JSONPath'],
            [key: 'ADDED', value: '$.commits[*].added', expressionType: 'JSONPath'],
            [key: 'REMOVED', value: '$.commits[*].removed', expressionType: 'JSONPath'],
            [key: 'REF', value: '$.ref', expressionType: 'JSONPath', regexpFilter: 'refs/heads/'],
            [key: 'GIT_USER', value: '$.user_name', expressionType: 'JSONPath']
            ],

            causeString: 'Triggered on $GIT_USER',

            // 使用JOB_NAME作为token,当我的job为Cluster-Hook时,gitlab的webhook填  http://jenkins.example.com/generic-webhook-trigger/invoke?token=Cluster-Hook
            token: env.JOB_NAME,

            printContributedVariables: false,
            printPostContent: false,

            silentResponse: false,

            regexpFilterText: '$MODIFIED$ADDED$REMOVED',
            // 当提交信息中有 "[    /   时,才触发
            regexpFilterExpression: '"[a-zA-Z0-9]+\\/'
        )
    }
    stages{
        stage("执行构建子Job"){
            steps{
                echo "========executing 执行构建子Job========"
                script {
                    CHANGE_MODULES=[]
                    // 转换
                    def CHANGE_STR_2_LIST = { String tmp->
                        // 获取到的MODIFIED,REMOVED,ADDED等值都是String类型, 使用切割的方法,通过each存放到list里面
                        def x = tmp.replace("[","").replace("]","").replace('"','').split(",")
                        x.each {
                            // 对每个元素进行判断,如果为pom.xml文件,则取pom.xm前的路径,不是则取src前的路径
                            // project1/module1/pom.xml   ---->  取 project1/module1/
                            // project1/module2/src/abc/cde.java   ---->  取 project1/module2/
                            if (!it.find("pom.xml")){
                                def str = it.split('src')
                                // 判断list中有没有当前路径,如果有就不添加,防止索引过界
                                if (!CHANGE_MODULES.contains(str[0])){
                                    CHANGE_MODULES.add(str[0])
                                }
                            } else {
                                // 没写错,专门少写的l 
                                def str = it.split('pom.xm')
                                CHANGE_MODULES.add(str[0])
                            }
                        }
                        // 三个变量可能有空值,将空值删除
                        if (CHANGE_MODULES.contains('')){
                            CHANGE_MODULES=CHANGE_MODULES.minus('')
                        }
                    }
                    // 调用闭包,获取模块路径存入list
                    CHANGE_STR_2_LIST(MODIFIED)
                    CHANGE_STR_2_LIST(REMOVED)
                    CHANGE_STR_2_LIST(ADDED)

                    println(CHANGE_MODULES.unique())
                    // 根据分支区分环境
                    // master --> prod
                    // gray --> gray
                    // alpha --> test
                    switch (REF){
                        case "master":
                            CHANGE_MODULES.unique().each {
                                // 根据路径判断要触发的Job
                                switch (it){
                                    case "servers/callback/" :
                                        // 构建callback 模块
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    case "servers/activity/" :
                                        // 构建activity 模块
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        // build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    case "project3/module2/" :
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        // build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    default:
                                        // 有的路径不需要单独Job打包
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                }
                            }
                            break
                        // case "alpha":
                        case "gray":
                            CHANGE_MODULES.unique().each {
                                switch (it){
                                    case "servers/callback/" :
                                        // 构建callback 模块
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        // build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    case "servers/activity/" :
                                        // 构建activity 模块
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        // build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    case "project3/module2/" :
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                        // build wait: false, propagate: false, job: 'example-parent-servers-callback'
                                        break
                                    default:
                                        println("模块:"+"$it\t"+"分支:"+"$REF")
                                }
                            }
                            break
                        default:
                            println("模块:"+"$it\t"+"分支:"+"$REF")
                    }
                }
            }
        }
    }
}

注意事项:

Generic Webhook Trigger的配置写在Pipeline中,需要手动执行一下构建,执行构建(失败)后,Jenkins会将Pipeline中的配置合并到Jenkins配置页面,然后gitlab webhook才能触发成功。如果直接配置中界面中,就不需要手动构建。

文档:

1赞