在gitlab通过webhook触发Jenkins的job中用script获取当前分支

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。感谢以上作者的文章!如果你有更巧妙的方法,欢迎留言告诉我!

发布了69 篇原创文章 · 获赞 55 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/xmh19936688/article/details/104953608
今日推荐