《Jenkins 2.x實踐指南》讀書筆記-觸發Pipeline執行

[TOC]git

1. 時間觸發

時間觸發是指定義一個時間,時間到了就觸發pipeline執行。在Jenkins pipeline中使用trigger指令來定義時間觸發。web

trigger指令只能被定義在pipeline塊下,Jenkins內置支持cron、pollSCM,upstream三種方式。其餘方式能夠經過插件來實現。正則表達式

1.1 定時執行:cron

定時執行就像cronjob,一到時間點就執行。它的使用場景一般是執行一些週期性的job,如每夜構建。express

pipeline {
    agent any
    triggers {
        cron('0 0 * * *')
    }
    stages {
        stage('Nightly build') {
            steps {
                echo "這是一個耗時的構建,天天凌晨執行"
            }
        }
     }
}

Jenkins trigger cron語法採用的是UNIX cron語法(有些細微的區別)。一條cron包含5個字段,使用空格或Tab分隔,格式爲:MINUTE HOUR DOM MONTH DOW。每一個字段的含義爲:json

  • MINUTE:一小時內的分鐘,取值範圍爲0∼59。
  • HOUR:一天內的小時,取值範圍爲0∼23。
  • DOM:一個月的某一天,取值範圍爲1∼31。
  • MONTH:月份,取值範圍爲1∼12。
  • DOW:星期幾,取值範圍爲0∼7。0和7表明星期天。
    還可使用如下特殊字符,一次性指定多個值。
  • *:匹配全部的值
  • M-N:匹配M 到N 之間的值。
  • M-N/X or*/X:指定在M 到N 範圍內,以X值爲步長。
  • A,B,· · ·,Z:使用逗號枚舉多個值。

在一些大型組織中,會同時存在大量的同一時刻執行的定時任務,好比N 個半夜零點(0 0 * * *)執行的任務。這樣會產生負載不均衡。在Jenkins trigger cron語法中使用「H」字符來解決這一問題,H表明hash。對於不必準確到零點0分執行的任務,cron能夠這樣寫:H 0 * * *,表明在零點0分至,H表明hash。表明在零點0分至零點59分之間任何一個時間點執行。安全

須要注意的是,H應用在DOM(一個月的某一天)字段時會有不許確的狀況,由於10月有31天,而2月倒是28天。app

Jenkins trigger cron還設計了一些人性化的別名:@yearly@annually@monthly@weekly@daily@midnight@hourly。例如,@hourlyH * * * *相同,表明一小時內的任什麼時候間;@midnight實際上表明在半夜12:00到凌晨2:59之間的某個時間。其餘別名不多有應用場景。curl

1.2 輪詢代碼倉庫:pollSCM

輪詢代碼倉庫是指按期到代碼倉庫詢問代碼是否有變化,若是有變化就執行。ide

pipeline {
    agent any
    triggers {
        // 每分鐘判斷一次代碼是否有變化
        pollSCM("H/1 * * * *")
    }
}

事實上,若是代碼有變化,最好的方式是代碼倉庫主動通知Jenkins,而不是Jenkins頻繁去代碼倉庫檢查。那這種方式存在的意義是什麼?
在一些特殊狀況下,好比外網的代碼倉庫沒法調用內網的Jenkins,或者反過來,則會採用這種方式。gitlab

2. 事件觸發

事件觸發就是發生了某個事件就觸發pipeline執行。這個事件能夠是你能想到的任何事件。好比手動在界面上觸發、其餘Job主動觸發、HTTP API Webhook觸發等。

2.1 由上游任務觸發:upstream

當B任務的執行依賴A任務的執行結果時,A就被稱爲B的上游任務。在Jenkins 2.22及以上版本中,trigger指令開始支持upstream類型的觸發條件。upstream的做用就是能讓B pipeline自行決定依賴哪些上游任務。

// job1和job2都是任務名
triggers {
    upstream(upstreamProjects: "job1,job2", threshold: hudson.model.Result.SUCCESS)
}

當upstreamProjects參數接收多個任務時,使用,分隔。threshold參數是指上游任務的執行結果是什麼值時觸發。hudson.model.Result是一個枚舉,包括如下值:

  • ABORTED:任務被手動停止。
  • FAILURE:構建失敗。
  • SUCCESS:構建成功。
  • UNSTABLE:存在一些錯誤,但不至於構建失敗。
  • NOT_BUILT:在多階段構建時,前面階段的問題致使後面階段沒法執行。

