Jenkinsfile使用

2018-08-21 17:19 更新

本節(jié)基于“ Jenkins入門”中介紹的信息,并介紹更有用的步驟,常見模式,并演示一些非平凡的Jenkinsfile示例。

創(chuàng)建一個(gè)Jenkinsfile被檢入源代碼控制,提供了一些直接的好處:

  • Pipeline上的代碼審查/迭代
  • Pipeline的審計(jì)跟蹤
  • Pipeline的唯一真實(shí)來源,可以由項(xiàng)目的多個(gè)成員查看和編輯。

Pipeline支持兩種語法:Declarative(在Pipeline 2.5中引入)和Scripted Pipeline。兩者都支持建立連續(xù)輸送Pipeline。兩者都可以用于在Web UI或者a中定義一個(gè)流水線Jenkinsfile,盡管通常被認(rèn)為是Jenkinsfile將文件創(chuàng)建并檢查到源代碼控制庫(kù)中的最佳做法。

創(chuàng)建Jenkins文件

如“ 入門” 部分所述,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)告和文件歸檔。

測(cè)試

運(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語法。

管道高級(jí)語法

字符串插值

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)重要。

工作環(huán)境

Jenkins  Pipeline通過全局變量公開環(huán)境變量,該變量env可從任何地方獲得Jenkinsfile。假設(shè)Jenkins主機(jī)正在運(yùn)行,在本地主機(jī):8080 / pipeline-syntax / globals#env中記錄了可從Jenkins Pipeline中訪問的環(huán)境變量的完整列表 localhost:8080,其中包括:

BUILD_ID

當(dāng)前版本ID,與Jenkins版本1.597+中創(chuàng)??建的構(gòu)建相同,為BUILD_NUMBER

JOB_NAME

此構(gòu)建項(xiàng)目的名稱,如“foo”或“foo / bar”。

JENKINS_URL

完整的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}"
}

設(shè)置環(huán)境變量

根據(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。

參數(shù)

聲明式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è)代理

在所有以前的例子中,只使用了一個(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í)行批處理腳本.

可選步驟參數(shù)

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 */

高級(jí)腳本管道

腳本Pipeline是 基于Groovy 的領(lǐng)域?qū)S谜Z言,大多數(shù)Groovy語法可以在腳本Pipeline中使用而無需修改。

同時(shí)執(zhí)行

上面的例子在線性系列中的兩個(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í)行。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)