在詹金斯构建期间防止水银推送

Prevent mercurial push during a jenkins build

我有一个 jenkins 作业,它在 mercurial 回购上运行一些测试,如果成功的话,用 'stable' 标签标记本地回购,然后将其推回主回购。我遇到的问题是,如果有人在构建 运行 时推送变更集,那么我无法推送 'stable' 标签。

我想知道是否有办法在构建 运行 时将远程存储库设置为只读,然后在构建完成后将其设置为 'push-able'?

谢谢, 瓦卡

阻止推送可能不是您想要的(而且这几乎是不可能的)。像 Mercurial 或 git 这样的 DVCS 的承诺是没有锁定——这是向前迈出的一步。

您是否考虑过让 Jenkins 在合并之前拉取和更新?您仍然可以标记正确的修订版。像这样:

  1. jenkins 检查代码并记下它正在构建的修订 ID
  2. jenkins 进行构建、运行测试等,一切顺利
  3. jenkins 执行 hg pull 从服务器获取最新的
  4. 詹金斯做了 hg tag -m "build number $BUILD_NUMBER" --revision X --force stable
  5. 詹金斯做了一个 hg push

然后(几乎)在最后一次拉取、标记和推送之间没有时间,但标记仍在实际构建的修订版上——因为您保存了第一次拉取时的修订版哈希 ID。

我一直在寻找类似的东西。在我们的案例中,Jenkins 正在执行合并,运行 一套广泛的测试,一旦它们全部通过,将合并的代码推送回存储库。因此,如果开发人员在作业执行时进行推送(无法进行最终推送),则需要约 1 小时并失败。

我找不到现成的解决方案,所以最后写了一个 mercurial hook,它在允许推送之前检查作业是否正在构建(使用 REST API)。

您需要访问您的远程 Mercurial 存储库,但除此之外,它并不太复杂。


将以下内容添加到 your-remote-repo/.hg/hgrc

[hooks]
pretxnchangegroup.DisablePushDuringJenkinsBuild= python:.hg/disable_push_if_building_hook.py:check_jenkins
[jenkins]
url=http://path-to-jenkins
jobs=jenkins-job-name[,comma-separated, for-multiple, jobs]

并确保此 python 脚本位于 your-remote-repo/.hg/

import json, urllib2
from mercurial import util   

TEN_SECONDS = 10

def check_jenkins(ui, repo, node, **kwargs):

    jenkins_url = ui.config('jenkins', 'url', default=None, untrusted=False)
    jenkins_jobs = ui.config('jenkins', 'jobs', default=None, untrusted=False)

    if not jenkins_url:
        raise util.Abort('Jenkins hook has not been configured correctly. Cannot find Jenkins url in .hg/hgrc.')

    if not jenkins_jobs:
        raise util.Abort('Jenkins hook has not been configured correctly. Cannot find Jenkins jobs in .hg/hgrc.')

    jenkins_jobs = [x.strip() for x in jenkins_jobs.split(',')]

    for job in jenkins_jobs:
        job_url = jenkins_url + '/job/' + job + '/lastBuild/api/json'
        ui.write('Checking if job is running at URL: %s\n' % job_url)

        try:
            job_metadata = json.load(urllib2.urlopen(job_url, timeout = TEN_SECONDS))

            if 'building' in job_metadata and job_metadata['building']:
                raise util.Abort('Jenkins build "%s" is in progress. Pushing is disabled until it completes.' % job_metadata['fullDisplayName'])

        except urllib2.URLError, e:
            raise util.Abort('Error while trying to poll Jenkins: "%s"' % e)

    return False # Everything is OK, push can be accepted