Bootstrap

使用 Generic Webhook Trigger 触发 Jenkins 多分支流水线自动化构建

在使用 Jenkins 驱动整个 CI/CD 的流程时,代码提交触发任务自动化构建是一个很重要的步骤。这篇文章主要介绍如何在 Jenkins 的多分支流水线(Multibranch Pipeline)中使用 触发任务的自动化构建。

需求

我们项目的源代码是托管在本地的 Gitlab 服务上,Git Flow 也是相对比较简单的。目前分为 、 和 分支。平时的开发是在 分支下,当 分支代码合并到 分支的时候,需要能做到代码构建并发布到本地测试环境,当 分支合并到 的时候,需要能做到代码发布到线上测试环境。

对于多分支流水线的问题是,每次触发的可能是所有的分支构建,这显然是不符合要求的。因此,我们需要的是 webhook 可以按分支触发构建,同时根据不同的分支完成不同的构建脚本。这里面涉及到两个需求:

webhook 按分支触发

首先,我们完成每次 和 分支有代码合并进去的时候,触发任务构建。这里需要借助到 插件。

Generic Webhook Trigger 插件

我们项目使用的 是声明式脚本,在 的文档中,声明式脚本是这样使用的:

pipeline {
  agent any
  triggers {
    GenericTrigger(
     genericVariables: [
      [key: 'ref', value: '$.ref']
     ],
     causeString: 'Triggered on $ref',
     token: 'abc123',
     printContributedVariables: true,
     printPostContent: true,
     silentResponse: false,
     regexpFilterText: '$ref',
     regexpFilterExpression: 'refs/heads/' + BRANCH_NAME
    )
  }
  stages {
    stage('Some step') {
      steps {
        sh "echo $ref"
      }
    }
  }
}

文档中没有对这些配置项做具体的说明,对使用者造成了一定的门槛。在实践中,发现有几个我们需要比较关注的配置项。

的触发 URL 是固定的:。通过 我们可以区分不同 job 的 trigger,同时该令牌还允许直接调用,而无需任何其他身份验证凭据。

也就是说,上面的 配置为 ,我们可以在浏览器中通过访问 触发该任务。

这个配置项的写法基本是固定的,从 中取出 赋值给 变量,我们就可以在脚本中使用 变量获取到 的 值。当然,我们也可以获取更多的内容复制给不同的变量,这个就看具体的需求了。

顾名思义,这是一个使用正则表达式的过滤器,也是我们做分支触发构建的关键因素。当满足该正则表达式的时候, 才会触发构建。

这里有一个小坑,就是 反斜杠在 Jenkins 中是用来转义字符的。举个例子,我们需要匹配 这个分支,我们的正则表达式是这样的:

regexpFilterExpression: '^refs/heads/(features/sprint\d*)$'

这样写会报错的,因为 直接转义了,我们需要再加一个 ,如下:

regexpFilterExpression: '^refs/heads/(features/sprint\\d*)$'

这个字段跟上面的 是成对使用的,正则表达式过滤的就是该字段的内容。我们前面把 的 值赋值给了 变量,这里就可以直接通过 来使用 变量了。

regexpFilterText: '$ref'

Trigger 配置

通过前面对 插件的了解,我们可以针对自己的项目进行配置了。

建议以项目名称开头,后面加上一定规则的哈希字符串,保证在 中 不会出现重复。

我们的过滤规则是只接受 和 分支

triggers{
    GenericTrigger(
        genericVariables: [
          [key: 'ref', value: '$.ref']
         ],
        causeString: 'Triggered on $ref',
        token: 'leangoo-b73b246d4bc9c5c9',
        printContributedVariables: true,
        printPostContent: true,
        silentResponse: false,
        regexpFilterText: '$ref',
        regexpFilterExpression: '^refs/heads/(features/sprint\\d*|master)$'
    )
}

到这里为止,Jenkins 这部分的配置已经全部完成了。接下来就是配置 的 了。

Gitlab webhook 配置

1. 进入项目的 界面,新增一个

就是 的 地址,触发事件这里我们只勾选 ,不需要 验证的话可以取消掉。

然后我们可以点击测试按钮进行测试。第一次尝试的时候,发现报 的错误,我们需要进入 的管理后台允许本地的请求。

2. 允许本地请求

这一步操作需要有管理员权限。进入 ,依次选择 ,勾选

再次点击测试按钮,可以成功地触发 的自动化构建。我们可以 代码到不同的分支测试一下配置是否正确。

不同分支的构建脚本差异化处理

前面的配置做到了 和 分支有代码合并进来会触发自动化构建。但是对于多分支流水线,如果 检测到了分支的根目录下有 文件,就会进行构建。最终导致的问题是,如果项目下有 n 个分支,每个分支都有 文件,那么这 n 个分支都会构建一遍。这显然也不是我们想要的。

我们可以利用 的 语法来做到让不同的分支来做不同的事情。 的语法示例如下:

pipeline {
    agent any
    stages {
        stage('Example Build') {
            steps {
                echo 'Hello World'
            }
        }
        stage('Example Deploy') {
            when {
                branch 'production'
            }
            steps {
                echo 'Deploying'
            }
        }
    }
}

指令允许管道根据给定条件确定是否应执行该阶段。 指令必须至少包含一个条件。如果 指令包含多个条件,则所有子条件必须返回 才能执行该阶段。

支持 表达式,配合正则表达式可以构建出我们需要的条件。 比如这里,如果是 或 分支我们就会下面的步骤。

stage('build') {
            when {
                expression { BRANCH_NAME ==~ /(master|features\/sprint\d*)/ }
            }
            steps {
                sh '''
                    # 要执行的脚本
                    ...
                '''
            }
        }