本節(jié)基于“ Jenkins入門”中介紹的信息,并介紹更有用的步驟,常見模式,并演示一些非平凡的Jenkinsfile示例。
創(chuàng)建一個(gè)Jenkinsfile被檢入源代碼控制,提供了一些直接的好處:
Pipeline支持兩種語法:Declarative(在Pipeline 2.5中引入)和Scripted Pipeline。兩者都支持建立連續(xù)輸送Pipeline。兩者都可以用于在Web UI或者a中定義一個(gè)流水線Jenkinsfile,盡管通常被認(rèn)為是Jenkinsfile將文件創(chuàng)建并檢查到源代碼控制庫(kù)中的最佳做法。
如“ 入門” 部分所述,a Jenkinsfile
是一個(gè)包含Jenkins Pipeline定義的文本文件,并被檢入源代碼控制??紤]以下Pipeline,實(shí)施基本的三階段連續(xù)輸送Pipeline。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test') {
steps {
echo 'Testing..'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
stage('Build') {
echo 'Building....'
}
stage('Test') {
echo 'Building....'
}
stage('Deploy') {
echo 'Deploying....'
}
}
并非所有的Pipeline都將具有相同的三個(gè)階段,但是對(duì)于大多數(shù)項(xiàng)目來說,這是一個(gè)很好的起點(diǎn)。以下部分將演示在Jenkins的測(cè)試安裝中創(chuàng)建和執(zhí)行簡(jiǎn)單的Jenkins。
假設(shè)已經(jīng)有一個(gè)項(xiàng)目的源代碼管理庫(kù),并且已經(jīng)在Jenkins中按照這些說明定義了一個(gè)Jenkins 。
使用文本編輯器,理想的是支持Groovy語法突出顯示的文本編輯器, Jenkinsfile在項(xiàng)目的根目錄中創(chuàng)建一個(gè)新的。
上述聲明性Pipeline示例包含實(shí)現(xiàn)連續(xù)傳送Pipeline的最小必要結(jié)構(gòu)。需要的代理指令指示Jenkins為Pipeline分配一個(gè)執(zhí)行器和工作區(qū)。沒有agent指令,不僅聲明Pipeline無效,所以不能做任何工作!默認(rèn)情況下,該agent偽指令確保源存儲(chǔ)庫(kù)已被檢出并可用于后續(xù)階段的步驟
該階段的指令,和步驟的指令也需要一個(gè)有效的聲明Pipeline,因?yàn)樗麄冎甘綣enkins如何執(zhí)行并在哪個(gè)階段應(yīng)該執(zhí)行。
要使用Scripted Pipeline進(jìn)行更高級(jí)的使用,上面的示例node是為Pipeline分配執(zhí)行程序和工作空間的關(guān)鍵第一步。在本質(zhì)上,沒有node Pipeline不能做任何工作!從內(nèi)部node,業(yè)務(wù)的第一個(gè)順序是檢查此項(xiàng)目的源代碼。由于Jenkinsfile直接從源代碼控制中抽取,所以Pipeline提供了一種快速簡(jiǎn)便的方式來訪問源代碼的正確版本
Jenkinsfile (Scripted Pipeline)
node {
checkout scm
/* .. snip .. */
}
:該
checkout
步驟將檢出從源控制代碼; scm
是一個(gè)特殊變量,指示checkout
步驟克隆觸發(fā)此Pipeline運(yùn)行的特定修訂。
對(duì)于許多項(xiàng)目,Pipeline“工作”的開始就是“建設(shè)”階段。通常,Pipeline的這個(gè)階段將是源代碼組裝,編譯或打包的地方。的Jenkinsfile是不為現(xiàn)有的構(gòu)建工具,如GNU/Make,Maven, Gradle,等的替代品,而是可以被看作是一個(gè)膠層結(jié)合項(xiàng)目的開發(fā)生命周期的多個(gè)階段(建設(shè),測(cè)試,部署等)一起。
Jenkins有一些插件,用于調(diào)用幾乎任何一般使用的構(gòu)建工具,但是這個(gè)例子將只是make從shell步驟(sh)調(diào)用。該sh步驟假定系統(tǒng)是基于Unix / Linux的,因?yàn)閎at可以使用基于Windows的系統(tǒng)。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'make'
archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
}
}
}
}
:該
sh
步驟調(diào)用該make
命令,只有在命令返回零退出代碼時(shí)才會(huì)繼續(xù)。任何非零退出代碼將失敗Pipeline。
:
archiveArtifacts
捕獲與include pattern(**/target/*.jar
)匹配的文件,并將它們保存到Jenkins主文件以供以后檢索。
存檔工件不能替代使用諸如Artifactory或Nexus之類的外部工件存儲(chǔ)庫(kù),只能用于基本報(bào)告和文件歸檔。
運(yùn)行自動(dòng)化測(cè)試是任何成功的連續(xù)傳送過程的重要組成部分。因此,Jenkins有許多插件提供的測(cè)試記錄,報(bào)告和可視化設(shè)備 。在基本層面上,當(dāng)有測(cè)試失敗時(shí),讓Jenkins在Web UI中記錄報(bào)告和可視化的故障是有用的。下面的示例使用junit由JUnit插件提供的步驟。
在下面的示例中,如果測(cè)試失敗,則Pipeline被標(biāo)記為“不穩(wěn)定”,如Web UI中的黃色球。根據(jù)記錄的測(cè)試報(bào)告,Jenkins還可以提供歷史趨勢(shì)分析和可視化。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Test') {
steps {
/* `make check` returns non-zero on test failures,
* using `true` to allow the Pipeline to continue nonetheless
*/
sh 'make check || true'
junit '**/target/*.xml'
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
/* .. snip .. */
stage('Test') {
/* `make check` returns non-zero on test failures,
* using `true` to allow the Pipeline to continue nonetheless
*/
sh 'make check || true'
junit '**/target/*.xml'
}
/* .. snip .. */
}
:使用內(nèi)聯(lián)shell conditional(
sh 'make || true'
)確保該 sh
步驟始終看到零退出代碼,從而使該junit
步驟有機(jī)會(huì)捕獲和處理測(cè)試報(bào)告。下面的“ 處理故障”部分將詳細(xì)介紹其他方法。
:
junit
捕獲并關(guān)聯(lián)與包含pattern(**/target/*.xml
)匹配的JUnit XML文件
部署可能意味著各種步驟,具體取決于項(xiàng)目或組織的要求,并且可能是從構(gòu)建的工件發(fā)送到Artifactory服務(wù)器,將代碼推送到生產(chǎn)系統(tǒng)的任何步驟。
在Pipeline示例的這個(gè)階段,“構(gòu)建”和“測(cè)試”階段都已成功執(zhí)行。實(shí)際上,“部署”階段只能在上一階段成功完成,否則Pipeline將早退。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Deploy') {
when {
expression {
currentBuild.result == null || currentBuild.result == 'SUCCESS'
}
}
steps {
sh 'make publish'
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
/* .. snip .. */
stage('Deploy') {
if (currentBuild.result == null || currentBuild.result == 'SUCCESS') {
sh 'make publish'
}
}
/* .. snip .. */
}
:訪問該
currentBuild.result
變量允許Pipeline確定是否有任何測(cè)試失敗。在這種情況下,值將是 UNSTABLE
。
假設(shè)一切都在Jenkins Pipeline示例中成功執(zhí)行,每個(gè)成功的Pipeline運(yùn)行都會(huì)將存檔的關(guān)聯(lián)構(gòu)建工件,報(bào)告的測(cè)試結(jié)果和完整的控制臺(tái)輸出全部放在Jenkins中。
腳本Pipeline可以包括條件測(cè)試(如上所示),循環(huán),try / catch / finally塊甚至函數(shù)。下一節(jié)將詳細(xì)介紹這種高級(jí)腳本Pipeline語法。
Jenkins Pipeline使用與Groovy相同的規(guī)則 進(jìn)行字符串插值。Groovy的字符串插值支持可能會(huì)讓很多新來的語言感到困惑。雖然Groovy支持使用單引號(hào)或雙引號(hào)聲明一個(gè)字符串,例如:
def singlyQuoted = 'Hello'
def doublyQuoted = "World"
只有后一個(gè)字符串將支持基于dollar-sign($
)的字符串插值,例如:
def username = 'Jenkins'
echo 'Hello Mr. ${username}'
echo "I said, Hello Mr. ${username}"
會(huì)導(dǎo)致:
Hello Mr. ${username}
I said, Hello Mr. Jenkins
了解如何使用字符串插值對(duì)于使用一些管道更高級(jí)的功能至關(guān)重要。
Jenkins Pipeline通過全局變量公開環(huán)境變量,該變量env
可從任何地方獲得Jenkinsfile
。假設(shè)Jenkins主機(jī)正在運(yùn)行,在本地主機(jī):8080 / pipeline-syntax / globals#env中記錄了可從Jenkins Pipeline中訪問的環(huán)境變量的完整列表 localhost:8080
,其中包括:
當(dāng)前版本ID,與Jenkins版本1.597+中創(chuàng)??建的構(gòu)建相同,為BUILD_NUMBER
此構(gòu)建項(xiàng)目的名稱,如“foo”或“foo / bar”。
完整的Jenkins網(wǎng)址,例如example.com:port/jenkins/(注意:只有在“系統(tǒng)配置”中設(shè)置了Jenkins網(wǎng)址時(shí)才可用)
參考或使用這些環(huán)境變量可以像訪問Groovy Map中的任何鍵一樣完成 ,例如:
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Example') {
steps {
echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
}
根據(jù)是否使用Declarative或Scripted Pipeline,在Jenkins Pipeline中設(shè)置環(huán)境變量是不同的。
聲明式Pipeline支持環(huán)境指令,而Scripted Pipeline的用戶必須使用該withEnv步驟。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
environment {
CC = 'clang'
}
stages {
stage('Example') {
environment {
DEBUG_FLAGS = '-g'
}
steps {
sh 'printenv'
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
/* .. snip .. */
withEnv(["PATH+MAVEN=${tool 'M3'}/bin"]) {
sh 'mvn -B verify'
}
}
:
environment
頂級(jí)pipeline
塊中使用的指令將適用于Pipeline中的所有步驟。
:在一個(gè)
environment
意圖中定義的一個(gè)指令stage
將僅將給定的環(huán)境變量應(yīng)用于該過程中的步驟stage
。
聲明式Pipeline支持開箱即用的參數(shù),允許Pipeline在運(yùn)行時(shí)通過parameters指令接受用戶指定的參數(shù)。使用腳本Pipeline配置參數(shù)是通過properties步驟完成的,可以在代碼段生成器中找到。
如果您使用“使用構(gòu)建參數(shù)”選項(xiàng)來配置Pipeline以接受參數(shù),那么這些參數(shù)可作為params 變量的成員訪問。
假設(shè)一個(gè)名為“Greeting”的String參數(shù)已經(jīng)在配置中 Jenkinsfile,它可以通過${params.Greeting}以下方式訪問該參數(shù):
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
parameters {
string(name: 'Greeting', defaultValue: 'Hello', description: 'How should I greet the world?')
}
stages {
stage('Example') {
steps {
echo "${params.Greeting} World!"
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
properties([parameters([string(defaultValue: 'Hello', description: 'How should I greet the world?', name: 'Greeting')])])
node {
echo "${params.Greeting} World!"
}
聲明性Pipeline默認(rèn)支持robust失敗處理經(jīng)由其post section,其允許聲明許多不同的“post conditions”,例如:always,unstable,success,failure,和 changed?!?Pipeline語法”部分提供了有關(guān)如何使用各種帖子條件的更多詳細(xì)信息。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'make check'
}
}
}
post {
always {
junit '**/target/*.xml'
}
failure {
mail to: team@example.com, subject: 'The Pipeline failed :('
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
node {
/* .. snip .. */
stage('Test') {
try {
sh 'make check'
}
finally {
junit '**/target/*.xml'
}
}
/* .. snip .. */
}
但是腳本Pipeline依賴于Groovy的內(nèi)置try/ catch/ finally該Pipeline的執(zhí)行過程中處理故障的語義。
在上面的測(cè)試示例中,該sh步驟被修改為從不返回非零退出代碼(sh 'make check || true')。這種方法雖然有效,但是意味著以下階段需要檢查currentBuild.result以確定是否有測(cè)試失敗。
處理這種情況的另一種方法是保留Pipeline故障的早期退出行為,同時(shí)仍然junit有機(jī)會(huì)捕獲測(cè)試報(bào)告,是使用一系列try/ finally塊:
在所有以前的例子中,只使用了一個(gè)代理。這意味著Jenkins將分配一個(gè)可用的執(zhí)行器,無論它是如何標(biāo)記或配置的。這不僅可以行為被覆蓋,但Pipeline允許從內(nèi)利用Jenkins環(huán)境中的多個(gè)代理商相同 Jenkinsfile,可為更高級(jí)的使用情況,如執(zhí)行有幫助建立跨多個(gè)平臺(tái)/測(cè)試。
在下面的示例中,“構(gòu)建”階段將在一個(gè)代理上執(zhí)行,并且構(gòu)建的結(jié)果將在“測(cè)試”階段中分別標(biāo)記為“l(fā)inux”和“windows”的兩個(gè)后續(xù)代理程序中重用。
Jenkinsfile (Declarative Pipeline)
pipeline {
agent none
stages {
stage('Build') {
agent any
steps {
checkout scm
sh 'make'
stash includes: '**/target/*.jar', name: 'app'
}
}
stage('Test on Linux') {
agent {
label 'linux'
}
steps {
unstash 'app'
sh 'make check'
}
post {
always {
junit '**/target/*.xml'
}
}
}
stage('Test on Windows') {
agent {
label 'windows'
}
steps {
unstash 'app'
bat 'make check'
}
post {
always {
junit '**/target/*.xml'
}
}
}
}
}
Toggle Scripted Pipeline (Advanced)
Jenkinsfile (Scripted Pipeline)
stage('Build') {
node {
checkout scm
sh 'make'
stash includes: '**/target/*.jar', name: 'app'
}
}
stage('Test') {
node('linux') {
checkout scm
try {
unstash 'app'
sh 'make check'
}
finally {
junit '**/target/*.xml'
}
}
node('windows') {
checkout scm
try {
unstash 'app'
bat 'make check'
}
finally {
junit '**/target/*.xml'
}
}
}
:該
stash
步驟允許捕獲與包含模式(**/target/*.jar
)匹配的文件,以在同一管道中重用。一旦Pipeline完成執(zhí)行,垃圾文件將從Jenkins主站中刪除。
:
agent
/中的參數(shù)node
允許任何有效的Jenkins標(biāo)簽表達(dá)式。有關(guān)詳細(xì)信息,請(qǐng)參閱Pipeline語法部分。
:
unstash
將從Jenkins主機(jī)中檢索名為“藏書”的管道當(dāng)前工作空間。
: 該
bat
腳本允許在基于Windows的平臺(tái)上執(zhí)行批處理腳本.
Pipeline遵循Groovy語言約定,允許在方法參數(shù)中省略括號(hào)。
許多Pipeline步驟還使用命名參數(shù)語法作為使用Groovy創(chuàng)建Map的簡(jiǎn)寫,它使用語法[key1: value1, key2: value2]。發(fā)表如下功能等同的語句:
git url: 'git://example.com/amazing-project.git', branch: 'master'
git([url: 'git://example.com/amazing-project.git', branch: 'master'])
為方便起見,當(dāng)僅調(diào)用一個(gè)參數(shù)(或只有一個(gè)必需參數(shù))時(shí),可能會(huì)省略參數(shù)名稱,例如:
sh 'echo hello' /* short form */
sh([script: 'echo hello']) /* long form */
腳本Pipeline是 基于Groovy 的領(lǐng)域?qū)S谜Z言,大多數(shù)Groovy語法可以在腳本Pipeline中使用而無需修改。
上面的例子在線性系列中的兩個(gè)不同平臺(tái)上運(yùn)行測(cè)試。在實(shí)踐中,如果make check 執(zhí)行需要30分鐘完成,“測(cè)試”階段現(xiàn)在需要60分鐘才能完成!
幸運(yùn)的是,Pipeline具有內(nèi)置功能,用于并行執(zhí)行Scripted Pipeline的部分,在適當(dāng)命名的parallel步驟中實(shí)現(xiàn)。
重構(gòu)上述示例以使用parallel步驟:
Jenkinsfile (Scripted Pipeline)
stage('Build') {
/* .. snip .. */
}
stage('Test') {
parallel linux: {
node('linux') {
checkout scm
try {
unstash 'app'
sh 'make check'
}
finally {
junit '**/target/*.xml'
}
}
},
windows: {
node('windows') {
/* .. snip .. */
}
}
}
而不是在“l(fā)inux”和“windows”標(biāo)簽的節(jié)點(diǎn)上執(zhí)行測(cè)試,它們現(xiàn)在將在Jenkins環(huán)境中存在必需容量的情況下并行執(zhí)行。
更多建議: