webhook給jenkins發了什麼
gitlab觸發jenkins的job是通過webhook完成的,也就是一次http請求,請求體在jenkins的job的ConsoleOutput中可以看到。長這樣子(網頁上的json是一坨,這裏format了一下):
GenericWebhookEnvironmentContributor
Received:
{
"object_kind": "push",
"before": "0000000000000000000000000000000000000000",
"after": "1d09c45658d42cd6c8c41d3370d4a2d5b46690b4",
"ref": "refs/heads/xxx-dev",
"checkout_sha": "1d09c45658d42cd6c8c41d3370d4a2d5b46690b4",
"message": null,
"user_id": 142,
"user_name": "xxx",
"user_email": "[email protected]",
"project_id": 531,
"repository": {
"name": "test",
"url": "ssh://[email protected].*.*:*/test.git",
"description": "test",
"homepage": "http://172.16.*.*:*/test",
"git_http_url": "http://172.16.*.*:*/test.git",
"git_ssh_url": "ssh://[email protected].*.*:*/test.git",
"visibility_level": 10
},
"commits": [
{
"id": "1d09c45658d42cd6c8c41d3370d4a2d5b46690b4",
"message": "test\n",
"timestamp": "2020-03-17T21:34:10+08:00",
"url": "http://172.16.*.*:*/test/commit/1d09c45658d42cd6c8c41d3370d4a2d5b46690b4",
"author": {
"name": "xxx",
"email": "[email protected]"
}
}
],
"total_commits_count": 1
}
找對分支名了嗎
在單元測試之類的觸發中,通常需要跑pipeline的分支是不可預知的,這就需要在jenkins腳本中進行動態獲取。我們可以注意到上面有一個字段ref
的值爲refs/heads/xxx-dev
,看上就是他了,但實際上這是不能用的,我們先試一下。
在jenkinsJob的Post content parameters
中配置了ref後,就可以獲取到ref的值:
node(label) {
println ref
}
這裏println
是groovy的語法,jenkins的PiplineScript基本上就是groovy。
然後我們來試一下直接用ref當分支:
node(label) {
stage('test') {
dir('/home/jenkins/agent/workspace/test') {
git branch: ref, credentialsId: 'xxxx', url: 'http://172.16.*.*:*/test.git'
}
}
}
然後會看到這樣的報錯:
using GIT_ASKPASS to set credentials
> git fetch --tags --force --progress -- http://172.16.*.*:*/test.git +refs/heads/*:refs/remotes/origin/* # timeout=10
> git rev-parse refs/remotes/origin/refs/heads/xxx-dev^{commit} # timeout=10
> git rev-parse refs/remotes/origin/origin/refs/heads/xxx-dev^{commit} # timeout=10
> git rev-parse origin/refs/heads/xxx-dev^{commit} # timeout=10
...
ERROR: Couldn't find any revision to build. Verify the repository and branch configuration for this job.
第一種方法調整分支
我們有兩個辦法讓jenkins拿到準確分支,先說第一種,checkout的方式:
node(label) {
stage('test') {
dir('/home/jenkins/agent/workspace/test') {
git branch: 'develop', credentialsId: 'xxxx', url: 'http://172.16.*.*:*/test.git'
sh '''
git checkout ${ref##*/}
'''
}
}
}
在script裏調用sh來實現checkout,這裏${ref##*/}
就是xxx-dev
,如果寫${ref#*/}
就是heads/xxx-dev
,如果寫${ref}
就是refs/heads/xxx-dev
但是有些情況下,checkout會報錯:
+ git checkout xxx-dev
error: The following untracked working tree files would be overwritten by checkout:
vendor/github.com/PuerkitoBio/purell/.gitignore
vendor/github.com/PuerkitoBio/purell/.travis.yml
...
這時我們就該考慮能不能讓jenkins上來就在指定分支上工作呢,其實是可以的,我們來看第二種方法。
第二種方法調整分支
第二種方法就是藉助groovy代碼對ref
變量做手腳,簡單思路就是用split
函數將字符串分割,然後取後面的部分。
ref.split("refs/heads/")
這裏有點奇怪的是,他的返回值首先是個引用類型,如果直接println ref.split("refs/heads/")
會看到[Ljava.lang.String;@618657aa
,所以不能直接ref.split("refs/heads/")[0]
:
def arr = ref.split("refs/heads/") as List
第二點比較奇怪的是,在其他語言比如C#、Java、go中,這種情況返回的數組只包含一個元素,而這裏返回的卻是兩個元素:
def arr = ref.split("refs/heads/") as List
println arr
// [, xxx-dev]
所以我們需要取arr[1]
來拿到分支名,這樣一來我們就可以將上面的腳本改寫:
node(label) {
stage('test') {
dir('/home/jenkins/agent/workspace/test') {
def arr = ref.split("refs/heads/") as List
def currentBranch = arr[1]
git branch: currentBranch, credentialsId: 'xxxx', url: 'http://172.16.*.*:*/test.git'
}
}
}
感謝
參考文章:我在這裏看到了split
;在這裏看到了as LinkedList
。感謝以上作者的文章!如果你有更巧妙的方法,歡迎留言告訴我!