【jenkins】第十一篇:jenkins pipline完整流水线实现

第十一篇:jenkins pipline完整流水线实现

一、实现

  • gitlab+jenkins+harbor+k8s_rancher的cicd流水线
  • 手动提交&gitlab触发判定
  • Generic Webhook Trigger触发器
  • 钉钉审批
  • 构建描述自定义
  • 构建名称自定义
  • 钉钉通知结果
  • gitlab cicd接收构建结果

二、流程图

在这里插入图片描述

三、效果展示

在这里插入图片描述

在这里插入图片描述

四、jenkinsfile

  • 在配置pipline之前,需要先安装相关插件和配置相相关凭据,见第二篇:jenkins插件;第三篇:jenkins凭据管理
  • 配置时,因为用到了参数化构建,第一次执行会报错,可手动添加参数,也可再执行一次。
pipeline {   
  agent any
  //参数化构建,xxxxxx需根据实际情况修改
  parameters {
​    //触发动作,用于区分是gitlab webhook自动触发还是jenkins手动触发
​    string(name: 'event_name', defaultValue: 'jenkins_admin', description: 'event name')
​    //分支名称,用于GenericTrigger-->regexpFilterText 制定匹配分支条件
​    string(name: 'BRANCHNAME', defaultValue: 'xxxxxx', description: '分支名称')
​    //用于GenericTrigger token
​    string(name: 'JENTRIGGERTOKEN', defaultValue: 'xxxxxx', description: '触发器token')
  }
  //定义用于自动安装和放置在PATH. 如果agent none指定,则忽略。例如自动安装maven、jdk、gradle等
  //我这里是springboot项目,需要jdk1.8 maven打包
  tools {
​    //maven
​    maven 'maven'
​    //jdk
​    jdk 'jdk1.8'
  }
  //环境变量
  environment {
​    //GIT凭证ID,根据实际情况修改
​    GITCREDENTIALSID='1'
​    //harbor凭证ID,根据实际情况修改
​    HARBORCREDENTIALSID='2'
​    //rancher凭证ID,根据实际情况修改
​    RANCHERCREDENTIALSID='3'
​    //版本定义
​    def DATE = sh(script: "date +%Y_%m_%d", returnStdout:true).trim()
​    BUILD_VERSION = "${DATE}.${BUILD_NUMBER}"
​    //#####以下为需要根据实际项目修改#####//
​    //GIT地址
​  GIT_ADDR='http://xxxx/xxxx/xxxxx.git'
​    //分支名称
​    BRANCH_NAME='xxxxxx'
​    //打包命令
​    BUILD_SH='xxxxxx'
​    //harbor地址
​    HARBOR_ADDRES='xxxxxx'
​    //harbor项目地址
​    HARBOR_PROJECT='xxxxxx'
​    //rancher工作负载api地址
​    WORKAPIADRESS='xxxxxx'
​    //jenkins触发器secretToken,与参数化构建中的保持一致
​    JENTRIGGERTOKEN='xxxxxx'
​    //Dockerfile所在相对路径
​    DOCKERFILEWORK='xxxxxx'
  }
  //运行参数,不需要修改
  options{
​    //时间戳
​    timestamps ()
​    //禁止管道的并发执行
​    disableConcurrentBuilds()
​    //构建保留配置
​    buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '7', numToKeepStr: '9')
  }
  //触发器配置,不需要修改
  triggers{
​    GenericTrigger(
​      genericVariables:[[key:'event_name',value:'$.event_name'],  //触发动作  pubat or tag_pubat
​        [key:'user_name',value:'$.user_name'],  //GitLab用户名
​        [key:'project_name',value:'$.project.name'],    //项目名称 DevOps_Test
​        [key:'git_url',value:'$.project.git_http_url'],   //git_url
​        [key:'ref',value:'$.ref'],         //分支或tag信息
​        [key:'group_name',value:'$.project.namespace'], //GITLAB_GROUP
​        [key:'commits_id',value:'$.commits[0].id'] //gitlab commits id],
​      token:"""${params.JENTRIGGERTOKEN}""",  //gitlab webhook触发token 多个任务配置同一个token会一起触发
​      //causeString:'Triggered on $ref',
​      causeString:'Triggered on $project_name $event_name by $user_name',
​      printContributedVariables:true,
​      printPostContent:true,
​      //此处的BRANCHNAME是通过环境变量获取构建过程中的当前分支
​      regexpFilterExpression: 'refs/heads/' + BRANCHNAME,
​      //regexpFilterExpression:'$ref',
​      regexpFilterText: """refs/heads/${params.BRANCHNAME}"""
​    )
  }
  //阶段
  stages {
​    stage('触发判定') {
​      steps {
​        script {if (params.event_name == 'jenkins_admin') {echo "This job is triggered by ${event_name}"
​            currentBuild.description = "Started by jenkins push by ${USER}"}else {echo "This job is triggered by Gitlab  ${event_name}"
​            currentBuild.description = "Started by GitLab ${event_name} by ${user_name} branch:${BRANCH_NAME}"}}}}
​    stage('构建名称定义') {
​      steps {
​        // 自定义设置构建历史显示的名称和描述信息 
​        script {
​          //设置buildName
​          wrap([$class: 'BuildUser']) {
​              // 修改构建历史展示名称
​              //def deploylog="${BUILD_USER} use pipeline  '${JOB_NAME}(${BUILD_NUMBER})' "
​              //println deploylog
​              buildName "#${BUILD_NUMBER}-${HARBOR_PROJECT}:${BUILD_VERSION}"
​              //buildName '#${BUILD_NUMBER} -demo:${HARBOR_PROJECT}:${BUILD_VERSION}'
​              //修改Description
​              //buildDescription '<span style="padding-left: 160px;color: #0587d4;"> demo:${buildVersion}  ${environment}  ${branch} </span>'}}}}
​    stage('钉钉审批') {
​      steps {
​        script {
           //py程序配置的Authorization
​          hook = registerWebhook(authToken: 'xxxxxx')
​          webhookId = hook.url.substring(hook.url.lastIndexOf('/') + 1)            
​          dingtalk (
             //jenkins配置里钉钉机器人ID
​            robot: '1',
​            type: 'ACTION_CARD',
​            title: '确认发布',
​            text: [
​              //'**是否确认发布**',
​              '## **<font color=blue>是否确认发布</font>**',
​              '',
​              '---',
​              "- 任务名称:${JOB_NAME}",
​              "- 构建ID:[#${env.BUILD_NUMBER}](${env.BUILD_URL})",
​              "- 构建人:${env.USER}",
​              "- 构建说明:${currentBuild.description}",
​              "- 持续时长:${currentBuild.durationString}"],
​            btns: [[
​              title: '确认',
               //py中转程序外网地址
​              actionUrl: "http://xxxxxx/jenkins/webhook?url=${webhookId}&type=confirm&jobName=${JOB_NAME}&buildNumber=${env.BUILD_NUMBER}"],
​              [
​              title: '取消',
               //py中转程序外网地址
​              actionUrl: "http://xxxxxx/jenapi/jenkins/webhook?url=${webhookId}&type=cancel&jobName=${JOB_NAME}&buildNumber=${env.BUILD_NUMBER}"]])
​          
​          // 30分钟没有确认 取消任务
​          timeout(time: 1800, unit: 'SECONDS') {
​            data = waitForWebhook hook
​            // 解析 JSON 字符串
​            def json = new groovy.json.JsonSlurperClassic().parseText(data)
​            def type = json.type
​            // 判断 type 的值
​            if (type == 'cancel') {echo "取消"
​              currentBuild.result = 'ABORTED'
​              error('任务被取消')}}}}}
​    stage('代码拉取') {
​      steps {git branch: env.BRANCH_NAME, credentialsId: env.GITCREDENTIALSID, url: env.GIT_ADDR
​      }}
​    stage('开始打包') {
​      steps {sh """${BUILD_SH}"""
​      }}
​    stage('镜像构建') {
​      steps {
​        script {
​          dir("${WORKSPACE}/${DOCKERFILEWORK}") {sh 'ls'
​            docker.withRegistry("${HARBOR_ADDRES}", env.HARBORCREDENTIALSID) {
​            docker.build("${HARBOR_PROJECT}:${BUILD_VERSION}").push()}echo "build DockerImage success"}}}}
​    stage('rancher部署') {
​      steps {
​        rancherRedeploy alwaysPull: true, credential: env.RANCHERCREDENTIALSID, images: """${HARBOR_PROJECT}:${BUILD_VERSION}""", workload: env.WORKAPIADRESS
​      }}
  }
  post {
​    always{
​      script{
​        println("一直执行")}}
​    success{
​      script{
​        println("成功")
​        updateGitlabCommitStatus name: 'cicd-build', state: 'success'}}
​    aborted{
​      script{
​        println("取消")
​        updateGitlabCommitStatus name: 'cicd-build', state: 'canceled'}}
​    failure{
​      script{
​        println("失败")
​        updateGitlabCommitStatus name: 'cicd-build', state: 'failed'}}
  }
}

五、python脚本

  • cat ding.py

启动 nohup python3 ding.py > ding.log 2>&1 &

# -*- coding: utf-8 -*-

from flask import Flask, request
from jenkinsapi.jenkins import Jenkins
import requests

app = Flask(__name__)

@app.route('/jenkins/webhook', methods=['GET'])
def post():
    commitType = request.args.get('type')
    webhookId = request.args.get('url')
    jobName = request.args.get('jobName')
    buildNumber = request.args.get("buildNumber")

    # 创建Jenkins对象
    ## jenkins地址
    jenkins_url = 'http://xxxxxx'
    ## jenkins用户名 
    username = 'admin'
    ## jenkins密码
    password = 'xxxxxx'
    jenkins = Jenkins(jenkins_url, username, password)
    
    # 获取job对象
    job = jenkins.get_job(jobName)
    
    # 获取指定构建的信息
    build_number = int(buildNumber)
    build = job.get_build(build_number)
    build_result = build.get_status()

    # 打印构建状态
    print('Job "{}" build {} status: {}'.format(jobName, buildNumber, build_result))

    if build_result == 'ABORTED':
        return "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;color:orange;'>任务已中止,请重新构建<h1>"
    elif build_result == 'FAILURE':
        return "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;color:red;'>任务构建失败,请勿重复点击<h1>"

    # 组装webhook基础参数
    ## jenkins地址/webhook-step
    url = 'http://xxxxxx/webhook-step/' + webhookId
    data = {'type': commitType}
    ## Authorization配置,在pipline里用到,用于接口调用验证
    headers = {
        'Authorization': 'xxxxxx',
        'Content-Type': 'application/json'
    }

    # 调用webhook
    try:
        response = requests.post(url, json=data, headers=headers)
        response.raise_for_status()
    except Exception as e:
        logging.exception("Failed to call Jenkins webhook step service.")
        return "请求失败:" + str(e)

    if commitType == 'confirm': 
        return "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;color: green;'>已同意</h1>" if response.status_code == 200 else "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;color:orange;'>请勿重复操作</h1>"
    else:
        return "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;;'>已拒绝</h1>" if response.status_code == 200 else "<h1 style='font-size: 2em;display: flex;justify-content: center;align-items: center;height: 100%;color:orange;'>请勿重复操作</h1>"
# 端口配置
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8099)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值