jenkins 使用 demo 小记

  • 新建构建任务,初步定命名规范:组名缩写-环境-仓库名(or 组名缩写-环境-仓库名-描述)
    在这里插入图片描述
  • 构建任务配置,启用用户安全添加用户并授权,非LDAP需要先注册用户
    在这里插入图片描述
  • 参数化构建
    在这里插入图片描述
    run_env不同环境对应值,其它值无效,其对应数据库字段,不同环境对应相应服务器
dev test alpha beta prod
  • 如果需要进行自动化提交构建则进行此步骤,配置webhook自动化构建,到gitlab的对应仓库设置hook对应的url,secret,需要自动化测试的分支,保存并测试
    在这里插入图片描述
    在这里插入图片描述
  • 添加pipeline流水线脚本

    pipeline{
    //运行节点设置
    agent {label 'master'}
    options {
        timestamps()
        skipDefaultCheckout()
    }
    
    stages {
        stage('prepare') {
            steps {
                echo '初始化相关变量...'
               script {
                    //branch_or_tag为参数化构建参数,git会拉取分支或者标签,run_env为参数化构建的发布环境,mode为参数化构建的子目录
    
                    //********** 只需要配置仓库目录名和仓库地址,仓库名和仓库地址需要在仓库字典存在对应一条记录 start ***********
                    main_dir = 'ToolReviewCode'
                    main_git = 'git@XXXXXXXXXXXXX/ToolReviewCode.git'
                    //********** end *****************
    
                    //以下不需要配置
                    //主仓库绝对路径
                    repo_path = "${WORKSPACE}"
                    //临时仓库项目目录
                    temp_project_path = "${BUILD_SPACE}/${currentBuild.projectName}"
                    //主仓库临时目录
                    temp_repo_path = "$temp_project_path/${main_dir}"
                    //创建临时目录
                    sh "mkdir -p ${temp_project_path}"
    
                }
            }
        }
    
        stage('checkout') {
           steps{
                //这里需要配置
                //主仓库拉取,只需要配置分支或标签${branchOrTag},git_url
                echo '开始拉取代码...'
                checkout([$class: 'GitSCM', branches: [[name: "${branch_or_tag}"]], userRemoteConfigs: [[url: "${main_git}"]]])
            }
        }
    
        stage('build') {
            steps {
                //发布前构建
                //先同步到临时目录,rsync 命令,-a -z为压缩,-t为保留文件时间属性,如果是量全量同步则是加 --delete-after,排除.git文件,可根据自己需要我改参数,后面两个目录参数可不动,注意第一个要加'/',第二个不用
                sh "rsync -azt --exclude=.git ${repo_path}/ ${temp_repo_path}"
    
                //写入主仓库发布标签识别文件,方便出故障确认发布版本,这里可不动
                sh "echo ${branch_or_tag} > ${temp_repo_path}/deploy-version"
    
            }
        }
        stage('Test') {
            steps{
                //自动化测试,日后做自动化测试
                echo 'This is a test step'
    
            }
        }
    
        stage('Sonar') {
            //根据条件判断是进行sonar扫描代码
            //when {
                //    expression { return params.run_env == ''}
                //}
            steps {
                //sonar检测,需要在项目根目录配置sonar-scanner.properties
                echo 'sonar检测...'
                echo 'This is a sonar stop'
    
                script {
                     def sonarqubeScannerHome = tool name: 'SonarQubeScanner'
                     withSonarQubeEnv('SonarQube') {
                            sh "${sonarqubeScannerHome}/bin/sonar-scanner"
                    }
                }
            }
        }
        //确认机制,可根据自己情况是否添加,这里判断如果是生产环境则进行手动发布确认
        stage('confirmed') {
             when {
                  expression { return params.run_env == 'prod'}
              }
              steps {
                  timeout(time: 1, unit: 'HOURS') {
                       input message:'Are you sure?', ok:'Yes'
                  }
    
              }
        }
        stage('Deploy') {
    
            steps{
                //调用python脚本发布到服务器
                //参数 env 发布环境可选默认test,
                //参数 mode 个人开发目录或灰度目录,默认为空
                //参数 git_url 仓库地址必须,必须存在仓库字典
                //参数 source_dir 仓库临时目录路径,必须
                //参数 code_run_path 仓库运行目录,可选,默认空字符串,如果为空则会获取仓库字典设置的发布目录,可带'/'可不带'/',最终发布目录会是连接mode
                //参数  is_sync_delete 同步方式,全量或增量,默认增量False,如果是全量则可传值True或1
                //参数 exclude-file 文件路径,默认为空,内容为同步时排除的文件名或目录名
                sh "cd ${JENKINS_HOME}/python_script && python3 deploy.py --git_url=${main_git} --source_dir=${temp_repo_path} --env=${run_env} --mode=${mode}"
            }
        }
    }
    }
  • 具有依赖仓库pipeline脚本模板

    pipeline{
    agent any
    options {
        timestamps()
        skipDefaultCheckout()
    }
    
    stages {
        stage('prepare') {
            steps {
               script {
                    //branch_or_tag为参数化构建参数,git会拉取分支或者标签,run_env为参数化构建的发布环境,mode为参数化构建的子目录
    
                    //********** 只需要配置仓库目录名和仓库地址,仓库名和仓库地址需要在仓库字典存在对应一条记录 start ***********
                    main_dir = 'XXX'
                    main_git = 'git@XXX:cloudserver/XXX'
                    //********** end *****************
                    //以下不需要配置
                    //主仓库绝对路径
                    repo_path = "${WORKSPACE}"
                    //临时仓库项目目录
                    temp_project_path = "${BUILD_SPACE}/${currentBuild.projectName}"
                    //主仓库临时目录
                    temp_repo_path = "$temp_project_path/${main_dir}"
                    //创建临时目录
                    sh "mkdir -p ${temp_project_path}"
    
                    //如果有依赖则定义每个依赖仓库的目录和分支或标签,依赖的分支或标签很少变动,可以写死在这里,也可以进行参数化构建,添加默认值
                    sdk_dir = 'sdk'
                    framework_dir = 'framework'
                    tsdk_dir = 'tSDK'
    
                }
            }
        }
    
        stage('checkout') {
           steps{
               echo '拉取代码...'
                //主仓库拉取,只需要配置分支或标签${branchOrTag},git_url
                checkout([$class: 'GitSCM', branches: [[name: "${branch_or_tag}"]],  userRemoteConfigs: [[url: "${main_git}"]]])
            }
        }
    
        stage('checkout rely') {
            //这里是拉取依赖仓库,可以并行执行,配置跟主仓库类似
            parallel {
                stage('sdk') {
                    when {
                        expression { return params.sdk_branch_or_tag}
                    }
                    steps {
                        checkout([$class: 'GitSCM', branches: [[name: "${sdk_branch_or_tag}"]],  extensions: [[$class: "RelativeTargetDirectory", relativeTargetDir: "rely_temp/${sdk_dir}"]], userRemoteConfigs: [[url: 'git@XXXXXX/sdk.git']]])
                    }
                }
    
                stage('framework') {
                    when {
                        expression { return params.framework_branch_or_tag}
                    }
                    steps {
                        checkout([$class: 'GitSCM', branches: [[name: "${framework_branch_or_tag}"]],  extensions: [[$class: "RelativeTargetDirectory", relativeTargetDir: "rely_temp/${framework_dir}"]], userRemoteConfigs: [[url: 'git@XXXXXX/framework.git']]])
                    }
                }
    
                stage('tSDK') {
                    when {
                        expression { return params.tsdk_branch_or_tag}
                    }
                    steps {
                        checkout([$class: 'GitSCM', branches: [[name: "${tsdk_branch_or_tag}"]],  extensions: [[$class: "RelativeTargetDirectory", relativeTargetDir: "rely_temp/${tsdk_dir}"]], userRemoteConfigs: [[url: 'git@XXXXXX/tSDK.git']]])
                    }
                }
    
            }
        }
    
        stage('build') {
            steps {
                echo '构建代码...'
                //发布前构建
                //先同步到临时目录,rsync 命令,-a -z为压缩,-t为保留文件时间属性,如果是量同步则是加 --delete-after, 排除.git和依赖存放临时目录rely_temp,可根据自己需要我改参数,后面两个目录参数可不动,注意第一个要加'/',第二个不用
                sh "rsync -azt --exclude=.git --exclude=rely_temp ${repo_path}/ ${temp_repo_path}"
    
                //写入主仓库发布标签识别文件,方便出故障确认发布版本
                sh "echo ${branch_or_tag} > ${temp_repo_path}/deploy-version"
    
                //如果有依赖,则进行依赖的同步,如果没有,则下面省略
    
                script {
                    exclude_file = "${temp_repo_path}/exclude.list"
                    sh "echo '' > ${exclude_file}"
    
                    if (sdk_branch_or_tag) {
    
                        sh "rsync -azt --exclude=.git ${WORKSPACE}/rely_temp/${sdk_dir}/ ${temp_repo_path}/protected/${sdk_dir}"
                        sh "echo ${sdk_branch_or_tag} > $temp_repo_path/protected/${sdk_dir}/deploy-version"
                    } else {
                        sh "echo 'protected/sdk' >> ${exclude_file}"
                        echo 'no sync sdk'
                    }
    
                    if (framework_branch_or_tag) {
    
                        sh "rsync -azt --exclude=.git ${WORKSPACE}/rely_temp/${framework_dir}/ ${temp_repo_path}/protected/${framework_dir}"
                        sh "echo ${framework_branch_or_tag} > $temp_repo_path/protected/${framework_dir}/deploy-version"
                    } else {
                        sh "echo 'protected/framework' >> ${exclude_file}"
                        echo 'no sync framework'
                    }
                    if (tsdk_branch_or_tag) {
    
                        sh "rsync -azt --exclude=.git ${WORKSPACE}/rely_temp/${tsdk_dir}/ ${temp_repo_path}/protected/${tsdk_dir}"
                        sh "echo ${tsdk_branch_or_tag} > $temp_repo_path/protected/${tsdk_dir}/deploy-version"
                    } else {
                        sh "echo 'protected/tSDK' >> ${exclude_file}"
                        echo 'no sync tSDK'
                    }
    
                }
            }
        }
        stage('Test') {
            steps{
                //自动化测试
                echo 'This is a test step'
    
            }
        }
    
        stage('Sonar') {
            //根据条件判断是进行sonar扫描代码
            //when {
                //    expression { return params.run_env == ''}
                //}
            steps {
                //sonar检测,需要在项目根目录配置sonar-scanner.properties
                echo 'sonar检测...'
                echo 'This is a sonar stop'
    
                // script {
                //      def sonarqubeScannerHome = tool name: 'SonarQubeScanner'
                //      withSonarQubeEnv('SonarQube') {
                //             sh "${sonarqubeScannerHome}/bin/sonar-scanner"
                //     }
                // }
            }
        }
        //确认机制,可根据自己情况是否添加
        stage('confirmed') {
             when {
                  expression { return params.run_env == 'prod'}
              }
              steps {
                  timeout(time: 1, unit: 'HOURS') {
                       input message:'Are you sure?', ok:'Yes'
                  }
    
              }
        }
        stage('Deploy') {
    
            steps{
                //调用python脚本发布到服务器
                //参数 env 发布环境可选默认test,
                //参数 mode 个人开发目录或灰度目录,默认为空
                //参数 git_url 仓库地址必须,必须存在仓库字典
                //参数 source_dir 仓库临时目录路径,必须
                //参数 code_run_path 仓库运行目录,可选,默认空字符串,如果为空则会获取仓库字典设置的发布目录,可带'/'可不带'/',最终发布目录会是连接mode
                //参数  is_sync_delete 同步方式,全量或增量,默认增量False,如果是全量则可传值True或1
                //参数 exclude-file 文件路径,默认为空,内容为同步时排除的文件名或目录名
                sh "cd ${JENKINS_HOME}/python_script && python3 deploy.py --git_url=${main_git} --source_dir=${temp_repo_path} --env=${run_env} --mode=${mode} --exclude_file=${exclude_file} --is_sync_delete=1"
            }
        }
    }
    }
  • 参数化构建的时候第一次执行时可能会出现以下问题,无法拉取代码的分支或标签,可尝试在脚本中先写死branch_or_tag的值,去掉branch_or_tag参数 ,执行构建一次,再加上branch_or_tag参数就可以了,目前还无法定位到这个问题的原因,或者如果嫌麻烦可心把branch_or_tag定义为字符串参数,手动输入分支或标签
    在这里插入图片描述
  • 如果需要做sonar检测,需要在项目根目录添加 sonar-project.properties 文件
    
    #unique project identifier (required)

sonar.projectKey = ToolReviewCode:1.1

project metadata (used to be required, optional since SonarQube 6.1)

sonar.projectName=ToolReviewCode
sonar.projectVersion=1.6

path to source directories (required)

sonar.sources = backend,frontend,common

sonar.exclusions=

path to test source directories (optional)

sonar.tests=testDir1,testDir2

path to Java project compiled classes (optional)

sonar.java.binaries=bin

comma-separated list of paths to libraries (optional)

sonar.java.libraries=path/to/library.jar,path/to/classes/dir

Additional parameters

sonar.my.property=value

#########

sonar.sourceEncoding=UTF-8

sonar.java.source=1.8

sonar.java.target=1.8

本作品采用《CC 协议》,转载必须注明作者和本文链接
雪花飘
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 2

大神,请教个问题。Jenkins构建完成后,归档成品时候如何归档递归目录?

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!