- 新建构建任务,初步定命名规范:组名缩写-环境-仓库名(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{
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