注意:須要手動觸發一次任務,讓Jenkins加載pipeline後,trigger指令纔會生效。

2.2 GitLab通知觸發

GitLab通知觸發是指當GitLab發現源代碼有變化時,觸發Jenkins執行構建。

由GitLab主動通知進行構建的好處是顯而易見的,這樣很容易就解決了咱們以前提到的輪詢代碼倉庫時「多久輪詢一次」的問題,實現每一次代碼的變化都對應一次構建。

2.2.1 在pipeline中實現GitLab trigger

GitLab插件上實現了基於GitLab的trigger。如下是具體使用方法。

pipeline {
    agent any
    triggers {
        gitlab(triggerOnPush: true,
            triggerOnMergeRequest: true,
            branchFilterType: "All",
            secretToken: "t8vcxwuza023ehzcftzr5a74vkpto6xr")
    }
    stages {
        stage('build') {
            steps {
                echo 'Hello World from gitlab trigger'
            }
        }
    }
}

secretToken使用隨機字符串生成器生成便可。若是Jenkins在內網使用,而且安全性有必定的保障,咱們能夠將secretToken定義爲一個Jenkins全局變量,供全部的項目使用。這樣作就不用爲每一個項目從新生成token了。
GitLab trigger方法有不少參數可配置,下面簡單介紹一些經常使用的參數。

  • triggerOnPush:當GitLab觸發push事件時,是否執行構建。
  • triggerOnMergeRequest:當GitLab觸發mergeRequest事件時,是否執行構建。
  • branchFilterType:只有符合條件的分支纔會被觸發。必選,不然沒法實現觸發。能夠設置的值有:
    • NameBasedFilter:基於分支名進行過濾,多個分支名使用逗號分隔。
    • RegexBasedFilter:基於正則表達對分支名進行過濾。
    • All:全部分支都會被觸發。
  • includeBranchesSpec:基於branchFilterType值,輸入指望包括的分支的規則。
  • excludeBranchesSpec:基於branchFilterType值,輸入指望排除的分支的規則。

2.2.2 使用Generic Webhook Trigger插件實現觸發

安裝 Generic Webhook Trigger 插件(下文使用 GWT 簡稱)後,Jenkins 會暴露一個 API:
<JENKINS URL>/generic-webhook-trigger/invoke,即由GWT插件來處理此API的請求。

如下爲使用token示例:

pipeline {
    agent any
    triggers {
        GenericTrigger(
            genericVariables: [
                [
                    key: 'ref', 
                    value: '$.ref'
                ]
            ],

            token: 'secret',

            causeString: 'Triggered on $ref',
            printContributedVariables: true,
            printPostContent: true
        )
    }
    stages {
        stage("Some step") {
            steps {
                sh "echo $ref"
                sh "printenv"
            }
        }
    }
}

curl -X POST -H "Content-Type: application/json" -d '{"ref": "ref/heads/master"}' -s https://jenkins.utcook.com/generic-webhook-trigger/invoke?token=secret

觸發結果

GenericTrigger觸發條件由GWT插件提供。此觸發條件能夠說是GWT的全部內容。
能夠將GenericTrigger觸發條件分爲5部分,這樣更易於理解各參數的做用。

  • 從HTTP POST請求中提取參數值。
  • token,GWT插件用於標識Jenkins項目的惟一性。
  • 根據請求參數值判斷是否觸發Jenkins項目的執行。
  • 日誌打印控制。
  • Webhook響應控制。

一個HTTP POST請求能夠從三個維度提取參數,即POST body、URL參數和header
GWT插件提供了三個參數分別對這三個維度的數據進行提取。

  1. genericVariables:提取POST body中的參數。
genericVariables: [
                [key: 'ref', value: '$.ref'],
                [key: 'before',
                 value: '$.before',
                 expressionType: 'JSONPath',
                 regexpFilter: '',
                 defaultValue: ''
                ]
            ]
  • value:JSONPath表達式,或者XPath表達式,取決於expressionType參數值,用於從POST body中提取值。
  • key:從POST body中提取出的值的新變量名,可用於pipeline其餘步驟。
  • expressionType:可選,value的表達式類型,默認爲JSONPath。當請求爲XML內容時,必須指定XPath值。
  • defaultValue:可選,當提取不到值,且defaultValue不爲空時,則使用defaultValue做爲返回值。
  • regexpFilter:可選,過濾表達式,對提取出來的值進行過濾。regexpFilter作的事情其實就是string.replaceAll(regexpFilter,"");。string是從HTTP請求中提取出來的值。
  1. genericRequestVariables:從URL參數中提取值。
