一、介紹
官方文檔
Jenkins Pipeline(或簡稱為“Pipeline”,大寫字母為“P”)是一套插件,支持在Jenkins中實現和集成連續交付管道。
持續交付(CD)管道是將軟件從版本控制直接傳遞給用戶和客戶的過程的自動表達。對軟件的每次更改(在源代碼管理中提交)都會在發布的過程中經歷一個復雜的過程。此過程涉及以可靠且可重復的方式構建軟件,以及通過多個測試和部署階段推進構建的軟件(稱為“構建”)。
Pipeline提供了一組可擴展的工具,用於通過管道域特定語言(Pipeline domain-specific language)語法“作為代碼”對簡單到復雜的傳輸管道進行建模。
Jenkins管道的定義被寫入一個文本文件(稱為Jenkinsfile),該文件又可以提交給項目的源代碼控制庫。這是“作為代碼的管道”的基礎;將CD管道視為應用程序的一部分,以便像任何其他代碼一樣進行版本控制和審查。
學習pipeline語法可以查看官方文檔也可以在經典UI中選擇幫助
兩種Pipeline語法的選擇
選擇
Jenkinsfile可以使用兩種語法編寫 - Declarative和Scripted。聲明式和腳本化管道的構造從根本上不同。
早期Jenkins是使用Java實現的,所以在很早的時候就引入了groovy作為DSL,管理員可以使用groovy來實現一些自動化和高級的管理功能。因為groovy引擎已經集成到Jenkins,所以在pipeline一開始很自然就使用groovy來編寫Jenkinsfile。也就是腳本式pipeline。但是groovy畢竟是一種語言,且學習成本很高。這個時候聲明式的pipeline就出現了,主要是為了降低入門的難度,提高分工協作的能力。
作為官方推薦的語法,Declarative Pipeline也獲得了很多官方的支持,比如blue ocean。即使聲明式語法還沒有支持的功能,也可以在聲明式里直接調用腳本。
所以Declarative Pipeline是個不錯的選擇。
區別
在Declarative Pipeline語法中,pipeline塊定義了整個管道中完成的所有工作。表達式與Groovy語法基本相同,區別在於:
Pipeline的頂級必須是一個塊,特別是:pipeline {}
沒有分號作為語句分隔符。 每個聲明都必須獨立
塊只能由章節,指令,步驟或賦值語句組成。(Sections, Directives, Steps, or assignment statements.)
屬性引用語句被視為無參數方法調用。 例如,輸入被視為輸入()
可以使用聲明性指令生成器(Declarative Directive Generator)來幫助您開始配置聲明性管道中的指令和部分。
聲明式pipeline
pipeline {
agent any
stages {
stage('Example Build') {
steps {
echo 'Hello World'
}
}
stage('Example Deploy') {
when {
branch 'production'
environment name: 'DEPLOY_TO', value: 'production'
}
steps {
echo 'Deploying'
}
}
}
}
腳本式pipeline
node {
stage('Example') {
if (env.BRANCH_NAME == 'master') {
echo 'I only execute on the master branch'
} else {
echo 'I execute elsewhere'
}
}
}
一個基本的Jenkinsfile
大多數項目並不止三個步驟,不過這創建、測試、交付是最基本的工作流。
pipeline {
agent any
stages {
stage('Build') {
steps {
echo 'Building..'
}
}
stage('Test') {
steps {
echo 'Testing..'
}
}
stage('Deploy') {
steps {
echo 'Deploying....'
}
}
}
}
章節Sections
通常包含一個或多個Directives or Steps。
關鍵字 | 意義 | 常見選項 |
---|---|---|
agent | 指定整個管道或特定階段在Jenkins環境中的執行位置,具體取決於代理程序部分的放置位置。 該部分必須在管道塊內的頂層定義,但階段級使用是可選的。 | any, none, label, node, docker, dockerfile |
post | post部分定義了一個或多個附加步驟,這些步驟在完成Pipeline或stage的運行時運行(取決於Pipeline中post部分的位置)。 | always, changed, fixed, regression, aborted, failure, success, unstable, cleanup |
stages | 包含一個或多個階段指令的序列 | |
steps | 定義了在給定階段指令中要執行的一系列一個或多個步驟。 |
指令Directives
關鍵字 | 意義 | 常見選項 |
---|---|---|
environment | 指定一系列鍵 - 值對,它們將被定義為所有 具體取決於環境指令在管道中的位置。 | credentials() |
options | 允許在Pipeline中配置特定於Pipeline的選項。 | buildDiscarder, checkoutToSubdirectory, disableConcurrentBuilds, newContainerPerStage, overrideIndexTriggers, preserveStashes, quietPeriod, retry, skipDefaultCheckout,skipStagesAfterUnstable, timeout,timestamps |
parameters | 提供了用戶在觸發Pipeline時應提供的參數列表 | string, test, booleanParam, choice, file, password |
triggers | 定義了重新觸發管道的自動方式。 對於與GitHub或BitBucket等源集成的管道,可能不需要觸發器,因為基於webhooks的集成可能已經存在。 目前可用的觸發器是cron,pollSCM和upstream。 | cron, pollSCM, upstream |
stage | 位於階段部分。Pipeline所做的所有實際工作都將包含在一個或多個階段指令中。 | |
tools | 定義用於自動安裝和放置PATH的工具的部分。 如果未指定agent none,則忽略此項。引用的工具名必須在Manage Jenkins → Global Tool Configuration中預定義 |
maven,jdk,gradle |
input | 允許您使用輸入步驟提示輸入。 在應用any選項之后,在進入stage的agent或評估其狀態之前,stage將暫停。 如果輸入被批准,則stage將繼續。 作為輸入提交的一部分提供的任何參數將在該階段的其余部分的環境中可用 | message, id, ok, submitter, submitterParameter, parameters |
when | 允許Pipeline根據給定的條件確定是否應該執行該階段。 when指令必須至少包含一個條件。 | beforeAgent, branch, buildingTag, changelog, changeset, changeRequest, environment, equal, expression, tag, not, allof, anyof |
串行stages - Sequential Stages
聲明性管道中的階段可以按順序聲明要在其中運行的嵌套階段的列表。
請注意,一個stage有且僅有一個steps, parallel, or stages,最后一個是連續階段。
stages中各stage的階段不能包含parallel或stage(s)本身,但它們允許使用階段的所有其他功能,包括agent, tool, when。
並行stages - Parallel
使用parallel可以在不同的代理商同時執行某項任務,和lable的區別在於,lable是線性的,比如完成一項測試需要30MIN分別在windows上執行和linux上執行需要60M。使用parallel可以同時在兩個代理上運行測試。
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 .. */
}
}
}
二、環境變量
pipeline {
agent any
environment {
PROJECT_HOME='/var/lib/jenkins/workspace/xxx/projdir'
}
stages{
stage("test_env"){
environment {
DEBUG_FLAGS = '-g'
}
steps {
echo "工作目錄是:$PROJECT_HOME"
echo "內置的環境變量可以直接使用 $BUILD_ID"
echo "內置的環境變量可以直接使用 $WORKSPACE"
echo "stage設置的環境變量只能在本塊中引用 $DEBUG_FLAGS"
}
}
}
}
自定義變量
1、environment頂層pipeline塊中使用的指令將應用於管道中的所有步驟,在stage中設置的只應用於stage內。
2、和shell的變量引用一樣,使用雙引號應用變量,單引號為字符串。
3、在腳本式pipeleine中使用withEnv
內置環境變量
系統內置的環境變量可以直接引用。系統的內置環境變量記錄在$ {YOUR_JENKINS_URL}--項目-- pipeline-syntax
流水線語法-- globals全局變量參考--env部分。
BUILD_ID | 當前的版本ID,與在Jenkins版本1.597+中創建的版本相同,為BUILD_NUMBER |
---|---|
BUILD_NUMBER | 當前的內部版本號,例如“ 153” |
BUILD_TAG | jenkins字符串-$ {JOB_NAME}-$ {BUILD_NUMBER}。方便放入資源文件,JAR文件等中,以便於識別 |
BUILD_URL | 可以找到此構建結果的URL(例如http:// buildserver / jenkins / job / MyJobName / 17 /) |
EXECUTOR_NUMBER | 標識執行此構建的當前執行程序(在同一計算機的執行程序中)的唯一編號。這是您在“構建執行器狀態”中看到的數字,除了該數字從0而不是1開始 |
JAVA_HOME | 如果您的作業配置為使用特定的JDK,則此變量設置為指定JDK的JAVA_HOME。設置此變量后,PATH也將更新為包括JAVA_HOME的bin子目錄 |
JENKINS_URL | Jenkins的完整URL,例如https://example.com:port/jenkins/(注意:僅在“系統配置”中設置了Jenkins URL時可用) |
JOB_NAME | 此生成的項目的名稱,例如“ foo”或“ foo / bar”。 |
NODE_NAME | 當前構建正在其上運行的節點的名稱。將主節點設置為“ master”。 |
WORKSPACE | 工作區的絕對路徑 |
動態設置環境變量
環境變量可以在運行時設置,可以由Shell腳本(sh
),Windows批處理腳本(bat
)和PowerShell腳本(powershell
)的狀態returnStatus
或結果returnStdout
作為變量值。
使用returnStdout
尾隨空格時,會將空白附加到返回的字符串中。使用.trim()
刪除它。
Jenkinsfile(聲明性管道)
pipeline {
agent any
environment {
// Using returnStdout
CC = """${sh(
returnStdout: true,
script: 'echo "clang"'
)}"""
// Using returnStatus
EXIT_STATUS = """${sh(
returnStatus: true,
script: 'exit 1'
)}"""
}
stages {
stage('Example') {
environment {
DEBUG_FLAGS = '-g'
}
steps {
sh 'printenv'
}
}
}
}
三、參數
參數和環境變量不一樣的地方是,參數可以在pipeline運行時指定,就是類似交互的意思。例如有字符串參數,布爾選擇參數,下拉多選參數等。可以通過UI設置,也可以卸載pipeline代碼中,在代碼片段生成器中找到properties
步驟參考。
pipeline{
agent any
parameters {
string(name: 'userName', defaultValue: 'Anthony', description: 'please give a name')
choice(name: 'version', choices: ['1.1', '1.2', '1.3'], description: 'select the version to test')
booleanParam(name: 'is_boy', defaultValue: true, description: 'you is boy or not')
}
stages {
stage('test') {
steps{
script {
sh "java -version"
}
}
}
}
}
字符串參數
定義一個字符串參數,用戶可以在Jenkins UI上輸入字符串,常見使用這個參數的場景有,用戶名,收件人郵箱,文件網絡路徑,主機名稱的或者url等。
pipeline {
agent any
parameters {
string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: '')
}
}
布爾值參數
定義一個布爾類型參數,用戶可以在Jenkins UI上選擇是還是否,選擇是表示代碼會執行這部分,如果選擇否,會跳過這部分。一般需要使用布爾值的場景有,執行一些特定集成的腳本或則工作,或者事后清除環境,例如清楚Jenkins的workspace這樣的動作。
pipeline {
agent any
parameters {
booleanParam(name: 'DEBUG_BUILD', defaultValue: true, description: '')
}
}
文本參數
文本(text)的參數就是支持寫很多行的字符串,這個變量我好像沒有使用過,例如想給發送一段歡迎的消息,你可以采用text的參數
pipeline {
agent any
parameters {
text(name: 'Welcome_text', defaultValue: 'One\nTwo\nThree\n', description: '')
}
}
選擇參數
選擇(choice)的參數就是支持用戶從多個選擇項中,選擇一個值用來表示這個變量的值。工作中常用的場景,有選擇服務器類型,選擇版本號等。
pipeline {
agent any
parameters {
choice(name: 'ENV_TYPE', choices: ['test', 'dev', 'product'], description: 'test means test env,….')
}
}
文件參數
文件(file)參數就是在Jenkins 參數化構建UI上提供一個文件路徑的輸入框,Jenkins會自動去你提供的網絡路徑去查找並下載。一般伴隨着還有你需要在Pipleline代碼中寫解析文件。也有這樣場景,這個構建job就是把一個war包部署到服務器上特定位置,你可以使用這個文件參數。
pipeline {
agent any
parameters {
name: 'FILE', description: 'Some file to upload')
}
}
密碼參數
密碼(password)參數就是在Jenkins 參數化構建UI提供一個暗文密碼輸入框,例如,我需要在一些linux機器上做自動化操作,需要提供機器的用戶名和密碼,由於密碼涉及安全問題,一般都采用暗文顯示,這個時候你就不能用string類型參數,就需要使用password參數類型。
pipeline {
agent any
parameters {
password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A secret password')
}
}
使用
stages {
stage('test_params') {
steps {
echo "pv_name: ${params.pv_name}"
echo "pv_volume: ${params.pv_volume}"
echo "dp_name: ${params.dp_name}"
echo "dp_port: ${params.dp_port}"
}
}
}
四、憑證
憑證類型
SSH用戶私鑰 | 處理 SSH公/私鑰對憑據,您可以從中指定: |
---|---|
密鑰文件變量 | 將綁定到這些憑據的環境變量的名稱。Jenkins實際上將此臨時變量分配給SSH公鑰/私鑰對身份驗證過程中所需的私鑰文件的安全位置。 |
密碼短語變量 | 將綁定到 與SSH公鑰/私鑰對關聯的密碼短語的環境變量的名稱 。 |
用戶名變量 | 將綁定到與SSH公鑰/私鑰對關聯的用戶名的環境變量的名稱。 |
憑證 | 選擇存儲在Jenkins中的SSH公/私鑰憑證。該字段的值是憑證ID,jenkins將其寫入已生成的代碼段。 |
證書 | 處理PKCS#12證書,您可以從中指定: |
密鑰庫變量 | 將綁定到這些憑據的環境變量的名稱。Jenkins實際上將此臨時變量分配給證書認證過程中所需的證書密鑰庫的安全位置。 |
密碼變量 | 將綁定到與證書關聯的密碼的環境變量的名稱。 |
別名變量 | 將綁定到與證書關聯的唯一別名的環境變量的名稱。 |
憑證 | 選擇存儲在Jenkins中的憑證憑證。該字段的值是憑證ID,jenkins將其寫入已生成的代碼段。 |
Docker客戶端證書 | 處理Docker主機證書身份驗證。 |
使用憑證
- credentials helper方法只支持Secret text、Username with password、Secretfile三種憑證。
- credentialsId()支持ssh憑據、docker憑據等。
- 使用Jenkins的代碼段生成器功能,可以通過Jenkins的經典UI進行訪問。
已訪問gitlab倉庫為例,如果憑證配置的username password 模式,就需要在environment中使用credentials()如果是SSH認證方式就可以在stage里使用credentialsId()
credentials helper方法
秘密文本
environment {
AWS_ACCESS_KEY_ID = credentials('jenkins-aws-secret-key-id')
AWS_SECRET_ACCESS_KEY = credentials('jenkins-aws-secret-access-key')
}
用戶密碼
environment {
BITBUCKET_COMMON_CREDS = credentials('jenkins-bitbucket-common-creds')
}
秘密文件
environment {
// The MY_KUBECONFIG environment variable will be assigned
// the value of a temporary file. For example:
// /home/user/.jenkins/workspace/cred_test@tmp/secretFiles/546a5cf3-9b56-4165-a0fd-19e2afe6b31f/kubeconfig.txt
MY_KUBECONFIG = credentials('my-kubeconfig')
}
credentialsId()
stages{
stage("Git clone"){
steps {
//拉取front代碼
echo '正在拉取代碼...'
dir("projdir/front"){
git credentialsId: '10e76a46-7872-4266-9e32-e0dbcb7df1c2', url: 'http://10.60.1.90/front.git',branch:'dev',changelog:true
}
//拉取middle代碼
dir("projdir/middle"){
git credentialsId: '10e76a46-7872-4266-9e32-e0dbcb7df1c2', url: 'http://10.60.1.90/middle.git',branch:'dev',changelog:true
}
}
}
合並憑證
使用代碼段生成器,可以使用withCredentials( … ) { … }
通過執行以下操作在一個步驟中提供多個憑據:
- 在Jenkins主頁(即Jenkins經典UI的儀表板)中,單擊您的Pipeline項目/項目的名稱。
- 在左側,單擊“ 管道語法”,並確保“ 代碼段生成器” 鏈接在左上角為粗體。(如果沒有,請單擊其鏈接。)
- 在“ 樣本步驟”字段中,選擇withCredentials:將憑證綁定到變量。
- 單擊綁定下的添加。
withCredentials( … ) { … }
從下拉列表中選擇要添加到步驟的憑據類型。- 指定憑證綁定詳細信息。
- 對每個(一組)憑據重復單擊``單擊添加 ...''(上方)以添加到
withCredentials( … ) { … }
步驟。 - 單擊生成管道腳本以生成最后
withCredentials( … ) { … }
代碼段。
示例
五、post 鈎子
post 步驟在Jenkins pipeline語法中是可選的,包含的是整個pipeline或階段完成后一些附加的步驟。
比如我們希望整個pipeline執行完成之后或pipeline的某個stage執行成功后發生一封郵件,就可以使用post,可
理解為”鈎子“
pipeline {
agent any
stages {
stage('Test') {
steps {
sh 'make check'
}
}
}
post {
always {
script{
if (currentBuild.currentResult == "ABORTED" || currentBuild.currentResult == "FAILURE" || currentBuild.currentResult == "UNSTABLE" ){
slackSend channel: "#機器人", message: "Build failure: ${env.JOB_NAME} -- No: ${env.BUILD_NUMBER}, please check detail in email!"
} else {
slackSend channel: "#機器人", message: "Build Success: ${env.JOB_NAME} -- Build No: ${env.BUILD_NUMBER}, please check on http://www.yourwebsite.com"
}
}
}
failure {
mail to: team@example.com, subject: 'The Pipeline failed :('
}
}
}
根據 pipeline 或階段的完成狀態,post 部分分成多種條件塊,包括:
-
always: 無論pipeline或者stage的執行結果如何,此塊中的預置操作都會執行。
-
changed:只有當pipeline或者stage的執行后,當前狀態與之前發生了改變時,此塊中的預置操作才會執行。
-
fixed:前一次運行為不穩定狀態或者失敗狀態,而且本次運行成功結束,這兩個條件同時滿足時,此塊中的預置操作才會執行。
-
regression: 本次運行狀態為不穩定狀態,失敗狀態或者是中止狀態,而且前一次運行成功結束,這兩個條件同時滿足時,此塊中的預置操作才會執行。
-
aborted:當前pipeline或者stage的狀態為aborted時,此塊中的預置操作才會執行。通常是由於流水線被手工中會導致此狀態產生,而產生此狀態后,通常在Jenkins的UI界面會顯示為灰色。
-
failure:當前pipeline或者stage的狀態為failed時,此塊中的預置操作才會執行。而產生此狀態后,通常在Jenkins的UI界面會顯示為紅色。
-
success:當前pipeline或者stage的狀態為success時,此塊中的預置操作才會執行。而產生此狀態后,通常在Jenkins的UI界面會顯示為綠色。
-
unstable: 當前pipeline或者stage的狀態為unstable時,此塊中的預置操作才會執行。通常情況下測試失敗或者代碼規約的違反都會導致此狀態產生,而產生此狀態后,通常在Jenkins的UI界面會顯示為黃色。
-
unsuccessful:當前pipeline或者stage的狀態不是success時,此塊中的預置操作才會執行。
-
cleanup:無論pipeline或者stage的狀態為何種狀態,在post中的其他的條件預置操作執行之后,此塊中的預置操作就會執行。
六、使用多個代理
agent lable可以使用不同的jenkins代理來執行構建,多用在跨平台的測試。如下:
構建結果將在“測試”階段期間在兩個后續代理(分別標記為“ linux”和“ windows”)上重用。
Jenkinsfile(聲明性管道)
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'
}
}
}
}
}
七、簡寫
管道遵循Groovy語言約定,允許在方法參數周圍省略括號。語法[key1: value1, key2: value2]
git([url: 'git://example.com/amazing-project.git', branch: 'master'])
簡寫 git url: 'git://example.com/amazing-project.git', branch: 'master'
為方便起見,當調用僅采用一個參數(或僅采用一個強制性參數)的步驟時,可以省略參數名稱,例如
sh 'echo hello' /* short form */
sh([script: 'echo hello']) /* long form */