前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >3.Jenkins进阶之流水线pipeline基础使用实践

3.Jenkins进阶之流水线pipeline基础使用实践

作者头像
全栈工程师修炼指南
发布2022-09-29 19:01:52
4.3K0
发布2022-09-29 19:01:52
举报
文章被收录于专栏:全栈工程师修炼之路

[TOC]

0x01 基础实践

(1) Maven 构建之 Pipeline Script

描述:此处重新不在累述新建流水线任务(maven-pipeline-helloword)而是直接进行配置测试等关键项; 流程:代码拉取 -> 代码检测 -> 代码构建 -> 代码部署 -> 消息通知

Step 1. Dashboard -> maven-pipeline-helloword -> 流水线项目配置 (名称|丢弃旧的构建|参数化构建过程(Git/名称))

代码语言:javascript
复制
# Git 参数
名称: git_tags
描述: Project_Release
参数类型: 标签
默认值: origin/master
排序方式: DESCENDING SMART
----------------------------
# 选项 参数
名称: deploy_option
选项:
deploy
rollback
redeploy
描述: 部署&回退&重部署

Step 2.流水线 Pipeline script 编写

代码语言:javascript
复制
pipeline {
  agent any
  stages {
    stage ("代码获取") {
      steps {
       checkout([$class: 'GitSCM', branches: [[name: '${git_tags}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f', url: 'git@gitlab.weiyigeek.top:ci-cd/java-maven.git']]])
      }
    }

    stage ("代码质检") {
     steps {
       sh label: 'sonar', returnStatus: true, script: '''/usr/local/bin/sonar-scanner -Dsonar.projectName=${JOB_NAME} -Dsonar.projectKey=Hello-World -Dsonar.sources=.'''
     }
    }

    stage ("项目构建") {
     steps {
      // 此处实际上不用执行cd命令
      sh label: 'build', script: 'cd /var/lib/jenkins/workspace/maven-pipeline-helloword/ && /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true '
     }
    }

    stage ("项目部署") {
     steps {
      // 脚本为前面一章的部署脚本(两种方式)
      sh label: 'deploy', script: '/tmp/script/maven-jenkins-ci-script.sh'
      // sh "/tmp/script/maven-jenkins-ci-script.sh"
     }
    }
  }

  // 消息通知: POST阶段当所有任务执行后触发
  post {
    // 企业微信
    always {
      qyWechatNotification aboutSend: true, failNotify: true, failSend: true, mentionedId: 'ALL', mentionedMobile: '', startBuild: true, successSend: true, unstableSend: true, webhookUrl: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c222f3fc-f645-440a-ad24-0ce8d9626fa0'
    }

    // 钉钉
    success {
      //当此Pipeline成功时打印消息(注意此处的robot为您在Jenkins全局配置中设置钉钉的id值)
      echo 'success'
      dingtalk (
          robot: 'weiyigeek-1000',
          type: 'LINK',
          title: 'Jenkins 持续集成 - 任务名称 ${JOB_NAME}',
          text: [
              '项目构建成功',
              'Pipeline 流水线测试'
          ],
          messageUrl: 'http://www.weiyigeek.top',
          picUrl: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2319834554,1372531032&fm=26&gp=0.jpg',
          atAll: true
      )
    }
  }
}

Step 3.Pipeline maven-pipeline-helloword 进行选项参数构建 (Build with Parameters)-> 部署 v1.8 版本

WeiyiGeek.参数构建
WeiyiGeek.参数构建

WeiyiGeek.参数构建

  • Step 4.查看部署结果与信息通知
WeiyiGeek.Kubernets部署结果与消息通知
WeiyiGeek.Kubernets部署结果与消息通知

WeiyiGeek.Kubernets部署结果与消息通知

(2) Maven 构建之 Pipeline Script from SCM

描述: 我也可以将上面流水线的脚本放在我们的代码项目之中,在流水线拉取项目时候便会自动按照项目中的Jenkinsfile文件内容进行执行对于操作

Step 1.修改项目首页文件以及在项目根添加Jenkinsfile文件(内容将取消第一阶段的代码拉取),例如:

代码语言:javascript
复制
# (1) E:\EclipseProject\hello-world\src\main\webapp\index.jsp
<h1>Maven - Hello World - v1.10 - Pipeline script for SCM</h1>

# (2) 项目信息
/e/EclipseProject/hello-world (master)
$ ls
Jenkinsfile  pom.xml  src/  target/

# (3) Jenkinsfile : 注意内容将取消第一阶段的代码拉取
pipeline {
  agent any
  stages {

    stage ("代码质检") {
     steps {
       sh label: 'sonar', returnStatus: true, script: '''/usr/local/bin/sonar-scanner -Dsonar.projectName=${JOB_NAME} -Dsonar.projectKey=Hello-World -Dsonar.sources=.'''
     }
    }

    stage ("项目构建") {
     steps {
      sh label: 'build', script: 'cd /var/lib/jenkins/workspace/maven-pipeline-helloword/ && /usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true '
     }
    }

    stage ("项目部署") {
     steps {
      // 脚本为前面一章的部署脚本
      sh label: 'deploy', script: '/tmp/script/maven-jenkins-ci-script.sh'
     }
    }
  }

  // 消息通知: POST阶段当所有任务执行后触发
  post {
    // 企业微信
    always {
      qyWechatNotification aboutSend: true, failNotify: true, failSend: true, mentionedId: 'ALL', mentionedMobile: '', startBuild: true, successSend: true, unstableSend: true, webhookUrl: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c222f3fc-f645-440a-ad24-0ce8d9626fa0'
    }

    // 钉钉
    success {
      //当此Pipeline成功时打印消息 (注意此处的robot为您在Jenkins全局配置中设置钉钉的id值)
      echo 'success'
      dingtalk (
          robot: 'weiyigeek-1000',
          type: 'LINK',
          title: 'Jenkins 持续集成 - 任务名称 ${JOB_NAME}',
          text: [
              '项目构建成功',
              'Pipeline 流水线测试'
          ],
          messageUrl: 'http://www.weiyigeek.top',
          picUrl: 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2319834554,1372531032&fm=26&gp=0.jpg',
          atAll: true
      )
    }
  }
}

Step 2.上传修改的项目到Gitlab内部私有仓库中

代码语言:javascript
复制
$ git add .
$ git commit -m "v1.10 pipeline script for SCM"
# [master 3f9b6e8] v1.10 pipeline
#  2 files changed, 26 insertions(+), 1 deletion(-)
#  create mode 100644 Jenkinsfile
$ git push
# To http://gitlab.weiyigeek.top/ci-cd/java-maven.git
#    0f50b10..3f9b6e8  master -> master
$ git tag -a "v1.10" -m "v1.10 Pipelinescript for SCM "
$ git push origin v1.10
# To http://gitlab.weiyigeek.top/ci-cd/java-maven.git
#  * [new tag]         v1.10 -> v1.10

