CICD 四(Jenkins jenkins-shared-library 编写)

目录结构

注意 ArgoCDUtils.groovy,BranchUtils.groovy 和 NotifyUtils.groovy 这三个文件保存在 src/cn/edana/jenkins/utils 目录下

ArgoCDUtils.groovy

该代码处理 ArgoCD 相关工作

package cn.edana.jenkins.utils

class ArgoCDUtils {
    final Script script

    ArgoCDUtils(Script script) {
        this.script = script
    }
	
    void syncArgoCD(String appName, String prop, String value, String remoteHost, String remoteUsername, String remotePassword) {
	
        // 设置 argocd 操作命令
	def setCmd = "argocd app set ${appName} -p ${prop}=${value}"
        def syncCmd = "argocd app sync ${appName}"

        //  远程 ssh 执行命令
	def remote = [:]
	remote.name = 'argocd-server'
	remote.host = remoteHost
	remote.user = remoteUsername
	remote.password = remotePassword
	remote.allowAnyHosts = true
		
	this.script.sshCommand remote: remote, command: setCmd
	this.script.sshCommand remote: remote, command: syncCmd
		
    }
}

BranchUtils.groovy

该代码处理代码分支相关工作

package cn.edana.jenkins.utils

static boolean isMasterBranch(String branchName) {
    return "master" == branchName
}

static boolean isReleaseBranch(String branchName) {
    return branchName != null && branchName.startsWith("release/")
}

static boolean isAllowAutoDeploy(String branchName) {
    return isMasterBranch(branchName) || isReleaseBranch(branchName)
}

NotifyUtils.groovy

该代码处理钉钉通知相关工作

package cn.edana.jenkins.utils

class NotifyUtils {
    final Script script

    NotifyUtils(Script script) {
        this.script = script
    }


    /**
     * 钉钉通知构建成功消息
     *
     * @param context
     */
    void notifySuccess(context) {
        def title = "项目【${getJobName()}】构建成功"
        notify(title, context)
    }


    /**
     * 钉钉通知构建失败消息
     *
     * @param context
     */
    void notifyFailed(context) {
        def title = "项目【${getJobName()}】构建失败,请相关同事注意!"
        notify(title, context)
    }

    /**
     * 发送钉钉通知消息
     *
     * @param context
     */
    void notify(String title, context) {
        title = title.replace("%2F", "/")
        def content = "## [${title}](${getJobUrl()})  \n" +
                "--- \n" +
                "- **构建仓库**: [${getJobName()}](${context.gitRepo})  \n" +
                "- **构建用户**: ${context.username}  \n" +
                "- **构建分支**: ${context.branchName}  \n" +
                "- **构建版本**: ${getBuildNumber()}  \n" +
                "- **构建详情**: [点击查看](${getBuildUrl()})"
        this.script.dingtalk(
                robot: '7b21fad4-28f7-4fbd-b8df-90bfb0d4f131',
                type: 'MARKDOWN',
                title: title,
                text: [content],
                hideAvatar: false
        )
    }

    private String getJobName() {
        return this.script.env.JOB_NAME.replace("%2F", "/");
    }

    private String getJobUrl() {
        return this.script.env.JOB_URL;
    }

    private String getBuildNumber() {
        return this.script.env.BUILD_NUMBER
    }

    private String getBuildUrl() {
        return this.script.env.BUILD_URL;
    }
}

flaskCI.groovy

该文件在 var 目录下,代码处理 flask 这一类模板代码,

import cn.edana.jenkins.utils.ArgoCDUtils
import cn.edana.jenkins.utils.NotifyUtils

import static cn.edana.jenkins.utils.BranchUtils.isAllowAutoDeploy
import static cn.edana.jenkins.utils.BranchUtils.isMasterBranch


def call(body) {

    def config = [
            "kAutoDeploy"           : false,                                          // 从项目代码 Jenkinsfile 中传入
            "dockerRegistry"        : "https://registry.cn-shenzhen.aliyuncs.com",    // 阿里云 docker 镜像仓库的URL
            "dockerNamespace"       : "klvchen",                                      // 阿里云 docker 镜像仓库的 名空间
            "dingdingId"            : "",
            "argocdAppName"         : "",                                             // 从项目代码 Jenkinsfile 中传入
            "argocdTagProp"         : "yp-flask.image.tag",                           // Helm 模板中指定容器 tag 的值 
	    "remoteHost"	    : "192.168.0.217",                                // 指定 argocd 命令行所在的IP
	    "remoteUsername"	    : "root",                                         // 指定 argocd 命令行所在的用户名
	    "remotePassword"	    : "klvchen",                                      // 指定 argocd 命令行所在的密码
    ]

    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    def argoCDUtils = new ArgoCDUtils(this);
    def notifyUtils = new NotifyUtils(this);

    node {

        // 是否主分支,只有主分支的包才能部署到Maven,也只有主分支的镜像才能发布到生产环境
        def context = [
                "gitRepo"    : "",
                "branchName" : "",
                "username"   : "",
                "projectName": "",
                "imageTag"   : "",
                "gitRepo"    : "",
        ]

        def packageJson
      
        // 把 Jenkins 安装 Docker 插件后的命令添加到环境变量中
        def dockerHome = tool 'myDocker'
        env.PATH = "${dockerHome}/bin:${env.PATH}"

        try {
            stage('拉取代码') {
                checkout scm
                print "change git branch: " + env.BRANCH_NAME

                // 读取项目代码下的 package.json 到 packageJson 对象
                packageJson = readJSON file: 'package.json'
                context.projectName = packageJson.name
                context.branchName = env.BRANCH_NAME
               
	        // 判断分支
                if (isMasterBranch(context.branchName)) {
	            context.imageTag = "${packageJson.version}.${BUILD_NUMBER}"
	        } else {
		    context.imageTag = "${packageJson.version}.${BUILD_NUMBER}-test"
	        }

                context.gitRepo = sh(label: '', returnStdout: true, script: 'git config remote.origin.url').trim()
                context.username = env.CHANGE_AUTHOR_DISPLAY_NAME
                }

                if (fileExists("./Dockerfile")) {
                    // Dockerfile 中包含打包版本
                    stage("打包镜像: ${context.projectName}") {
                        def image = docker.build("${config.dockerNamespace}/${context.projectName}")
                        docker.withRegistry("https://registry.cn-shenzhen.aliyuncs.com") {
                        if (image != null) {
                            image.push("${context.imageTag}")
                        }
                    }
                }
				
	    stage('部署到k8s') {
                def appName = config.argocdAppName
                def branchName = context.branchName
                if (appName == null   == appName) {
                    unstable('未配置argocd应用名')
                    return
                }

                if (!config.kAutoDeploy) {
                    unstable('跳过部署')
                    return
                }

                if (!isAllowAutoDeploy(branchName)) {
                    unstable('只有master和release分支允许自动部署')
                    return
                }

                try {
                    // 传入远程 argocd 所在的服务器信息,执行 argocd 命令			
                    argoCDUtils.syncArgoCD(appName, config.argocdTagProp, context.imageTag.toString(), config.remoteHost, config.remoteUsername, config.remotePassword)
                } catch (err) { // timeout reached or input Aborted
                    unstable('部署异常')
                    print err
                    }
                }

              
            }
            // 钉钉通知
            notifyUtils.notifySuccess(context)
        } catch (e) {
            notifyUtils.notifyFailed(context)
            throw e
        }
    }
}
posted @ 2020-12-18 18:24  klvchen  阅读(75)  评论(0)    收藏  举报