背景
- 公司目前使用環境和分支綁定的分支管理策略,不同環境有對應分支,代碼由功能特性分支合並到測試環境,然后根據環境等級逐級往上合並,為提高效率,需要實現功能特性分支自動合並到測試環境對應分支。
實現思路
- 整體思路gitlab配置合並請求,自動觸發merge request鈎子推送相關信息至jenkins的webhook觸發jenkins的合並的job,該job通過調用gitlab api實現自動合並,並且將合並的結果郵件通知到請求人員。
實施過程
- gitlab創建jenkins賬號,給予管理員權限(如果對權限管理比較嚴格,可以在指定的項目,給予主程權限),配置服務調用token,給jenkins使用。

- jenkins配置憑據,將gitlab token 添加到全局憑據中.

- 配置郵件通知,詳細教程可以參考<<jenkins配置郵件擴展插件,實現郵件發送通知>>


- 編寫共享庫,實現獲取對git api的常見操作。
src/com/devops/gitlab.groovy
package com.devops
// 此處參考zeyang的jenkins封裝的源碼,也可以去gitlab的api文檔中獲取當前版本的api接口,根據實際需求進行編寫。https://your-gitlab-url/help/api/README.md下有所有的api接口說明文檔
//封裝HTTP請求
def HttpReq(reqType,reqUrl,reqBody){
// 定義gitlab的接口地址
def gitServer = "https://gitlab.url.com/api/v4"
// 此處使用之前在jenkins中創建的gitlab token的憑據的id名稱
withCredentials([string(credentialsId: 'jenkins-gitlab-token-text', variable: 'gitlabToken')]) {
result = httpRequest customHeaders: [[maskValue: true, name: 'PRIVATE-TOKEN', value: "${gitlabToken}"]],
httpMode: reqType,
contentType: "APPLICATION_JSON",
consoleLogResponseBody: true,
ignoreSslErrors: true,
requestBody: reqBody,
url: "${gitServer}/${reqUrl}"
//quiet: true
}
return result
}
//允許合並
def AcceptMr(projectId,mergeId){
def apiUrl = "projects/${projectId}/merge_requests/${mergeId}/merge"
HttpReq('PUT',apiUrl,'')
}
- 共享庫內編寫郵件模板
src/com/devops/email.groovy
package com.devops
//定義郵件內容
def mergeEmail(username, source_branch, target_branch, status, merge_url, emailUser){
emailext body: """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
<img height="100" width="100" src="https://about.gitlab.com/images/devops-tools/gitlab-logo.svg">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<tr>
<td><br />
<b><font color="#0B610B">代碼合並處理通知</font></b>
</td>
</tr>
<tr>
<td>
<ul>
<li>提交人: ${username}</li>
<li>源分支: ${source_branch}</li>
<li>目標分支: ${target_branch}</li>
<li>合並結果: ${status} </li>
<li>合並URL: <a href="${merge_url}">${merge_url}</a></li>
</ul>
</td>
</tr>
<tr>
</table>
</body>
</html> """,
subject: "gitlab分支合並結果通知",
to: emailUser
}
- 創建jenkins item, 編寫pipeline
@Library("jenkinslib@master") _
def gitlabapi = new com.devops.gitlab()
def toemail = new com.devops.email()
def sourceBranch = source_branch - "refs/heads/"
def targetBranch = target_branch - "refs/heads/"
List branch_list = ["fat", 'fat1', 'fat2', 'uat']
currentBuild.description = "Trigger by ${username} ${sourceBranch} merge to ${targetBranch}"
if (!branch_list.contains(target_branch)) {
error "目標分支不在${branch_list}中"
}
pipeline {
agent any
options {
buildDiscarder(logRotator(numToKeepStr: '60')) // 保留構建記錄為60次
disableConcurrentBuilds() // 關閉同時執行流水線
timeout(time: 1, unit: 'HOURS') // 設置流水線超時時間
timestamps() //日志打印時間戳
}
triggers {
// 參考鏈接1: https://www.jianshu.com/p/7873d2f0dd3e
// 參考鏈接2: https://plugins.jenkins.io/generic-webhook-trigger/
GenericTrigger(
genericVariables: [
[key: 'username', value: '$.user.username'],
[key: 'user_email', value: '$.user.email', ],
[key: 'source_branch', value: '$.object_attributes.source_branch', ],
[key: 'target_branch', value: '$.object_attributes.target_branch', ],
[key: 'project_id', value: '$.project.id', ],
[key: 'megre_id', value: '$.object_attributes.iid', ],
[key: 'megre_state', value: '$.object_attributes.state',],
[key: 'merge_url', value: '$.object_attributes.url']
],
token: 'jenkins-gitlab-mr' ,
causeString: ' Triggered on $branch' ,
silentResponse: true,
printContributedVariables: true,
printPostContent: true,
)
}
stages {
stage('merge') {
when {
equals expected: 'opened', actual: megre_state
}
steps {
script {
try {
gitlabapi.AcceptMr(project_id, megre_id)
toemail.mergeEmail(username, source_branch, target_branch, '合並成功', merge_url, user_email)
} catch(Exception ex) {
toemail.mergeEmail(username, source_branch, target_branch, '合並失敗', merge_url, user_email)
error ex
}
}
}
}
stage('do not merge') {
when {
not {
equals expected: 'opened', actual: megre_state
}
}
steps {
script {
println("mergeState is not opened, nothing to do.")
}
}
}
}
}
- 測試結果