Step 3.任务项目流水线设置 -> 选择 Pipeline script from SCM -> git -> 输入 Repository URL 和 Credentials -> 指定分支 Branches to build (以及Jenkinsfile 拉取的文件名实现自动构建集成)

WeiyiGeek.Pipeline script from SCM
WeiyiGeek.Pipeline script from SCM

WeiyiGeek.Pipeline script from SCM

  • Step 4.项目构建参数输入 -> v1.10 | deploy -> 进行构建 -> 查看流水线
WeiyiGeek.PIPE 流水线
WeiyiGeek.PIPE 流水线

WeiyiGeek.PIPE 流水线

Step 5.查看部署结果http://10.10.107.202:30089/结果正常;

代码语言:javascript
复制
Maven - Hello World - v1.10 - Pipeline script for SCM

访问时间: Tue Jan 26 2021 14:54:35 GMT+0800 (中国标准时间)

Server : Apache Tomcat/8.5.61 | 10.244.1.217

Client : 10.244.0.0 | 10.244.0.0

Document_Root : /usr/local/tomcat/webapps/ROOT/

URL : 10.10.107.202/index.jsp

(3) Jenkins pipeline 之 邮件(Email)发信管理

描述: 如果利用 Freestyle 的原生Job我们可以很好的进行Job邮件发信,而在与 Jenkins 流水线中需要Extended E-mail Notification的方式进行实现(此处只是简单说明建议采用钉钉或者企业微信的方式更加及时方便);

下面提供两种格式进行参考:

(1) Scripted Pipeline

代码语言:javascript
复制
node ("master"){
    parameters {string(name:'Jenkins',defaultValue:'Hello',description:'How should I greet the world')}
    echo  "${params.nane} 你好!"
    // gitlab 流水线通知
    gitlabCommitStatus {
        stage('第1步拉代码'){
            echo "拉代码"
            git credentialsId: '03fd8295-c536-4871-9794-1c37394676e0', url: 'git@gitlab.weiyigeek.top:weiyigeek/ops.git'
        }
        stage('第2步编译'){
            echo "编译"
           // sh "source /etc/profile && /usr/local/maven/bin/mvn clean compile"
        }
        stage('第3步打包'){
            echo "打包,有一个mail模块是系统级别的,需要sudo"
            // sh "sudo /usr/local/maven/bin/mvn package"
            // echo "完成后 修改一下权限,否则下一次麻烦"
            // sh "sudo chown -R  jenkins: ."
            // sh "find -name '*SNAPSHOT.jar' "
        }
        stage('第四步单元测试'){
            echo "单元测试"
            //sh "sudo /usr/local/maven/bin/mvn test"
        }
        stage("放到下载服务器上"){
            echo "发送文件"
          //  sh "sudo cp ./account-email/target/account-email-1.0.0-SNAPSHOT.jar /home/admin/webserver/html/download && sudo chown  -R admin: /home/admin/webserver/html/download"
        }
    }
    stage("发送邮件"){
      def git_url = 'git@gitlab.weiyigeek.top:weiyigeek/ops.git'
            def branch = 'dev'
            def username = 'Jenkins'
            echo "Hello Mr.${username}"
            echo "GIT路径: ${git_url}"
  
            echo "发送邮件"
            emailext body: """
            <!DOCTYPE html>
            <html>
            <head>
            <meta charset="UTF-8">
            <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
            </head>
            <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
                <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
                    <tr>
                        <td>(本邮件由程序自动下发,请勿回复!)</td>
                    </tr>
                    <tr>
                        <td>
                            <h2><font color="#FF0000">构建结果 - ${BUILD_STATUS}</font></h2>
                        </td>
                    </tr>
                    <tr>
                        <td><br />
                            <b><font color="#0B610B">构建信息</font></b>
                            <hr size="2" width="100%" align="center" />
                        </td>
                    </tr>
                    <tr><a href="${PROJECT_URL}">${PROJECT_URL}</a>
                        <td>
                            <ul>
                                <li>项目名称:${PROJECT_NAME}</li>
                                <li>GIT路径:<a href="git@gitlab.weiyigeek.top:weiyigeek/ops.git">git@gitlab.weiyigeek.top:weiyigeek/ops.git</a></li>   
                                <li>GIT分支: master</li>
                                <li>构建编号:${BUILD_NUMBER}</li>                    
                                <li>触发原因:${CAUSE}</li>   
                                <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                            </ul>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <b><font color="#0B610B">变更信息:</font></b>
                           <hr size="2" width="100%" align="center" />
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <ul>
                                <li>上次构建成功后变化 :  ${CHANGES_SINCE_LAST_SUCCESS}</a></li>
                            </ul>    
                        </td>
                    </tr>
             <tr>
                        <td>
                            <ul>
                                <li>上次构建不稳定后变化 :  ${CHANGES_SINCE_LAST_UNSTABLE}</a></li>
                            </ul>    
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <ul>
                                <li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
                            </ul>    
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <ul>
                                <li>变更集:${JELLY_SCRIPT,template="html"}</a></li>
                            </ul>    
                        </td>
                    </tr>
                    <!--
                    <tr>
                        <td>
                            <b><font color="#0B610B">Failed Test Results</font></b>
                            <hr size="2" width="100%" align="center" />
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">${FAILED_TESTS}</pre>
                            <br />
                        </td>
                    </tr>
                    
                    <tr>
                        <td>
                            <b><font color="#0B610B">构建日志 (最后 100行):</font></b>
                            <hr size="2" width="100%" align="center" />
                        </td>
                    </tr>-->
                    <!-- <tr>
                        <td>Test Logs (if test has ran): <a
                            href="${PROJECT_URL}ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip">${PROJECT_URL}/ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip</a>
                            <br />
                        <br />
                        </td>
                    </tr> -->
                    <!--
                    <tr>
                        <td>
                            <textarea cols="80" rows="30" readonly="readonly" style="font-family: Courier New">${BUILD_LOG, maxLines=100,escapeHtml=true}</textarea>
                        </td>
                    </tr>-->
                    <hr size="2" width="100%" align="center" />
             
                </table>
             
             
            </body>
            </html>
    """, subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', to: 'master@weiyigeek.top'
    }
}

(2) Declarative Pipeline