genericRequestVariables: [
                [key: 'requestWithNumber', regexpFilter: '[^0-9]'],
                [key: 'requestWithString', regexpFilter: '']
            ]
  • key:提取出的值的新變量名,可用於pipeline其餘步驟。
  • regexpFilter:對提取出的值進行過濾。
  1. genericHeaderVariables:從HTTP header中提取值。
    genericHeaderVariables: [
                [key: 'headerWithNumber', regexpFilter: '[^0-9]'],
                [key: 'headerWithString', regexpFilter: '']
            ]

genericHeaderVariables的用法與genericRequestVariables同樣,區別是它是從HTTP header中提取值的。

根據請求參數值判斷是否觸發Jenkins項目執行

GWT並不僅是根據token值來判斷是否觸發,還能夠根據咱們提取出的值進行判斷。示例以下:

GenericTrigger(
            genericVariables: [
                [key: 'refValue', value: '$.ref'],
            ],

            token: env.JOB_NAME,

            regexpFilterText: '$refValue',
            regexpFilterExpression: 'refs/heads/(master|dev)'
        )
  • regexpFilterText:須要進行匹配的key。例子中,咱們使用從POST body中提取出的refValue變量值。
  • regexpFilterExpression:正則表達式。
    若是regexpFilterText參數的值符合regexpFilterExpression參數的正則表達式,則觸發執行。

控制打印內容

打印日誌有助於調試。GWT插件提供了三個參數。

  • printPostContent:布爾值,將Webhook請求信息打印到日誌上。
  • printContributedVariables:布爾值,將提取後的變量名及變量值打印出來。
  • causeString:字符串類型,觸發緣由,能夠直接引用提取後的變量,如 causeString:'Triggered on $msg'

控制響應

  • silentResponse:布爾類型,在正常狀況下,當Webhook請求成功後,GWT插件會返回HTTP 200狀態碼和觸發結果給調用方。可是當silentResponse設置爲true時,就只返回HTTP 200狀態碼,不返回觸發結果。

3. 開發推送代碼觸發jenkins構建實戰

3.1 安裝Jenkins插件

3.2 建立項目

新建gitlab項目

新建gitlab項目

新建jenkins項目

新建jenkins項目

gltlab設置集成webhook
gltlab設置集成webhook

webhook測試報錯
webhook測試報錯

以上報錯須要進行jenkins安裝設置,取消勾選「CSRF Protection」
jenkins安全設置

3.3 將構建狀態信息推送到Gitlab

jenkins構建項目後,能夠將構建的狀態信息推送到gitlab的pipeline中,而且點擊pipeline會自動跳轉到jenkins的構建頁面下。

首先gitlab倉庫的管理賬戶下生成我的訪問token。

生成gitlab token

而後在jenkins內,進入"Manage Jenkins" → "Configure System",頁面中找到「Gitlab」,並添加gitlab和token憑證信息。

添加gitlab

添加gitlab token憑證

修改Jenkinsfile,若是jenkins中未觸發過任務,第一次須要手動觸發,之後gitlab內代碼的修改會自動觸發,並將運行結果提交到gitlab pipeline中。

完整的Jenkinsfile

pipeline {
    agent any
    triggers {
        gitlab(triggerOnPush: true,
            triggerOnMergeRequest: true,
            branchFilterType: "All",
            secretToken: "t8vcxwuza023ehzcftzr5a74vkpto6xr")
    }
    stages {
        stage('build') {
            steps {
                echo 'Hello World from gitlab trigger'
            }
        }
    }
    post {
        failure {
            updateGitlabCommitStatus name: "build", state: "failed"
        }
        success {
            updateGitlabCommitStatus name: "build", state: "success"
        }
    }
    options {
        gitLabConnection("gitlab")
    }
}

修改Jenkinsfile添加post到gitlab

gitlab倉庫的pipeline中可查看到構建信息。
《Jenkins 2.x實踐指南》讀書筆記-觸發Pipeline執行

參考資料:
[1] 《Jenkins 2.x實戰指南》
[2] https://jenkins.io/zh/doc/book/pipeline/syntax/
[3] https://jenkins.io/zh/doc/pipeline/steps/
[4] https://blog.csdn.net/xiashei/article/details/88694027

相關文章
相關標籤/搜索