Pre build
Gerrit-code-review 多分支流水线
- Jenkinsfile标黄部分为注释,为方便理解Jenkinsfile,实际使用时不需要,需要删除
- Jenkinsfile 标红为需要根据项目实际修改的部分
pipeline {//2~30 行 初始化编译环境,标红部分需要换成项目编译需要的docker imges
agent {
kubernetes {
label "${UUID.randomUUID().toString()}"
yaml """
metadata:
labels:
some-label: some-label-value
class: KubernetesDeclarativeAgentTest
namespace: scm
spec:
nodeSelector:
jenkins-ci: "true"
containers:
- name: build
image: hub.hobot.cc/systemsoft/build-ci:V2022.09.01
command:
- cat
tty: true
env:
- name: CONTAINER_ENV_VAR
value: build
volumes:
- name: gallery-upload-secret
secret:
defaultMode: 420
secretName: gallery-upload-secret
"""
}
}
environment {
LANG = 'en_US.UTF-8'
}
stages{
stage('building') {
steps {
container('build') {
building() //执行编译
}
}
}
}
post {//根据jenkins返回结果回写gerrit状态
success {
gerritReview labels: [Verified: 1]
gerritCheck checks: ['example:checker': 'SUCCESSFUL']
}
unstable { gerritReview labels: [Verified: 0], message: 'Build is unstable' }
failure {
gerritReview labels: [Verified: -1]
gerritCheck checks: ['example:checker': 'FAILED'], message: 'invalid syntax'
}
}
}
def building() {//执行编译
sh '''
ls
'''
}
gerrit-trigger 流水线
- Jenkinsfile标黄部分为注释,为方便理解Jenkinsfile,实际使用时不需要,需要删除
- Jenkinsfile 标红为需要根据项目实际修改的部分
- 整个流程由主流程和子流程 两个Jenkinsfile组成
主流程
子流程
Jenkinsfile命名
Jenkinsfile
dev目录下 ${Branch_name}.jenkinsfile
例如:master.jenkinsfile、develop.jenkinsfile
作用
-
初始化编译环境
-
根据分支名判断需要调用哪个子流程编译,如果提交是master分支就会到dev/目录下运行master.jenkinsfile
-
下载代码、patch 并执行编译
主流程:Jenkinsfile
主流程
pipeline {//2~30 行 初始化编译环境,标红部分需要换成项目编译需要的docker imges
agent {
kubernetes {
label "${UUID.randomUUID().toString()}"
yaml """
metadata:
labels:
some-label: some-label-value
class: KubernetesDeclarativeAgentTest
namespace: scm
spec:
nodeSelector:
jenkins-ci: "true"
containers:
- name: build
image: hub.hobot.cc/systemsoft/build-ci:V2022.09.01
command:
- cat
tty: true
env:
- name: CONTAINER_ENV_VAR
value: build
volumes:
- name: gallery-upload-secret
secret:
defaultMode: 420
secretName: gallery-upload-secret
"""
}
}
environment { //环境变量
//这里的环境变量都是repo init下载代码的参数,标红部分需要按照实际修改
LANG = 'en_US.UTF-8'
SSH_KEY_FILE = credentials('cc69e1ac-xxx')
//项目cicd公共账号的credentials
USERNAME = 'yiyue.xu'
//项目cicd公共账号名
SSH_URL = "ssh://${USERNAME}@gerrit.hobot.cc:29418"
MANIFEST_PROJECT = "${SSH_URL}/Test.git"
//MANIFEST 仓库名
MANIFEST_XML = 'manifest.xml'
//MANIFEST.xml 名字,例如default.xml、manifest.xml
REPO_URL = "${SSH_URL}/SCM/git-repo.git"
}
stages{// 根据分支判断调用哪个子流程jenkinsfile
stage('prepare') {
steps{
container('prepare') {
script {
println 'CI on branch ' + env.GERRIT_BRANCH
def jenkinsfile_dir = 'dev/jenkinsfiles/' //jenkinsfile存放路径
if (env.GERRIT_BRANCH == 'master') {
find_and_load(jenkinsfile_dir + 'master.jenkinsfile')
//如果是master分支,调用dev/jenkinsfiles/master.jenkinsfile
} else if (env.GERRIT_BRANCH.startsWith('release-')) {
find_and_load(jenkinsfile_dir + 'release.jenkinsfile')
} else {
find_and_load(jenkinsfile_dir + 'develop.jenkinsfile')
}
}
}
}
}
}
}
def find_and_load(jenkinsfile_name) {
def build_Jenkinsfile_exist = fileExists jenkinsfile_name
if (build_Jenkinsfile_exist) {
println 'Jump to ' + jenkinsfile_name
load jenkinsfile_name
} else {
println 'Cannot find ' + jenkinsfile_name + ', CI terminated.'
}
}
子流程
在子流程中配置key 初始化repo 和下载代码 获取patch 命令都已封装成函数写在脚本中,只需传递参数使用
流程中的 以下用法就是使用公共脚本
bash ${WORKSPACE}/scmtools/cicd_script/ssh_key_init.sh ${USERNAME} ${SSH_KEY_FILE}
bash ${WORKSPACE}/scmtools/cicd_script/repo_tool_init.sh ${REPO_URL}
bash ${WORKSPACE}/scmtools/cicd_script/get_code_repoinit.sh ${MANIFEST_PROJECT} ${GERRIT_BRANCH} ${MANIFEST_XML} ${REPO_URL}
bash ${WORKSPACE}/scmtools/cicd_script/get_patch_repoinit.sh ${SSH_URL} ${GERRIT_PROJECT} ${GERRIT_REFSPEC}
Jenkinsfile 模板
stage('prepare') { // prepare阶段会下载代码,使用的是scm/scmtools仓库下的脚本,不需要修改。
container('prepare') {
script {
sh '''
git clone "https://gerrit.hobot.cc:8443/scm/scmtools"
bash ${WORKSPACE}/scmtools/cicd_script/ssh_key_init.sh ${USERNAME} ${SSH_KEY_FILE}
bash ${WORKSPACE}/scmtools/cicd_script/repo_tool_init.sh ${REPO_URL}
bash ${WORKSPACE}/scmtools/cicd_script/get_code_repoinit.sh ${MANIFEST_PROJECT} ${GERRIT_BRANCH} ${MANIFEST_XML} ${REPO_URL}
'''
//初始化repo工具、下载代码
try {
sh '''
python3 scmtools/cicd_script/get_path.py .repo/manifest.xml ${GERRIT_PROJECT} ${GERRIT_BRANCH}
'''
}
catch (Exception e) {
sh '''
echo "INFO: No Match REPO and BRANCH, ignore build mark as successful "
'''
currentBuild.getRawBuild().getExecutor().interrupt(Result.SUCCESS)
sleep(5)
}
}
}
}
stage('building') {
container('build') {
//执行脚本获取patch,这里不需要修改
sh '''
bash ${WORKSPACE}/scmtools/cicd_script/ssh_key_init.sh ${USERNAME} ${SSH_KEY_FILE}
bash ${WORKSPACE}/scmtools/cicd_script/get_patch_repoinit.sh ${SSH_URL} ${GERRIT_PROJECT} ${GERRIT_REFSPEC}
'''
building()//调用def building()执行编译
}
}
def building() {//这里实际执行编译,需要修改为项目实际编译命令
sh '''
ls
'''
}
TAG build
- Jenkinsfile标黄部分为注释,为方便理解Jenkinsfile,实际使用时不需要,需要删除
- Jenkinsfile 标红为需要根据项目实际修改的部分
- 140~192行 为流程中实际调用的函数。如流程要修改,要到调用的函数中修改。
pipeline {//2~30 行 初始化编译环境,标红部分需要换成项目编译需要的docker imges
agent {
kubernetes {
label "${UUID.randomUUID().toString()}"
yaml """
metadata:
labels:
some-label: some-label-value
class: KubernetesDeclarativeAgentTest
namespace: scm
spec:
nodeSelector:
jenkins-ci: "true"
containers:
- name: build
image: hub.hobot.cc/systemsoft/build-ci:V2022.09.01
command:
- cat
tty: true
env:
- name: CONTAINER_ENV_VAR
value: build
volumes:
- name: gallery-upload-secret
secret:
defaultMode: 420
secretName: gallery-upload-secret
"""
}
}
environment {
LANG = 'en_US.UTF-8'
SSH_KEY_FILE = credentials('cc69e1ac-xxxxx')
USERNAME = 'yiyue.xu'
// SSH_KEY_FILE 需要修改成项目账号
}
parameters { //参数, 根据这些参数同步代码编译
string defaultValue: '', description: 'Enter MANIFEST_PROJECT', name: 'MANIFEST_PROJECT', trim: true
//存放manifest.xml的代码仓库名 ,例如:ptd/ss/hobot-release/manifest
string defaultValue: '', description: 'Enter MANIFEST_BRANCH', name: 'MANIFEST_BRANCH', trim: true
//manifest.xml 的分支名,例如REL-J5
string defaultValue: '', description: 'Enter MANIFEST_XML', name: 'MANIFEST_XML', trim: true
//manifest的命名,例如:manifest.xml 、default.xml
string defaultValue: 'ssh://XXX@gerrit.hobot.cc:29418/SCM/git-repo.git', description: 'Enter REPO_URL', name: 'REPO_URL', trim: true
//需要把这里的XXX 修改为项目账号
string defaultValue: '', description: 'Enter TAG_NAME', name: 'TAG_NAME', trim: true
//TAG名
string defaultValue: '', description: 'Enter TAG_ANNOTATION', name: 'TAG_ANNOTATION', trim: true
//TAG的描述信息
booleanParam defaultValue: true, description: '如果需要将TAG信息回写到代码仓库,请勾选', name: 'TAG_THE_BUILD'
//是否需要在代码仓库打TAG,不勾选不会回写TAG
}
stages{
stage('prepare') { //同步代码
steps {
container('prepare') {
script {
sh "env"
sh '''
git clone "https://gerrit.hobot.cc:8443/scm/scmtools"
bash ${WORKSPACE}/scmtools/cicd_script/ssh_key_init.sh ${USERNAME} ${SSH_KEY_FILE}
bash ${WORKSPACE}/scmtools/cicd_script/repo_tool_init.sh ${REPO_URL}
bash ${WORKSPACE}/scmtools/cicd_script/get_code_repoinit.sh ${MANIFEST_PROJECT} ${MANIFEST_BRANCH} ${MANIFEST_XML} ${REPO_URL}
'''
}
}
}
}
stage('building') { //编译
steps {
container('build') {
building() // 编译代码
}
}
}
stage('TAG') {//回写TAG
when {
environment name: 'TAG_THE_BUILD', value: 'true' //TAG_THE_BUILD为true时执行
beforeAgent true
}
steps {
container('build') {
script {
dir('repo_init') {
sh '''
echo "to be tag"
bash ${WORKSPACE}/scmtools/cicd_script/ssh_key_init.sh ${USERNAME} ${SSH_KEY_FILE}
'''
push_tag() //推tag到代码仓库
}
}
}
}
}
}
}
def building() { //这里需要写项目编译步骤
sh '''
ls
'''
}
def push_tag() {
sh '''
if [ ! -n ${TAG_ANNOTATION} ];then
repo forall -c 'git tag '${TAG_NAME}' && git push origin '${TAG_NAME}''
else
repo forall -c 'git tag -a '${TAG_NAME}' -m '${TAG_ANNOTATION}' && git push origin '${TAG_NAME}''
fi
'''
}