代码语言:javascript
复制
pipeline{
  agent{label 'master'}
  environment {
    git_url = 'git@gitlab.weiyigeek.top:weiyigeek/ops.git'
    git_key = '03fd8295-c536-4871-9794-1c37394676e0'
    git_branch = 'master'
  }

  stages {
    stage('下载代码') {
      steps {
        git branch: "${git_branch}",credentialsId: "${git_key}", url: "${env.git_url}"
      }
    }
  }
    
  post { 
    //always部分 pipeline运行结果为任何状态都运行
    always{
      script{
        emailext body: 
          '''  <!DOCTYPE html>
          <html>
          <head>
          <meta charset="UTF-8">
          <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
          </head>
          <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
              <table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
                  <tr>
                      <td>(本邮件由程序自动下发,请勿回复!)</td>
                  </tr>
                  <tr>
                      <td>
                          <h2><font color="#FF0000">构建结果 - ${BUILD_STATUS}</font></h2>
                      </td>
                  </tr>
                  <tr>
                      <td><br />
                          <b><font color="#0B610B">构建信息</font></b>
                          <hr size="2" width="100%" align="center" />
                      </td>
                  </tr>
                  <tr><a href="${PROJECT_URL}">${PROJECT_URL}</a>
                      <td>
                          <ul>
                              <li>项目名称:${PROJECT_NAME}</li>
                              <li>GIT路径:<a href="git@gitlab.weiyigeek.top:weiyigeek/ops.git">git@gitlab.weiyigeek.top:weiyigeek/ops.git</a></li>   
                              <li>GIT分支: master</li>
                              <li>构建编号:${BUILD_NUMBER}</li>                    
                              <li>触发原因:${CAUSE}</li>   
                              <li>构建日志:<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                          </ul>
                      </td>
                  </tr>
                  <tr>
                      <td>
                          <b><font color="#0B610B">变更信息:</font></b>
                          <hr size="2" width="100%" align="center" />
                      </td>
                  </tr>
                  <tr>
                      <td>
                          <ul>
                              <li>上次构建成功后变化 :  ${CHANGES_SINCE_LAST_SUCCESS}</a></li>
                          </ul>    
                      </td>
                  </tr>
            <tr>
                      <td>
                          <ul>
                              <li>上次构建不稳定后变化 :  ${CHANGES_SINCE_LAST_UNSTABLE}</a></li>
                          </ul>    
                      </td>
                  </tr>
                  <tr>
                      <td>
                          <ul>
                              <li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
                          </ul>    
                      </td>
                  </tr>
                  <tr>
                      <td>
                          <ul>
                              <li>变更集:${JELLY_SCRIPT,template="html"}</a></li>
                          </ul>    
                      </td>
                  </tr>
                  <!--
                  <tr>
                      <td>
                          <b><font color="#0B610B">Failed Test Results</font></b>
                          <hr size="2" width="100%" align="center" />
                      </td>
                  </tr>
                  <tr>
                      <td>
                          <pre style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
                          <br />
                      </td>
                  </tr>
                  
                  <tr>
                      <td>
                          <b><font color="#0B610B">构建日志 (最后 100行):</font></b>
                          <hr size="2" width="100%" align="center" />
                      </td>
                  </tr>-->
                  <!-- <tr>
                      <td>Test Logs (if test has ran): <a
                          href="${PROJECT_URL}ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip">${PROJECT_URL}/ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip</a>
                          <br />
                      <br />
                      </td>
                  </tr> -->
                  <!--
                  <tr>
                      <td>
                          <textarea cols="80" rows="30" readonly="readonly" style="font-family: Courier New">${BUILD_LOG, maxLines=100,escapeHtml=true}</textarea>
                      </td>
                  </tr>-->
                  <hr size="2" width="100%" align="center" />
            
              </table>
            
            
          </body>
          </html>
''', 
              subject: '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', to: 'master@weiyigeek.top'
          }
          }

          success {
              //当此Pipeline成功时打印消息
              echo 'success'
          }
          failure {
              //当此Pipeline失败时打印消息
              echo 'failure'
          }
          unstable {
              //当此Pipeline 为不稳定时打印消息
              echo 'unstable'     
          }
          aborted {
              //当此Pipeline 终止时打印消息
              echo 'aborted'  
          }
          changed {
              //当pipeline的状态与上一次build状态不同时打印消息
              echo 'changed'          
          } 
  }
}

0x02 进阶实践

(1) Sonarqube 代码质量检测之 Pipeline Script from SCM

实验需求: 拉取代码并指定Tag、采用sonarqube进行代码质量检测并进行构建

Tips : sonarQube 是sonarQube扫描插件工具, 该工具除了前面直接下载二进制执行文件到Jenkins种(登陆jenkins页面–>系统管理–>全局工具配置)进行配置; 还可以通过自动化构建工具安装,不管是maven项目还是gradle项目都提供了安装sonarQube扫描工具的插件。;

代码语言:javascript
复制
plugins {
  id "org.sonarqube" version "2.7"
}

实验流程:

Step 0.按照前面的流程在Jenkins中下载并配置好SonarQube并且在SonarQube中进行URL设置

代码语言:javascript
复制
# 关键项:
# (1) Sonarqube 通用配置项
Server base URL : http://sonar.weiyigeek.top:9000/

# (2) Dashboard -> 全局配置 -> SonarQube servers 
# 环境变量允许将SonarQube服务器配置注入构建环境变量
Server URL : http://sonar.weiyigeek.top:9000
Server authentication token : 可以参照下面的Step2步骤
WeiyiGeek.Jenkins && Sonarqube
WeiyiGeek.Jenkins && Sonarqube

WeiyiGeek.Jenkins && Sonarqube

Step 1.并生成项目标识符名称(somarqube-test)并获取令牌somarqube-test: 4354fc222bee3c2bad2d812b087dabab943a7ab0

Step 2.将该Token添加到Jenkins凭据之中Dashboard -> 凭据 -> 系统 -> 全局凭据 (unrestricted)选择Secret类型文本 -> Secret(输入上面的Token) -> 描述:somarqube-test-api;

代码语言:javascript
复制
Secret text	6810ea0d-e76a-40cf-9373-5040ed6b5456	somarqube-test-api	Secret text	somarqube-test-api
WeiyiGeek.somarqube-test-api
WeiyiGeek.somarqube-test-api

WeiyiGeek.somarqube-test-api

  • Step 3.创建一个流水线项目somarqube-test-pipeline -> 编写Pipeline Script脚本如下(非常值得注意涵盖的知识较多)
