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 协议》,转载必须注明作者和本文链接
推荐文章: