git与jenkins的集成

作者 Lu Liang 日期 2018-10-17
git与jenkins的集成

Git和Jenkins的集成中,主要是在git api, git hooks,git alias, git plugin for Jenkins 及Jenkins API 等中间做文章。下面就来介绍一下这几种集成方法。

Use Github Webhooks

很多的project都是利用github来做源代码管理的。 这里我们就利用github的webhook,通过git的push动作来触发Jenkins job的build。

  1. 登陆GitHub设置webhook如下:

  2. 登陆Jenkins Server设置Github Connection信息:

  3. 登陆Jenkins Server修改Job触发条件

上面这种实现方式的特点就是很方便,只需要在网页上面设置几下就可以,但是不够灵活。例如,触发job时无法指定参数等。

Use Git hooks 及 Jenkins API

如果project不是部署在GitHub上,上面的方法就无法使用了,怎么办呢? 这里就需要我们可以自己实现git hooks来调用相应的Jenkins API来实现同样的功能。git的钩子有很多,在.git/hooks下就有一些samples,如下图:

git hooks的具体说明,可以参考最后面列表。 这里使用post-update为例,具体步骤如下:

  1. Copy over your .git directory to your web server

  2. On your local copy, modify your .git/config file and add your web server as a remote:

    [remote "production"]
    url = username@webserver:/path/to/htdocs/.git
  3. On the server, replace .git/hooks/post-update with file below:

    #!/bin/sh
    #
    # 实现项目的部署脚本或者使用Jenkins remote API调用相关的jenkins job
    # 这里使用curl去调用jenkins job
    curl "http://xx.xx.xxx:8080/job/test234/buildWithParameters?token=build_token&Param1=dddddd"
  4. Add execute access to the file (again, on the server):

    chmod +x .git/hooks/post-update
  5. Now, just locally push to your web server and it should automatically update the working copy:

    git push production

Use Git alias 及 Jenkins API

上面的方法需要在git client端和server端进行设置, 好处是可以在server端利用hook做一系列的工作。如果不需要在server端做工作的话,可以使用别名,这样就更加简单。

  1. 设置git alias

    $ git config alias.xpush '!git push $1 $2 && trigger-jenkins.sh'
    # (remember the backslash before the ! if your shell requires it)
    This adds the following to your .git/config file:

    [alias]
    xpush = !git push $1 $2 && trigger-jenkins.sh

    -------------------------------

    # trigger-jenkins.sh 脚本如下:

    #!/bin/sh
    #
    curl "http://xx.xx.xxx:8080/job/test234/buildWithParameters?token=build_token&Param1=dddddd"
  2. 配置remote trigger

  3. 使用git alias,触发jenkins job.

    $ git xpush

    #your changes will be pushed, and then trigger-jenkins.sh will be executed.

Use Git API 及 Jenkins API

与上述的几种方法相比,使用API是最灵活的;可以根据需求,实现各种定制的功能。Git/Jenkins提供了各种相关编程语言的API,这里以python为例,做个介绍。

  1. GitPython
    GitPython 是一个用于操作 Git 版本库的 python 包,它提供了一系列的对象模型(库 - Repo、树 - Tree、提交 - Commit等) 用于操作版本库中的相应对象。

    pip install GitPython

    from git import Repo
    # 创建版本库对象
    repo = git.Repo('./')

    # 版本库是否为空版本库
    repo.bare

    # 当前工作区是否干净
    repo.is_dirty()

    # 版本库中未跟踪的文件列表
    repo.untracked_files

    # 克隆版本库
    repo.clone('clone_path')

    # 压缩版本库到 tar 文件
    with open('repo.tar', 'wb') as fp:
    repo.archive(fp)

    # 新建分支
    repo.create_head('branchname')

    # 查看当前分支
    repo.active_branch

    # 获取默认版本库 origin
    remote = repo.remote()

    # 从远程版本库拉取分支
    remote.pull()

    # 推送本地分支到远程版本库
    remote.push()

    # 重命名远程分支
    # remote.rename('new_origin')
  2. Python-Jenkins
    python-jenkins 通过Jenkins的REST接口管理Jenkins Server,实现对Jenkins, node, view, job的管理。

    # 安装Python-Jenkins
    pip install python-jenkins

    # 登陆 Jenkins Server 或者 Server 版本信息
    import jenkins

    server = jenkins.Jenkins('http://localhost:8080', username='myuser', password='mypassword')
    user = server.get_whoami()
    version = server.get_version()
    print('Hello %s from Jenkins %s' % (user['fullName'], version))

    # 获取 job列表
    jobs = server.get_jobs()
    print jobs

    # 获取指定的job
    my_job = server.get_job_config('cool-job')
    print(my_job) # prints XML configuration

    # 运行job
    server.build_job('empty')

    # 关闭job
    server.disable_job('empty')

    # 复制job
    server.copy_job('empty', 'empty_copy')

    # 激活job
    server.enable_job('empty_copy')

    # 重新配置job
    server.reconfig_job('empty_copy', jenkins.RECONFIG_XML)

    # 删除job
    server.delete_job('empty')
    server.delete_job('empty_copy')

    # 配置,运行带参数的job
    # build a parameterized job
    # requires creating and configuring the api-test job to accept 'param1' & 'param2'
    server.build_job('api-test', {'param1': 'test value 1', 'param2': 'test value 2'})
    last_build_number = server.get_job_info('api-test')['lastCompletedBuild']['number']
    build_info = server.get_build_info('api-test', last_build_number)
    print build_info

    # get all jobs from the specific view
    jobs = server.get_jobs(view_name='View Name')
    print jobs
  3. 联合使用GitPython及Python-Jenkins实现前面的例子

    from git import Repo
    import jenkins

    repo = git.Repo('./')
    remote = repo.remote()
    remote.push()

    server = jenkins.Jenkins('http://localhost:8080', username='myuser', password='mypassword')
    server.build_job('empty')