代码语言:javascript
复制
pipeline {
  agent any
  /* 该块中的变量将写入到Linux环境变量之中作为全局变量,在shell可通过变量名访问,而在script pipeline脚本中通过env.变量名称访问. */
  environment {
    GITLAB_URL = 'git@gitlab.weiyigeek.top:ci-cd/java-maven.git'
    // 代码质量检测项目名称
    SONARQUBE_PROJECTKEY = 'somarqube-test';
    // 代码质量检测反馈超时时间
    SONARQUBE_TIMEOUT = '10';
    // 版本号
    //RELEASE_VERSION="v1.1"
    // 默认操作方式
    //PREJECT_OPERATION="deploy"
  }

  /* 全局参数, 在shell可通过变量名访问,而在script pipeline脚本中通过params.参数名称访问.  */
  parameters {
    // Jenkins -> 原生 Build With Parameters 支持 (BuleOcean不支持gitParameter) 
  //   gitParameter name: 'RELEASE_VERSION', 
  //                    type: 'PT_BRANCH_TAG',
  //                    branchFilter: 'origin/(.*)',
  //                    defaultValue: 'master',
  //                    selectedValue: 'DEFAULT',
  //                    sortMode: 'DESCENDING_SMART',
  // 				 description: 'Message: 请选择部署的Tags版本?'
    choice(name: 'SONARQUBE', choices: ['False','True'],description: 'Message: 是否进行代码质量检测?')	
    string(name: 'RELEASE_VERSION', defaultValue: "", description: 'Message: 请选择部署的Tags版本?')
    choice(name: 'PREJECT_OPERATION', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message: 选择项目操作方式?')
  }

  stages {
    stage ('代码拉取') {
      //注意: 此处得input不能包含在steps中并且只有局部stage块中可用调用,调用方式 ${RELEASE_VERSION} ${PREJECT_OPERATION} 
      // input {
      //   message "Title : ${JOB_NAME} 项目构建参数"
      //   ok "完成提交"
      //   parameters {
      //     string(name: 'RELEASE_VERSION', defaultValue: '', description: 'Message: 请选择部署的Tags版本?')
      //     choice(name: 'PREJECT_OPERATION', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message: 选择项目操作方式?')
      //   }
      // }
      steps {
        // (1) git项目拉取
        git branch: "${params.RELEASE_VERSION}", credentialsId: 'b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f', url: "${env.GITLAB_URL}"

        // (2) 超时时间设置 5 分钟
        timeout(time: 1, unit: 'MINUTES') {
          script {
              // (3) 存储可用版本
              def RELEASE=sh label: 'release',returnStdout: true, script: """\
              git tag -l --column | tr -d ' '  > tag ;
              export a="\$(sed "s#v#, v#g" tag)'";
              echo [\${a#,*}]
              """

              // 由于此处是groovy的变量此处得input通过script块包含只有局部stage块中可用调用(故此处不采用)
              // (4) 定义操作变量(RELEASE_VERSION 与 PREJECT_OPERATION) 注意此处无法影响shell中的变量
              //def RELEASE_VERSION=input message: "${JOB_NAME} 项目版本:\n ${RELEASE}", ok: '完成提交', parameters: [ string(name: 'RELEASE_VERSION', description: 'Message: 请选择部署的Tags版本?')];
              //def PREJECT_OPERATION=input message: "${JOB_NAME} 项目构建参数", ok: '完成提交', parameters: [choice(name: 'PREJECT_OPERATION', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message: 选择项目操作方式?')];
           
              // (5) 输出变量与操作
              // 例如: RELEASE_VERSION: v1.11 , PREJECT_OPERATION: redeploy. SONARQUBE: True
              echo "RELEASE_VERSION: ${RELEASE_VERSION} , PREJECT_OPERATION: ${PREJECT_OPERATION}. SONARQUBE: ${params.SONARQUBE}"
        
              // (6) 切换分支版本(其实上面有了branch: "${params.RELEASE_VERSION}"此处显得多余)
              sh label: 'checkout_version', script: '[ -n "${RELEASE_VERSION}" ] &&  git checkout ${RELEASE_VERSION} || { echo -e "切换至指定的tag的版本 tag:${RELEASE_VERSION} 不存在或为空,请检查输入的tag!" && exit 1; }'
          }
        }
     }
   }
   
    stage ('代码检测') {
      // (7) 判断是否进行代码质量检测
      when {
        // expression { return params.SONARQUBE == "True" }
        anyOf {
          environment name: 'SONARQUBE', value: 'True'
          environment name: 'PREJECT_OPERATION', value: 'deploy'
          environment name: 'PREJECT_OPERATION', value: 'redeploy'
        }
      }

      steps {
        script {
        // (8) Tool 后的名称一定是对应全局工具配置中sonar扫描器的名字进行代码质量检测
        def sonarqubeScanner = tool 'sonarqubescanner';
        withSonarQubeEnv(credentialsId: '6810ea0d-e76a-40cf-9373-5040ed6b5456') {
          // 注意:可以将sonarQube的属性定义在这里,也可以定义在项目文件中然后在这里引用配置文件
          sh "${sonarqubeScanner}/bin/sonar-scanner " + 
                "-Dsonar.projectName=${JOB_NAME} " + 
                "-Dsonar.projectKey=${SONARQUBE_PROJECTKEY} " + 
                "-Dsonar.projectVersion=${RELEASE_VERSION} " + 
                "-Dsonar.sourceEncoding=utf8  " + 
                "-Dsonar.sources=.  " + 
                "-Dsonar.language=java  " + 
                "-Dsonar.java.binaries=."
        }
        
        // (9) 暂停10s等待sonarqube扫描反馈
        sh "sleep ${SONARQUBE_TIMEOUT}"
        // 方式1
        // timeout(1) {
        //     def qg = waitForQualityGate() 
        //     if (qg.status != 'OK') {
        //         error "未通过Sonarqube的代码质量阈检查,请及时修改!failure: ${qg.status}"
        //     } else {
        //         echo "successful"
        //     }
        // } 
        
        // 方式2
        timeout(time: 1, unit: 'MINUTES') {
            waitForQualityGate abortPipeline: true
          }
        }
      }
    }
    
    // (10) 项目构建打包处理
    stage ("项目构建") {
      steps {
       sh label: 'build', script: '/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true '
     }
    }

    // (11) 进行开发测试部署
    stage ("开发测试部署") {
      steps {
        echo "后续添加......"
      }
    }
  }
  
  // (12) 全部阶段完成后执行进行工作空间的清理以及消息通知;
  post {
    always {
        echo 'One way or another, I have finished'
        deleteDir() /* clean up our workspace */
    }
    success {
        echo 'I succeeeded!'
    }
    unstable {
        echo 'I am unstable :/'
    }
    failure {
        echo 'I failed :('
    }
    changed {
        echo 'Things were different before...'
    }
  }
}

Step 4.项目运行以及代码拉取结果反馈

代码语言:javascript
复制
# git@gitlab.weiyigeek.top:ci-cd/java-maven.git— Print Message <1s
# Git  4s
# 查看可用标签
# git tag -l --column | tr -d ' ' > tag ; export a="$(sed "s#v#, v#g" tag)'"; echo [${a#,*}] — release<1s
# RELEASE_VERSION: v1.11 , PREJECT_OPERATION: deploy. SONARQUBE: True— Print Message <1s
# [ -n "${RELEASE_VERSION}" ] && git checkout ${RELEASE_VERSION} || { echo -e "切换至指定的tag的版本 tag:${RELEASE_VERSION} 不存在或为空,请检查输入的tag!" && exit 1; }— checkout_version  <1s
WeiyiGeek.项目运行以及代码拉取
WeiyiGeek.项目运行以及代码拉取

WeiyiGeek.项目运行以及代码拉取

Step 5.代码检测阶段查看(重点), SonarQube analysis api 接口URL(http://sonar.weiyigeek.top:9000/api/ce/task?id=AXdd7NO4mUDNtrevcJJD)

代码语言:javascript
复制
# sonarqubescanner— Use a tool from a predefined Tool Installation <1s
# /usr/local/sonar//bin/sonar-scanner -Dsonar.projectName=somarqube-test-pipeline -Dsonar.projectKey=somarqube-test -Dsonar.projectVersion=v1.11 -Dsonar.sourceEncoding=utf8 -Dsonar.sources=. -Dsonar.language=java -Dsonar.java.binaries=.— Shell Script7s
# sleep 10 — Shell Script10s
# true— Wait for SonarQube analysis to be completed and return quality gate status  <1s
WeiyiGeek.代码检测阶段查
WeiyiGeek.代码检测阶段查

WeiyiGeek.代码检测阶段查

  • Step 6.综合效果
WeiyiGeek.最终效果
WeiyiGeek.最终效果

WeiyiGeek.最终效果

(2) Gitlab 自动触发构建之 Pipeline Script from SCM

实验需求:Gitlab 上传自动触发Jenkins构建并通过BlueOcan进行控制构建, 以及与 Gitlab 流水线状态同步

实验流程:

Step 1.此处假设您已安装配置Gitlab Authentication plugin、GitLab Plugin这两个插件

Step 2.到 Gitlab私有仓库中进行生成项目API Access Token -> 用户设置 -> 访问令牌 -> 输入您的应用程序的名称 -> 选择相应到期时间 -> 范围: 授予对API的完全读/写访问权,包括所有组和项目、容器注册表和包注册表 -> 然后创建个人访问令牌;

Step 3.得到api Token(kWL_9Fw_nvbxTkpDb9X6)后在Jenkins中添加全局凭据 -> Dashboard -> 凭据 -> 系统 -> 全局凭据 (unrestricted) -> 选择凭据类型为Gitlab API Token -> 然后确定即可 -> 他会自动生成一个类似于UUID的一个字符串

代码语言:javascript
复制
# Value
f49076a8-11e4-4351-a88a-143cfab6555b	GitLab API token (gitlab_admin_api)	GitLab API token	gitlab_admin
WeiyiGeek.Gitlab-API-Token
WeiyiGeek.Gitlab-API-Token

WeiyiGeek.Gitlab-API-Token

Step 4.或者直接在全局配置的 Gitlab -> Enable authentication for ‘/project’ end-point -> 应用保存;

WeiyiGeek.Gitlab-Token-配置
WeiyiGeek.Gitlab-Token-配置

WeiyiGeek.Gitlab-Token-配置

  • Step 5.在Dashboard -> Gitlab-Pipeline Job 中 -> 构建触发器 -> 勾选Build when a change is pushed to GitLab. -> 重新生成打开的合并请求为On push to source branch -> Comment (regex) for triggering a build 可以在提交Jenkins build字符串进行触发构建编译;
  • Step 6.Jenkins 生成 Api Token -> 面板 _> 用户设置 -> API Token 生成 (APl令牌提供了一种进行经过身份验证的CLI或REST API调用的方法。注意每六个月需要重新生成一次) 11112e147020668570e571fa438439cc60 Tips: 每次重新启动Jenkins时,未使用的遗留令牌的创建日期将被重置,这意味着日期可能不准确。
WeiyiGeek.Jenkins-API-Token
WeiyiGeek.Jenkins-API-Token

WeiyiGeek.Jenkins-API-Token

Step 7.在Gitlab -> java-maven 项目 -> 设置 -> WebHooks -> 地址为是前面Build when a change is pushed to GitLab. GitLab webhook URL中的地址 http://jenkins.weiyigeek.top:8080/project/Gitlab-Pipeline-> 输入 Secret Token -> 选择Push events Trigger -> add Webhook -> 最后进行选择push events测试 -> Hook executed successfully: HTTP 200

注意事项:

代码语言:javascript
复制
#补充说明
Gitlab Project -> helloworld -> Webhook设置 

# Gitlab 设置
URL :Jenkins Job
Secret Token
Trigger
  Push events  : This URL will be triggered by a push to the repository  (每次提交都将触发-如不需要则不要勾选即可)
  Tag push events : This URL will be triggered when a new tag is pushed to the repository  (非常建议设置tag后才会触发) - 一般开启该事件选项后不建议开启Push evnts
  Comments : This URL will be triggered when someone adds a comment (评论触发)

# 成功 > 控制台输出 #32
# 2021-2-23 上午11:38 CST
# Started by GitLab push by Gitlab WeiyiGeek
WeiyiGeek.GitLab webhook URL
WeiyiGeek.GitLab webhook URL

WeiyiGeek.GitLab webhook URL

Tips : 此处需要设置允许来自钩子和服务的对本地网络的请求。 Tips : 注意请根据您的Jenkins站点启用SSL(建议内网也需要注意的)

  • Step 8.此处先使用Pipeine Script脚本然后应用保存然后上传v1.11版本到Gitlab,查看是否自动触发Build;
代码语言:javascript
复制
pipeline {
  agent any
  // 全局选项
  options {
    gitLabConnection('Private-Gitlab')
    gitlabBuilds(builds: ['代码拉取', '代码检测', '项目构建','测试部署','成品归档'])
    timeout
  }
  
  environment {
    GITLAB_URL = 'git@gitlab.weiyigeek.top:ci-cd/java-maven.git'
    // 代码质量检测项目名称
    SONARQUBE_PROJECTKEY = 'Hello-World';
    // 代码质量检测反馈超时时间
    SONARQUBE_TIMEOUT = '10';
    // 版本号
    //RELEASE_VERSION="v1.1"
    // 默认操作方式
    //PREJECT_OPERATION="deploy"
    // 企业微信WebHookURL
    QYWX_WEBHOOK = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c222f3fc-f645-440a-ad24-0ce8d9626fa0'
  }

  /* 全局参数, 在shell可通过变量名访问,而在script pipeline脚本中通过params.参数名称访问.  */
  parameters {
    string(name: 'RELEASE_VERSION', defaultValue: "master", description: 'Message: 请选择部署的Tags版本?',trim: 'True')
    choice(name: 'PREJECT_OPERATION', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message: 选择项目操作方式?')
    choice(name: 'SONARQUBE', choices: ['False','True'],description: 'Message: 是否进行代码质量检测?')
  }

   triggers {
        gitlab(triggerOnPush: true, triggerOnMergeRequest: true, branchFilterType: 'All')
    } 

  stages {
    stage ('代码拉取') {
      steps {
        // (1) git项目拉取
        echo "${env.GITLAB_URL} -- ${params.RELEASE_VERSION}"
        // (2) 超时时间设置 5 分钟
        timeout(time: 1, unit: 'MINUTES') {
          script {
              try { 
                          echo "${env.GITLAB_URL} -- ${params.RELEASE_VERSION}"

                // 方式1: git branch: 'v1.11', credentialsId: '43287e62-ce5b-489a-9c11-cedf38e16e92', url: "${env.GITLAB_URL}"
                // 方式2:
                checkout([$class: 'GitSCM', branches: [[name: "${params.RELEASE_VERSION}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f', url: "${env.GITLAB_URL}"]]])
                updateGitlabCommitStatus name: '代码拉取', state: 'success'
              } catch(Exception err) {
                updateGitlabCommitStatus name: '代码拉取', state: 'failed'
                // 显示错误信息但还是会进行下一阶段操作
                echo err.toString()    /* hudson.AbortException: Couldn't find any revision to build. Verify the repository and branch configuration for this job. */
                unstable '拉取代码失败'
                // 构建停止
                error "[-Error] : 代码拉取失败\n [-Msg] : ${err.getMessage()} "

              } 
              // (3) 存储可用版本
              def RELEASE=sh label: 'release',returnStdout: true, script: """\
              git tag -l --column | tr -d ' '  > tag ;
              export a="\$(sed "s#v#, v#g" tag)'";
              echo [\${a#,*}]
              """

              // (4) 输出变量与操作
              // 例如: RELEASE_VERSION: v1.11 , PREJECT_OPERATION: redeploy. SONARQUBE: True
              echo "RELEASE_VERSION: ${params.RELEASE_VERSION} , PREJECT_OPERATION: ${params.PREJECT_OPERATION}. SONARQUBE: ${params.SONARQUBE}"
        
              // (5) 切换数据库版本
              //sh label: 'checkout_version', script: '[ -n "${RELEASE_VERSION}" ] &&  git checkout ${RELEASE_VERSION} || { echo -e "切换至指定的tag的版本 tag:${RELEASE_VERSION} 不存在或为空,请检查输入的tag!" && exit 1; }'
              sh "git branch"
          }
        }
     }
   }
   
    stage ('代码检测') {
      // (6) 判断是否进行代码质量检测
      when {
        expression { return params.PREJECT_OPERATION != "rollback" }
        anyOf {
          environment name: 'SONARQUBE', value: 'True'
          environment name: 'PREJECT_OPERATION', value: 'deploy'
          environment name: 'PREJECT_OPERATION', value: 'redeploy'
        }
      }

      steps {
        script {
            
        // (7) Tool 后的名称一定是对应全局工具配置中sonar扫描器的名字进行代码质量检测
        def sonarqubeScanner = tool 'sonarqubescanner';
        withSonarQubeEnv(credentialsId: '6810ea0d-e76a-40cf-9373-5040ed6b5456') {
          // 注意:可以将sonarQube的属性定义在这里,也可以定义在项目文件中然后在这里引用配置文件
          sh "${sonarqubeScanner}/bin/sonar-scanner " + 
                "-Dsonar.projectName=${JOB_NAME} " + 
                "-Dsonar.projectKey=${SONARQUBE_PROJECTKEY} " + 
                "-Dsonar.projectVersion=${RELEASE_VERSION} " + 
                "-Dsonar.sourceEncoding=utf8  " + 
                "-Dsonar.sources=.  " + 
                "-Dsonar.language=java  " + 
                "-Dsonar.java.binaries=."
        }
        
        // (8) 暂停10s等待sonarqube扫描反馈
        sleep time: "${env.SONARQUBE_TIMEOUT}", unit: 'NANOSECONDS'
        sh "sleep ${SONARQUBE_TIMEOUT}"
        // 方式1
        // timeout(1) {
        //     def qg = waitForQualityGate() 
        //     if (qg.status != 'OK') {
        //         error "未通过Sonarqube的代码质量阈检查,请及时修改!failure: ${qg.status}"
        //     } else {
        //         echo "successful"
        //     }
        // } 
        try {
        // 方式2
        timeout(time: 1, unit: 'MINUTES') {
          waitForQualityGate abortPipeline: true
        }

        updateGitlabCommitStatus name: '代码检测', state: 'success'
        
        
        } catch(Exception err) {
           updateGitlabCommitStatus name: '代码检测', state: 'failed'
            // 显示错误信息但还是会进行下一阶段操作
            unstable '代码检测失败'
        }
        }
      }
    }
    
    // (10) 项目构建打包处理
    stage ("项目构建") {
         when {
         expression { return params.PREJECT_OPERATION != "rollback" }
         }
      steps {
           gitlabCommitStatus(connection: gitLabConnection('Private-Gitlab'),name: "项目构建") {
              sh script: '/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true'
           }
           
     }
    }

    // (11) 进行开发测试部署
    stage ("测试部署") {
      steps {
        script {
            try {
                sh label: 'deploy', script: '/tmp/script/jenkins-pipeline-gitlab-k8s.sh'
                updateGitlabCommitStatus name: '测试部署', state: 'success'
            }catch(Exception err) {
                echo err.toString()    /* hudson.AbortException: Couldn't find any revision to build. Verify the repository and branch configuration for this job. */
                unstable '部署失败'
                updateGitlabCommitStatus name: '测试部署', state: 'failed'

                // 构建停止
                error "[-Error] : 测试部署失败\n [-Msg] : ${err.getMessage()} "
            }
            
        }
      }
    }
    
    stage('成品归档') {
    steps {
       script {
         try {
            archiveArtifacts artifacts: "target/*.war",fingerprint: true, followSymlinks: false, onlyIfSuccessful: true
            updateGitlabCommitStatus name: '成品归档', state: 'success'
         } catch (Exception err) {
            updateGitlabCommitStatus name: '成品归档', state: 'failed'
            echo err.toString()    /* hudson.AbortException: Couldn't find any revision to build. Verify the repository and branch configuration for this job. */
        
         }
       }
    }
    }
  }
  


  // (12) POST阶段当所有任务执行后触发进行工作空间的清理以及消息通知;
  post {
    always {
      echo 'One way or another, I have finished'
      qyWechatNotification aboutSend: true, failNotify: true, failSend: true, mentionedMobile: '', startBuild: true, successSend: true, unstableSend: true, webhookUrl: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=c222f3fc-f645-440a-ad24-0ce8d9626fa0'
      deleteDir()  /* clean up our workspace */
        
    }
    success {
      echo 'I succeeeded!'
    }
    unstable {
      echo 'I am unstable - 不稳定 :/'
    }
    failure {
      echo 'I failed :('
    }
    changed {
      echo 'Things were different before - 以前的情况不一样...'
    }
  }
}

/tmp/script/jenkins-pipeline-gitlab-k8s.sh

代码语言:javascript
复制
#!/bin/bash
# Description: Jenkins CI & Kubernetes & Gitlab -> Deploy or Rollback or Redeploy Java Maven Project
DATE=$(date +%Y%m%d-%H%M%S)
WAR_PATH="/nfs/data4/war"
WEBROOT_PATH="/nfs/data4/webapps"
WEB_DIR="${JOB_NAME}-${DATE}-${RELEASE_VERSION}"
WAR_DIR=" ${WAR_PATH}/${WEB_DIR}"
WAR_NAME="${WEB_DIR}.war"
K8S_MATER="WeiyiGeek@10.10.107.202"
K8S_MATER_PORT="20211"
echo "${RELEASE_VERSION}  --------------- ${PREJECT_OPERATION}"


# 部署
deploy () {
  # 1.上传Maven打包的war包到master之中
  scp -P ${K8S_MATER_PORT} ${WORKSPACE}/target/*.war WeiyiGeek@10.10.107.202:${WAR_PATH}/${WAR_NAME}

  # 2.解压&软链接
  ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "unzip ${WAR_PATH}/${WAR_NAME} -d ${WAR_DIR} && \
                                         rm -rf ${WEBROOT_PATH} && \
                                         ln -s ${WAR_PATH}/${WEB_DIR} ${WEBROOT_PATH} && \
                                         kubectl delete pod -l app=java-maven"
}

# 回退
rollback () {
  History_Version=$(ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "find ${WAR_PATH} -maxdepth 1 -type d -name ${JOB_NAME}-*-${RELEASE_VERSION}")
  ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "rm -rf ${WEBROOT_PATH} && \
                                         ln -s ${History_Version} ${WEBROOT_PATH} && \
                                         kubectl delete pod -l app=java-maven"
}


# 重部署
redeploy () {
  # 如果是以前部署过则删除以前部署的项目目录(包括多个文件夹)否则重新部署;
  if [[ "v${GIT_COMMIT}" = "v${GIT_PREVIOUS_SUCCESSFUL_COMMIT}" ]];then
    echo -e "曾经部署过 ${RELEASE_VERSION} 版本,现在正在重新部署!"
    $(ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "find ${WAR_PATH} -d -maxdepth 1 -type d -name ${JOB_NAME}-*-${RELEASE_VERSION} && find ${WAR_PATH} -d -maxdepth 1 -type f -name ${JOB_NAME}-*-${RELEASE_VERSION}.war")
    # ssh -p ${K8S_MATER_PORT} ${K8S_MATER} "rm -rf ${History_Version}"
  fi
  # 物理如何都要重新部署
  deploy
}

# 部署 & 回退 入口(坑-==两边没有空格)
if [[ "${PREJECT_OPERATION}" = "deploy" ]]; then
  # 坑 (防止字符串为空)
#  if [[ "v${GIT_COMMIT}" = "v${GIT_PREVIOUS_SUCCESSFUL_COMMIT}" ]];then
 #   echo -e "您已经部署过 ${RELEASE_VERSION} 版本"
 #   exit 1
 # else
    deploy
 # fi
elif [[ "${PREJECT_OPERATION}" = "rollback" ]];then
  rollback
elif [[ "${PREJECT_OPERATION}" = "redeploy" ]];then
  redeploy
else
  echo -e "无任何操作!停止执行脚本"
  exit 127
fi

Step 9.功能分析之Git与Gitlab拉取指定分支并切换分支

代码语言:javascript
复制
#在“源代码管理”部分中:
1. 单击Git

2. 输入您的存储库URL,例如git@your.gitlab.server:gitlab_group/gitlab_project.git
 #在高级设置,设置名称,以origin和的Refspec到+refs/heads/*:refs/remotes/origin/* +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*

3. 在“分支说明符”中输入:
# 对于单存储库工作流: origin/${gitlabSourceBranch}
# 对于分叉的存储库工作流: merge-requests/${gitlabMergeRequestIid}

4.在其他行为中:
# 点击添加下拉按钮
# 从下拉列表中选择合并,然后再构建
# 将存储库名称设置为origin
# 将“分支”设置为合并为${gitlabTargetBranch}

# 补充:标签时构建
(1) 在GitLab Webhook配置中,添加“标签推送事件”
(2) 在“源代码管理”下的作业配置中:
  1.选择“高级...”并添加“ `+refs/tags/*:refs/remotes/origin/tags/*` ”作为参考规格
  2.您还可以使用“分支说明符”来指定需要构建的标签(例如“ refs / tags / $ {TAGNAME}”示例)

简单示例:

代码语言:javascript
复制
// 方式1.
git branch: "${params.RELEASE_VERSION}", credentialsId: 'b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f', url: "${env.GITLAB_URL}"
// git branch: 'v1.11', credentialsId: '43287e62-ce5b-489a-9c11-cedf38e16e92', url: 'git@gitlab.weiyigeek.top:ci-cd/java-maven.git'

//方式2.
checkout([$class: 'GitSCM', branches: [[name: "origin/${params.RELEASE_VERSION}"]], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'b4c8b4e9-2777-44a1-a1ed-e9dc21d37f4f', url: '${env.GITLAB_URL}']]])

Step 9.功能分析之 Jenkins 同步到 Gitlab 流水线之中,并且从Gitlab中可以直接进入Jenkins Job页面查看构建情况;

代码语言:javascript
复制
# 语法参考: 包含在 steps 块之中
gitlabCommitStatus(connection: gitLabConnection('Private-Gitlab'), name: '${JOB_NAME}') {
  sh label: 'build', script: '/usr/local/maven/bin/mvn clean package -Dmaven.test.skip=true'
}
WeiyiGeek.jenkins与Gitlab流水线
WeiyiGeek.jenkins与Gitlab流水线

WeiyiGeek.jenkins与Gitlab流水线

Step 10.功能分析之 Jenkins 中成品进行归档, 注意其路径为相对路径及其您生成的项目打包文件格式文件和Gitlab Relase 发布

代码语言:javascript
复制
# (1) 成品归档当前路径为 ${WORKSPACE} 变量路径;
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true, followSymlinks: false, onlyIfSuccessful: true # 对于war项目则'target/*war'

# (2) 获取归档成品的URL(注意为了后续不丢失建议采用专门的服务器进行存储或者在jenkins将此次Job编译进行完整留存)
http://jenkins.weiyigeek.top:8080/job/Gitlab-Pipeline/187/artifact/target/hello-world.war

# (3) 项目 -> 发布 (Release) -> 新建发布 -> 编写相关资源 -> 发布资源
# 推荐格式: https://host/namespace/project/releases/:release/downloads/:filepath
WeiyiGeek.Jenkins归档与Release发布
WeiyiGeek.Jenkins归档与Release发布

WeiyiGeek.Jenkins归档与Release发布

Tips : Gitlab 项目 Release 自动发布 GitLab CI 工具: https://gitlab.com/gitlab-org/release-cli/-/blob/master/docs/index.md#usage 后面有时间再扩充;

Step 11.同样访问我们的K8s部署的Pod查看是否部署成功URL: http://10.10.107.202:30089/;

代码语言:javascript
复制
Maven - Hello World - v1.13 - Declarative Pipeline jobs for Gitlab WebHook Trigger

访问时间: Tue Feb 02 2021 14:15:24 GMT+0800 (中国标准时间)

Server : Apache Tomcat/8.5.61 | 10.244.0.245

Client : 10.244.0.1 | 10.244.0.1

Document_Root : /usr/local/tomcat/webapps/ROOT/

URL : 10.10.107.202/index.jsp
WeiyiGeek.Jenkins & gitlab 自动触发
WeiyiGeek.Jenkins & gitlab 自动触发

WeiyiGeek.Jenkins & gitlab 自动触发


0x03 入坑与出坑

问题1.在BlueOcean中流水线使用的输入类型不支持。请使用 经典 Jenkins 参数化构建。 问题原因: 在BlueOcean中不支持选择下拉而只支持文本参数; 文本参数:

  • git_tags 默认值 描述信息
  • deploy_option 默认值(deploy 、rollback、redeploy) 描述信息(部署&回退&重部署)
WeiyiGeek.BlueOcean输入
WeiyiGeek.BlueOcean输入

WeiyiGeek.BlueOcean输入

问题2.添加Webhook测试时显示Hook execution failed: URL ‘http://jenkins.weiyigeek.top:8080/project/Gitlab-Pipeline' is blocked: Requests to the local network are not allowed 错误信息:

代码语言:javascript
复制
Hook execution failed: URL 'http://jenkins.weiyigeek.top:8080/project/Gitlab-Pipeline' is blocked: Requests to the local network are not allowed

解决办法: 允许来自钩子和服务的对本地网络的请求。

操作流程: 管理中心 -> 设置 -> 网络 -> 勾选 允许Webhook和服务对本地网络的请求 -> 然后输入 钩子和服务可以访问的本地IP地址和域名。

WeiyiGeek.外发请求设置
WeiyiGeek.外发请求设置

WeiyiGeek.外发请求设置

问题3.Jenkinsfile 编写过程中遇到的情况以及解决办法

1.字符串插值处理

代码语言:javascript
复制
#设置环境变量
environment {
  STATIC_VAR = "静态变量"
  def dynamic_var = ""
}

# 可选的步骤参数
parameters {
  string(name: 'RELEASE_VERSION', defaultValue: "master", description: 'Message: 请选择部署的Tags版本?', trim: 'True')
  choice(name: 'PREJECT_OPERATION', choices: ['deploy', 'rollback', 'redeploy'], description: 'Message: 选择项目操作方式?')
}

#使用环境变量
echo "${env.STATIC_VAR}"
echo "${params.PREJECT_OPERATION}"

#动态设置环境变量
dynamic_var = "动态设置环境变量"
println(dynamic_var)

2.凭据处理

代码语言:javascript
复制
// # Secret 文本,带密码的用户名,Secret 文件
withCredentials([string(credentialsId: 'ce228573-ad3d-40e8-a3bf-b9de510080db', variable: 'GITLAB_TOKEN')]) {
  echo GITLAB_TOKEN  # println(GITLAB_TOKEN)
}

// # ssh私钥密钥凭据类型
// # SSH User Private Key / Public
$ cat id_ed25519.pub | base64 -w 0
// c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUIinfozVnFFbyt1NmZXNExZeWN1bk9QKzBubnE3cWNJd3lBWXVtNUp1Qi8gbWFzdGVyQHdlaXlpZ2Vlay50b3AK
echo "c3NoLWVkMjU1MTkgQUFBQUMzTnphQzFsWkRJMU5URTVBQUFBSUIinfozVnFFbyt1NmZXNExZeWN1bk9QKzBubnE3cWNJd3lBWXVtNUp1Qi8gbWFzdGVyQHdlaXlpZ2Vlay50b3AK" | base64 -d
// ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB3a0sVqEo+u6fW4LYycunOP+0nnq7qcIwyAYum5JuB/ master@weiyigeek.top

script {
  withCredentials([
      sshUserPrivateKey(credentialsId: '1d4e61cb-5d59-4da8-813b-a5fb345770c9', keyFileVariable: 'keyFile', passphraseVariable: 'pass', usernameVariable: 'user'),
      string(credentialsId: '79a78423-e539-4b1f-a872-f0cf1dd3f9fa', variable: 'keyPub')
  ]) {
    // SSH User Private Key
    writeFile file: 'private.key', text: keyFile
    sh "cp \$(cat private.key) ~/.ssh/id_ed25519"
    
    // SSH User Public
    writeFile file: 'private.pub', text: keyPub
    sh "echo \$(cat private.pub) | base64 -d > ~/.ssh/id_ed25519.pub"

    //其他方式
    //sh "curl -s http://192.168.12.107:8080/id_ed25519.pub -o ~/.ssh/id_ed25519.pub"
  }  
}

// # Certificate
withCredentials([certificate(aliasVariable: 'aliase', credentialsId: '6795a628-97a9-4a18-8dcc-1c913e6901d4', keystoreVariable: 'private', passwordVariable: 'pass')]) {
  # // some block
}
WeiyiGeek.SSH密钥与公钥处理
WeiyiGeek.SSH密钥与公钥处理

WeiyiGeek.SSH密钥与公钥处理

3.额外处理

代码语言:javascript
复制
# 处理故障
try {
  sh script: "./test.sh"
  timeout(time: 1, unit: 'MINUTES') {
    waitForQualityGate abortPipeline: true
  }
  updateGitlabCommitStatus name: '代码检测', state: 'success'
} catch(Exception err) {
  updateGitlabCommitStatus name: '代码检测', state: 'failed'
  unstable '代码检测失败'
}

# 使用多个代理

# 高级脚本式流水线

# 并行执行
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-12-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 基础实践
    • (1) Maven 构建之 Pipeline Script
      • (2) Maven 构建之 Pipeline Script from SCM
        • (3) Jenkins pipeline 之 邮件(Email)发信管理
        • 0x02 进阶实践
          • (1) Sonarqube 代码质量检测之 Pipeline Script from SCM
            • (2) Gitlab 自动触发构建之 Pipeline Script from SCM
            • 0x03 入坑与出坑
            相关产品与服务
            持续集成
            CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档