博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

jenkins集成gitlab实现自动合并

Posted on 2021-03-16 11:12  小憩清风  阅读(1862)  评论(0编辑  收藏  举报

背景

  • 公司目前使用环境和分支绑定的分支管理策略,不同环境有对应分支,代码由功能特性分支合并到测试环境,然后根据环境等级逐级往上合并,为提高效率,需要实现功能特性分支自动合并到测试环境对应分支。

实现思路

  • 整体思路gitlab配置合并请求,自动触发merge request钩子推送相关信息至jenkins的webhook触发jenkins的合并的job,该job通过调用gitlab api实现自动合并,并且将合并的结果邮件通知到请求人员。

实施过程

  1. gitlab创建jenkins账号,给予管理员权限(如果对权限管理比较严格,可以在指定的项目,给予主程权限),配置服务调用token,给jenkins使用。
    image
  2. jenkins配置凭据,将gitlab token 添加到全局凭据中.
    image
  3. 配置邮件通知,详细教程可以参考<<jenkins配置邮件扩展插件,实现邮件发送通知>>
    imageimage
  4. 编写共享库,实现获取对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,'')
}

  1. 共享库内编写邮件模板

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
        
}
  1. 创建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.")
                }
            }
        }
    }
}
  1. 测试结果
    image
    image
    image