JenkinsFile pipeline 语法使用心得
本次使用心得针对想让特定的 job 在指定的 jenkins slave 节点上运行。并能通过 pipeline 的方式规定任务流程。在使用过程中遇到很多问题,以及语法的一些尝试,最终完美解决各个阶段的连通性 克隆代码–>编译代码–>处理编译后文件–>项目压缩–>项目部署工具处理–>部署工具转存等,原本计划要写很多,因为在书写过程中语法报错很多次,但是在书写完成后,其实只要注意的部分是语法的格式、调用方式、执行顺序、变量的调取方式等,有想法就持续更新此文档吧,呜呜呜呜呜!
- 最终效果展示
- 最终代码展示
pipeline {
agent {
label 'jenkins-slave'
}
parameters {
// 指定 tag 或者分支名称
gitParameter(name: 'BRANCH_TAG',type: 'PT_BRANCH_TAG',defaultValue: 'master')
// 定义基础镜像
string(name: 'BASE_IMAGE', defaultValue: '192.168.1.64/magic/magicjupyter:v0.3', description: '输入使用的基础镜像名称?')
}
environment {
// 定义编译过程中配置文件转存目录
CONFIG_PATH="/data/conf_tmp"
// 定义项目打包后存放路径
PACKAGE_PATH="/data/package_save"
// 通过 sh 的输出定义为变量
// PROJECTNAME=sh(returnStdout: true, script: 'basename ${WORKSPACE}_${BRANCH_TAG}')
// 项目名称,在打包时进行调用
PROJECT_NAME="magicjupyter"
// 远程目录
REMOTE_PATH="/package_download/tools"
// 远端主机,使用 jenkins 插件进行传送配置麻烦,简单使用 scp 传送(前提做好 SSH 免密登陆即可)
REMOTE_HOST="192.168.1.74"
}
stages {
stage('克隆代码'){
steps {
checkout([$class: 'GitSCM',
branches: [[name: "${params.BRANCH_TAG}"]],
doGenerateSubmoduleConfigurations: false,
extensions: [],
gitTool: 'Default',
submoduleCfg: [],
userRemoteConfigs: [[credentialsId: 'jenkins-slave-git-key', url: 'ssh://git@192.168.1.12:2223/lab/magicjupyter.git']]
])
}
}
stage('编译准备') {
parallel {
stage('临时目录创建') {
steps {
sh '[[ ! -d "${CONFIG_PATH}" ]] && mkdir -p ${CONFIG_PATH}'
}
}
stage('同步目录') {
steps {
sh 'rsync -rv --exclude=.git --exclude=.gitignore ${WORKSPACE}/ ${WORKSPACE}_${BRANCH_TAG} >> /dev/null 2>&1'
}
}
stage('处理项目结构') {
steps {
sh '[[ ! -d ${PACKAGE_PATH} ]] && mkdir -p ${PACKAGE_PATH}'
}
}
}
}
stage('代码编译') {
stages {
stage('转存配置文件') {
steps {
sh '''
cp ${WORKSPACE}_${BRANCH_TAG}/api/settings.py ${CONFIG_PATH}
cp ${WORKSPACE}_${BRANCH_TAG}/utils/constants.py ${CONFIG_PATH}
'''
}
}
stage('运行编译') {
steps {
dir("${env.WORKSPACE}_${BRANCH_TAG}") {
sh '/usr/local/python3/bin/python3 setup.py build_ext --inplace'
}
}
}
stage('删除编译后pyc文件') {
steps {
dir("${env.WORKSPACE}_${BRANCH_TAG}") {
sh """
/bin/bash clean.sh
"""
}
}
}
stage('还原配置文件') {
steps {
dir("${env.WORKSPACE}_${BRANCH_TAG}") {
sh '''
[[ -f "./api/settings.pyc" ]] && rm -f ./api/settings.pyc
[[ -f "./utils/constants.pyc" ]] && rm -f ./utils/constants.pyc
cp ${CONFIG_PATH}/settings.py ./api/settings.py
cp ${CONFIG_PATH}/constants.py ./utils/constants.py
'''
}
}
}
}
}
stage('编译后处理') {
stages {
stage('重命名') {
steps {
sh 'mv ${WORKSPACE}_${BRANCH_TAG} ${PACKAGE_PATH}/${PROJECT_NAME}'
}
}
stage('压缩项目文件') {
steps {
dir("${env.PACKAGE_PATH}") {
sh '''
tar czvf ${PROJECT_NAME}-${BRANCH_TAG}.tar.gz \\
--exclude=${PROJECT_NAME}/logs \\
--exclude=${PROJECT_NAME}/static \\
--exclude=${PROJECT_NAME}/build \\
--exclude=${PROJECT_NAME}/Dockerfile \\
--exclude=${PROJECT_NAME}/Jenkinsfile \\
--exclude=${PROJECT_NAME}/README.md \\
--exclude=${PROJECT_NAME}/requirements.txt \\
--exclude=${PROJECT_NAME}/clean.sh \\
${PROJECT_NAME} >> /dev/null 2>&1
'''
}
}
}
stage('构建镜像') {
stages {
stage('编译镜像准备') {
steps {
dir("${env.PACKAGE_PATH}") {
sh 'mv ${PROJECT_NAME}-${BRANCH_TAG}.tar.gz ${PROJECT_NAME}/build/'
}
}
}
stage('编译镜像') {
// 只要注意包含关系 dir 切换目录;stage{stages {....}} 或者 stages { stage { steps {.....}}
steps {
script {
dir("${env.PACKAGE_PATH}/${env.PROJECT_NAME}") {
docker.withRegistry('http://192.168.1.64/', 'harbor') {
def customImage = docker.build("192.168.1.64/magic/${env.PROJECT_NAME}:${env.BRANCH_TAG}", "--build-arg TARNAME=${PROJECT_NAME}-${BRANCH_TAG}.tar.gz --build-arg DOCKER_BASE_IMAGE=${params.BASE_IMAGE} ./build")
customImage.push()
}
}
}
}
}
}
}
}
}
stage('部署工具') {
stages {
stage ('压缩镜像') {
input {
message "是否进行打包?"
ok "Yes"
}
steps {
dir("${env.PACKAGE_PATH}/${env.PROJECT_NAME}/deploy/code_pack") {
sh '''
docker save 192.168.1.64/magic/${PROJECT_NAME}:${BRANCH_TAG} | gzip > ${PROJECT_NAME}:${BRANCH_TAG}.tar.gz
'''
}
}
}
stage ('打包部署工具') {
steps {
dir("${env.PACKAGE_PATH}/${env.PROJECT_NAME}") {
sh '''
tar czvf ${PROJECT_NAME}_${BUILD_NUMBER}.tar.gz deploy
'''
}
}
}
stage ('传送文件') {
steps {
dir("${env.PACKAGE_PATH}/${env.PROJECT_NAME}") {
sh '''
scp ${PROJECT_NAME}_${BUILD_NUMBER}.tar.gz root@${REMOTE_HOST}:${REMOTE_PATH}/
'''
}
}
}
}
}
}
post {
// pipeline 执行左后删除临时目录
always {
dir("${env.WORKSPACE}@tmp") {
deleteDir()
}
dir("${env.WORKSPACE}_${BRANCH_TAG}@tmp") {
deleteDir()
}
dir("${env.WORKSPACE}_${BRANCH_TAG}") {
deleteDir()
}
dir("${env.CONFIG_PATH}") {
deleteDir()
}
dir("${env.PACKAGE_PATH}") {
deleteDir()
}
}
}
}
-
使用到的语法简介
pipeline
: 块是 声明式流水线.agent
: 具体参数使用可以查阅官网说明:Jenkinsfile 文档- 官方说明: 部分指定了整个流水线或特定的部分, 将会在Jenkins环境中执行的位置,这取决于 agent 区域的位置。该部分必须在 pipeline 块的顶层被定义, 但是 stage 级别的使用是可选的。
- 本人理解: 就是可以使用 pipeline 整个生态中,也可以指定在具体的 stage 块中使用。
parameters
: 定义构建过程参数environment
: 设置环境变量,也可以动态设置变量stages
: 包含一系列一个或多个 stage 指令, stages 部分是流水线描述的大部分"work" 的位置。本文中进行了尝试如下使用同样OK,stages { stage { stages { } } }
steps
: 在给定的 stage 指令中执行的定义了一系列的一个或多个steps。dir
: 指定在什么目录下工作sh
: 执行 shell 命令docker
: 直接编译 docker 镜像与提交镜像input
: 运行中的交互功能post
: 在所有 pipeline 既定任务完成后,执行的操作;