Jenkins Pipeline
Jenkins2.0的Pipeline(formerly called ‘workflow’)允许用户定义软件项目的整个生命周期来支持持续集成。在项目根目录下创建一个Jenkinsfile文件,编写从构建到部署的整个生命周期,减少了复杂的Jenkins界面操作。
Pipeline特性如下:
- 持久性(durable):在Jenkins master按计划和非计划的重启后,pipeline仍然能够工作,类似nohup
- 暂停:支持任务暂停并等待手动触发
- 灵活:Pipeline支持复杂的持续集成需求,包括fork, join, loop, work in parallel
- 扩展:支持DSL(Domain Scripting Language)并可与其他插件集成
一些跟Pipeline相关的插件:
- Pipeline: 包含了核心pipeline引擎以及其从属的插件,
Pipeline: API, Pipeline: Basic Steps, Pipeline: Durable Task Step, Pipeline: Execution Support, Pipeline: Global Shared Library for CPS pipeline, Pipeline: Groovy CPS Execution, Pipeline: Job, Pipeline: SCM Step, Pipeline: Step API
- Pipeline Stage View: 图形化的泳道阶段图
- Multibranch Pipeline: 自动构建包含
Jenkinsfile的分支
- Docker Pipeline: 在Jenkinsfile脚本中使用Docker containers进行构建
Jenkinsfile Template
#!groovy
// 设置Pipe只保存最近5次的build
def projectProperties = [
[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numberToKeepStr: '5']],
]
if(!env.CHANGE_ID) {
if (env.BRANCH_NAME == null) {
projectProperties.add(pipelineTriggers([cron('H/30 * * * *')]))
}
}
properties(projectProperties)
node {
def workspace = pwd()
// 将源码checkout到pipeline的workspace,使用Pipeline任务配置的Repo
// 等同于:git branch: 'jenkinsfile', credentialsId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', url: 'repo url'
// 但不需要credentialsId
stage('Checkout Source Code') {
checkout scm
}
stage('build') {
try {
// 目前这种写法不好,因为在node里使用input将使得node本身和workspace被lock,不能够被别的job使用
def userInput = input(
id: 'userInput', message: 'Choose the build Environment', ok: 'Submit', parameters[
//[$class: 'TextParameterDefinition', defaultValue: '', description: 'Data Sufix', name: 'snapshot'],
[$class: 'ChioceParameterDefinition', name: 'target', description: 'Build Env', choices: 'dev\ntesting\nstaging\nproduction'],
]
)
//sh "./gradlew clean build -Penv=" + userInput['target']
// 如果只有一个Input值,则直接使用userInput获取输入值
sh "./gradlew clean build -Penv=" + userInput
}
catch(err) {
stage('Failure Notification') {
def to emailextrecipients([
[$class: 'DevelopersRecipientProvider']
])
mail to: to, subject: "${env.JOB_NAME} Failed!",
body: "${env.JOB_NAME} failed the last time it was run. See ${env.BUILD_URL} for more information."
currentBuild.result = 'FAILURE'
}
}
}
// 将构建好的包上传到Nexus仓库,其中用户名密码在Jenkins `Configure System`中添加
stage('Publish') {
timeout(time: 10, unit: 'MINUTES') {
input "Publish ${env.ENV} archive package to Nexus?"
env.REPO_URL = sh(returnStdout: true, script: "./gradlew -Penv=${env.ENV} publish | grep -oP -m 1 'http.*?zip'").trim()
echo "Publish to url: ${env.REPO_URL}"
}
}
// 将上传到Nexus上的包拉下来部署到运行环境,需要在Jenkins上用ssh-copy-id来设置免密码登陆
stage('Deploy') {
timeout(time: 10, unit: 'MINUTES') {
input "Deploy to ${env.ENV} environment?"
def host = map["${env.ENV}"]
if ("${env.ENV}" == "dev") {
// -x让shell打印每一行执行的命令,-s表示从标准输入读取要运行的脚本,这里重定向了deploy.sh
sh "ssh root@${host} 'bash -x -s' < ./deploy.sh " + "${env.REPO_URL}"
}
}
}
//if (env.BRANCE_NAME == 'release') {
// stage('Tag release') {
// String version = readFile('Version')
// Object git = load 'groovy/git.groovy'
// git.gitTag "v${version}", "Release ${version}"
// }
//}
}
def archiveUnitTestResults() {
step([$class: "JunitResultArchiver", testResults: "build/**/TEST-*.xml"])
}
def archiveCheckStyleResults() {
step([$class: "CheckStylePublisher",
canComputeNew: false,
defaultEncoding: "",
health: "",
pattern: "build/reports/checkstyle/main.xml",
unHealthy: ""
])
}
deploy.sh脚本中为远程机器上执行的命令。
#!/bin/bash
WORK_DIR="/opt/workdir"
PRJ_DIR="$WORK_DIR/prj1"
PRJ_TMP="$WORK_DIR/tmp"
RUN_PID="$PRJ_DIR/bin/run.pid"
if [ ! -d $WORK_DIR ]; then
mkdir -p $WORK_DIR
fi
# 删除之前运行的进程
if [ -f $RUN_PID ]; then
PID=`cat $RUN_PID`
echo "Killing former running progress $PID"
cat $RUN_PID | xargs kill -9
echo "Killing former running progree $PID done."
fi
yes | rm -r $PRJ_DIR
cd $WORK_DIR
mkdir -p $UPMS_DIR
wget $1
url=$1
unzip ${url##*/} -d $PRJ_TMP
yes | rm ${url##*/}
mv $PRO_TMP/*/* $PRO_DIR
cd $PRO_DIR/bin/
nohup $PRO_DIR/bin/xxxx-start > /dev/null 2>&1 &
echo $! > $RUN_PID
echo "SERVER started with pid `cat $RUN_PID`"
Stage View
Another Jenkinsfile
https://github.com/zhjwpku/ijkplayer/blob/master/Jenkinsfile
Copyright © 2016-2024 by 赵军旺