Current git hooks

Hook Name Invoked By Description Parameters (Number and Description)
applypatch-msg git am Can edit the commit message file and is often used to verify or actively format a patch’s message to a project’s standards. A non-zero exit status aborts the commit. (1) name of the file containing the proposed commit message
pre-applypatch git am This is actually called after the patch is applied, but before the changes are committed. Exiting with a non-zero status will leave the changes in an uncommitted state. Can be used to check the state of the tree before actually committing the changes. (none)
post-applypatch git am This hook is run after the patch is applied and committed. Because of this, it cannot abort the process, and is mainly used for creating notifications. (none)
pre-commit git commit This hook is called before obtaining the proposed commit message. Exiting with anything other than zero will abort the commit. It is used to check the commit itself (rather than the message). (none)
prepare-commit-msg git commit Called after receiving the default commit message, just prior to firing up the commit message editor. A non-zero exit aborts the commit. This is used to edit the message in a way that cannot be suppressed. (1 to 3) Name of the file with the commit message, the source of the commit message (message, template, merge, squash, or commit), and the commit SHA-1 (when operating on an existing commit).
commit-msg git commit Can be used to adjust the message after it has been edited in order to ensure conformity to a standard or to reject based on any criteria. It can abort the commit if it exits with a non-zero value. (1) The file that holds the proposed message.
post-commit git commit Called after the actual commit is made. Because of this, it cannot disrupt the commit. It is mainly used to allow notifications. (none)
pre-rebase git rebase Called when rebasing a branch. Mainly used to halt the rebase if it is not desirable. (1 or 2) The upstream from where it was forked, the branch being rebased (not set when rebasing current)
post-checkout git checkout and git clone Run when a checkout is called after updating the worktree or after git clone. It is mainly used to verify conditions, display differences, and configure the environment if necessary. (3) Ref of the previous HEAD, ref of the new HEAD, flag indicating whether it was a branch checkout (1) or a file checkout (0)
post-merge git merge or git pull Called after a merge. Because of this, it cannot abort a merge. Can be used to save or apply permissions or other kinds of data that git does not handle. (1) Flag indicating whether the merge was a squash.
pre-push git push Called prior to a push to a remote. In addition to the parameters, additional information, separated by a space is passed in through stdin in the form of “ “. Parsing the input can get you additional information that you can use to check. For instance, if the local sha1 is 40 zeros long, the push is a delete and if the remote sha1 is 40 zeros, it is a new branch. This can be used to do many comparisons of the pushed ref to what is currently there. A non-zero exit status aborts the push. (2) Name of the destination remote, location of the destination remote
pre-receive git-receive-pack on the remote repo This is called on the remote repo just before updating the pushed refs. A non-zero status will abort the process. Although it receives no parameters, it is passed a string through stdin in the form of “ “ for each ref. (none)
update git-receive-pack on the remote repo This is run on the remote repo once for each ref being pushed instead of once for each push. A non-zero status will abort the process. This can be used to make sure all commits are only fast-forward, for instance. (3) The name of the ref being updated, the old object name, the new object name
post-receive git-receive-pack on the remote repo This is run on the remote when pushing after the all refs have been updated. It does not take parameters, but receives info through stdin in the form of “ “. Because it is called after the updates, it cannot abort the process. (none)
post-update git-receive-pack on the remote repo This is run only once after all of the refs have been pushed. It is similar to the post-receive hook in that regard, but does not receive the old or new values. It is used mostly to implement notifications for the pushed refs. (?) A parameter for each of the pushed refs containing its name
pre-auto-gc git gc –auto Is used to do some checks before automatically cleaning repos. (none)
post-rewrite git commit –amend, git-rebase This is called when git commands are rewriting already committed data. In addition to the parameters, it receives strings in stdin in the form of “ “. (1) Name of the command that invoked it (amend or rebase)

Refer to