Groovy 背景
Jenkins 流水線(Pipeline 是 Jenkins2.X 最核心的特性,幫助 Jenkins 實現從 CI 到 CD 與DevOps 的轉變,可支持復雜流程的編排與可視化) 是一套插件,可通過 Jenkinsfile 執行,支持腳本式(Script)和聲明式(Declarative)兩種,其中腳本式可通過 Groovy 語法編寫執行過程,聲明式需要用 script {}包裹使用 Groovy 語句。
聲明式指令簡介
1.最外層必須由 pipline{ //do something }來進行包裹
2.不需要分號作為分隔符,每個語句獨占一行
3.不能直接使用 groovy 語句(例如循環判斷等),需要被 script {}包裹
- pipeline :聲明其內容為一個聲明式的 pipeline 腳本
- agent:執行節點(支持 any,none,label,docker,dockerfile)
- stages:階段集合,包裹所有的階段(例如:打包,部署等各個階段)
- stage:階段,被 stages 包裹,一個 stages 可以有多個 stage
- steps:步驟,為每個階段的最小執行單元,被 stage 包裹
// 示例
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
}
environment
- 在 pipline 塊內,為全局變量,對所有階段和步驟生效
- 在 stage 階段內,為局部變量,只對階段和步驟生效
withEnv
- 一般使用在子步驟下
// 示例
pipeline {
agent any
stages {
stage('Example') {
environment {
deploy = 'testing'
}
steps {
echo env.NAME
echo "${NAME}"
echo "${deploy}"
echo "$CC"
withEnv(['name=tester']) {
echo "$name"
}
}
}
}
environment {
CC = 'clang'
}
}
post (通常定義在 pipeline 末端)
- always: 始終執行
- aborted: 終止時執行
- failure: 失敗時執行
- success: 成功是執行
- unsuccessful :不成功時執行
- cleanup :其他 post 過程執行完畢后執行
// 示例
pipeline {
agent any
stages {
stage('Example') {
steps {
error '構建失敗:這是一個自定義的錯誤信息'
}
}
}
post {
failure {
echo "this is a error"
}
}
}
when (使用在 stage 內)
- branch: 分支匹配時執行(when { branch 'master' })
- branch: 分支匹配時執行(when { branch 'master' })
- environment: 變量為給定值時執行(when { environment name: 'DEPLOY_ENV', value: 'production' })
- expression: Groovy表達式求值為true時執行(when { expression { return params.DEBUG_BUILD } })
- not: 嵌套條件為false時執行(when { not { branch 'master' } })
- allOf: 嵌套的條件都為真時執行(when { allOf { branch 'master'; environment name: 'DEPLOY_ENV', value: 'production' } })
- anyOf: 至少一個嵌套的條件為真時執行(when { anyOf { branch 'master'; branch 'staging' } })
// 示例
pipeline {
agent any
stages {
stage('DEPLOY_ENV') {
when { environment name: 'DEPLOY_ENV', value: 'production' }
steps {
echo "production 環境正在執行"
}
}
}
}
Parallel (並行)
// 示例
pipeline {
agent any
stages {
stage('Parallel Stage') {
when {
branch 'master'
}
parallel {
stage('testing') {
steps {
echo "depoly testing"
}
}
stage('staging') {
steps {
echo "depoly staging"
}
}
}
}
}
}
options (選項)
- 常用的有 timeout()、retry()
// 示例
pipeline {
agent any
options {
retry(3) // 重試
timeout(time:10, unit:"SECONDS") // 超時
}
stages {
stage('demo'){
steps{
sh 'echo hello'
sleep(15)
}
}
}
}
steps 中的一些操作
- error:拋出異常,中斷整個pipeline
- timeout: 超時
- waitUntil: 循環運行閉包內容,直到返回true,通常與timeout一起使用
- retry:失敗重試
- sleep:睡眠,默認單位秒
// 示例
pipeline{
agent any
stages{
stage('stash'){
parallel('測試') {
stage('輪詢') {
steps{
timeout(time:10, unit:"SECONDS"){
waitUntil{
script{
def rs = sh script: 'docker version', returnStatus: true
return (rs == 0)
}
}
}
}
}
stage('重試') {
steps{
retry(3){
script{
sh script: 'curl https://www.baidu.com', returnStatus: true
}
sleep(3)
}
}
}
stage('錯誤') {
steps{
retry(3){
error("執行失敗")
}
}
}
}
}
}
}
input (暫停執行,等待確認)
// 示例
pipeline {
agent any
stages {
stage('Example') {
input {
message 'Should we continue?'
parameters {
string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
input(message: '是否繼續執行構建', parameters: [ choice(name:'depoly',description:'部署環境',choices:['testing','staging','production'])])
}
}
}
}
script (腳本使用)
// 示例
def test = "test"
pipeline {
agent any
stages {
stage('環境變量') {
steps {
sh 'pwd'
sh "echo ${NAME}"
script {
if ("${NAME}" == "/root/test") {
echo "pass"
} else if ("${NAME}" == "${test}") {
echo "pass"
} else {
error("環境變量有誤 ${NAME}")
}
}
}
}
}
}
腳本式案例
- 最外層有 node{} 包裹
// 示例
def TEST_PROJECT_NAME=""
def deployments = ["testing", "staging", "production"]
def run(stepName) {
retry(3){
TEST_PROJECT_NAME = sh(script: "openssl rand -hex 4",returnStdout: true).trim()
sh (
script: "echo ${TEST_PROJECT_NAME}",
label: "開始 ${stepName} 環境API測試"
)
}
}
node {
deployments.each{ param ->
stage("$param") {
run("$param")
}
}
}
拓展
build
- build 用法,支持觸發另一個 job 構建
// 示例
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
}
}
}
post {
success {
script {
println "執行成功"
jobB = build job: 'pipeline'
println("構建狀態: "+jobB.getResult())
}
}
}
}