Pipeline as Code是Jenkins 2.0版本的精華所在,是幫助Jenkins實現從CI到CD華麗轉身的關鍵工具。node
所謂Pipeline,簡單來講,就是一套運行於Jenkins上的工做流框架,將本來獨立運行於單個或者多個節點的任務鏈接起來,實現單個任務難以完成的複雜發佈流程android
Pipeline的實現方式是一套Groovy DSL(相似Gradle),任何發佈流程均可以表述爲一段Groovy腳本,而且Jenkins支持從代碼庫直接讀取腳本,從而實現了Pipeline as Code的理念。git
注: 本文首發於 My 公衆號 CodeSheep ,可 長按 或 掃描 下面的 當心心 來訂閱 ↓ ↓ ↓github
這裏主要結合我本身對傳統Jenkins Job使用的一些痛點來講:docker
傳統的Jenkins Job難以靈活高效地並行(Job間、節點間、任務間、甚至任務內四個維度的並行)shell
傳統的Jenkins Job日益失控的趨勢讓咱們措手不及,Job太多,CI腳本太離散,維護成本實在過高了,並且很危險,一單Jenkins Server掛了,一切都Game Over了編程
新拉分支的分支代碼CI部署太麻煩了c#
傳統的Jenkins Job顯示真的是不太直觀啊windows
我想這些理由應該足以讓咱們把目光轉向Jenkins2.0的Pipeline!bash
Pipeline的功能和優勢:
Pipeline爲用戶設計了三個最最基本的概念:
一個典型的Stage View以下圖所示:
從圖中能夠十分方便地看到哪些Stage經過,哪些Stage失敗,以及構建的時間。
Jenkins2.0的Pipeline搭建使用的是Groovy腳本,經過Groovy腳本實現工做流管理的步驟以下:
實際上更經常使用的是MultiBranch Pipeline,上面的圖中截圖沒有包含,但與普通Pipeline基本相似。
上圖的實例腳本以下:
node {
stage('Checkout Code') { // for display purposes
// Get some code from a GitHub repository
git 'https://github.com/jglick/simple-maven-project-with-tests.git'
}
stage('Build') {
// Run the maven build
if (isUnix()) {
sh "'${MAVEN_HOME}/bin/mvn' -Dmaven.test.failure.ignore clean package"
} else {
bat(/"${MAVEN_HOME}\bin\mvn" -Dmaven.test.failure.ignore clean package/)
}
}
stage('Unit test') {
junit '**/target/surefire-reports/TEST-UT.xml'
archive 'target/*.jar'
}
}
複製代碼
構建過程的stage View以下:
很明顯能夠看出,這裏顯示的和Groovy腳本中格式化的代碼是一致的,會實時顯示各個工做流的執行進度和結果,直觀易懂。鼠標移上去,能看到日誌信息的縮略圖,單擊能夠調到對應stage的console中。
總而言之,一切都是那麼地優雅!
在這裏總結一下Pipeline中的關鍵DSL語法,利用Groovy對其進行組合能夠完成任何一項複雜的CI/CD流程,熟悉它們大有裨益。
歸檔文件,舉例:
archiveArtifacts 'target/*.jar'
複製代碼
執行windows平臺下的批處理文件,如
bat "call example.bat"
複製代碼
觸發構建一個jenkins job,如
build 'TEST_JOB'
複製代碼
從SCM系統中checkout repo,如:
checkout([$class: 'SubversionSCM', additionalCredentials: [], excludedCommitMessages: '', excludedRegions: '', excludedRevprop: '', excludedUsers: '', filterChangelog: false, ignoreDirPropChanges: false, includedRegions: '', locations: [[credentialsId: '30e6c1e5-1035-4bdd-8a44-05ba8f885158', depthOption: 'infinity', ignoreExternalsOption: true, local: '.', remote: 'svn://xxxxxx']], workspaceUpdater: [$class: 'UpdateUpdater']])
複製代碼
從workspace中刪除當前目錄
切換目錄,如
dir('/home/jenkins') { // 切換到/home/jenkins目錄中作一些事情
// some block
}
複製代碼
打印信息,如 echo 'hello world'
利用Jenkins發送郵件,內容、主題全均可以自定義,如
emailext body: 'Subject_test', subject: 'Subject_test', to: 'hansonwang99@163.com.cn'
// 郵件的正文body,主題subject,收件人to等能夠進行自定義
複製代碼
拋出一個錯誤信號,能夠自行在代碼裏拋出,如 error 'read_error'
檢查工做空間某個路徑裏是否存在某個file,舉例:
fileExists '/home/test.txt' // 檢查是否存在test.txt
複製代碼
等待外界用戶的交互輸入,舉例:
input message: '', parameters: [string(defaultValue: '默認值', description: '版本號', name: 'version')] // 在某一步驟,等待用戶輸入version參數才能往下執行
複製代碼
用於判斷當前任務是否運行於Unix-like節點上,舉例:
def flag = isUnix()
if( flag == false ) { // 能夠據此進行判斷
echo "not run on a unix node !"
}
複製代碼
調用一個外部groovy腳本,舉例:
load 'D:\\jenkins\\workspace\\test.groovy'
複製代碼
分配節點給某個任務運行,舉例:
node('節點標籤') { // 在對應標籤的節點上運行某項任務
Task()
}
複製代碼
並行地執行任務,能夠說是最實用高效的工具了,舉例:
parallel( //並行地執行android unit tests和android e2e tests兩個任務
'android unit tests': {
runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-android-docker-unit-tests.sh', '--privileged --rm')
},
'android e2e tests': {
runCmdOnDockerImage(androidImageName, 'bash /app/ContainerShip/scripts/run-ci-e2e-tests.sh --android --js', '--rm')
}
)
複製代碼
設置Job的屬性,舉例:
properties([parameters([string(defaultValue: '1.0.0', description: '版本號', name: 'VERSION')]), pipelineTriggers([])]) // 爲job設置了一個VERSION參數
複製代碼
pwd 顯示當前目錄
readFile
從工做空間中讀取文件,舉例:
def editionName = readFile '/home/Test/exam.txt'
複製代碼
重複body內代碼N次,舉例:
retry(10) {
// some block
}
複製代碼
執行shell腳本,如:sh "sh test.sh"
延時,如延時2小時:sleep time: 2, unit: 'HOURS'
建立任務的stage,舉例:
stage('stage name') {
// some block
}
複製代碼
存放文件爲後續構建使用,舉例:
dir('target') {
stash name: 'war', includes: 'x.war'
}
複製代碼
將stash步驟中存放的文件在當前工做空間中重建,舉例:
def deploy(id) {
unstash 'war'
sh "cp x.war /tmp/${id}.war"
}
複製代碼
時間限制,舉例
timeout(time: 4, unit: 'SECONDS') {
// some block
}
複製代碼
用於在控制檯加時間戳,舉例:
timestamps {
// some block
}
複製代碼
建立文件,舉例:
touch file: 'TEST.txt', timestamp: 0
複製代碼
解壓文件,舉例:
unzip dir: '/home/workspace', glob: '', zipFile: 'TEST.zip'
複製代碼
檢查給定的文件是否包含一個有效的Declarative Pipeline,返回T或者F
validateDeclarativePipeline '/home/wospace'
複製代碼
等待,直到條件知足
waitUntil {
// some block
}
複製代碼
使用憑據
withCredentials([usernameColonPassword(credentialsId: 'mylogin', variable: 'USERPASS')]) {
sh ''' set +x curl -u $USERPASS https://private.server/ > output '''
}
複製代碼
設置環境變量,注意近本次運行有效!
withEnv(['MYTOOL_HOME=/usr/local/mytool']) {
sh '$MYTOOL_HOME/bin/start'
}
複製代碼
寫文件到某個路徑
writeFile file: '/home/workspace', text: 'hello world'
複製代碼
寫JSON文件,用法基本同上
建立zip文件
zip dir: '/home/workspace', glob: '', zipFile: 'TEST.zip'
複製代碼
自定義工做空間,在其中作一些工做,效果相似於Dir命令,舉例:
ws('/home/jenkins_workspace') {
// some block
}
複製代碼
做者更多的SpringBt實踐文章在此:
若是有興趣,也能夠抽點時間看看做者一些關於容器化、微服務化方面的文章: