4

只是一个小问题:是否可以通过 python 脚本或命令行(而不是通过 Web 界面)强制在 Buildbot 中构建?

谢谢!

4

2 回答 2

4

如果您在 master.cfg 中配置了 PBSource,则可以从命令行发送更改:

buildbot sendchange --master {MASTERHOST}:{PORT} --auth {USER}:{PASS}
    --who {USER} {FILENAMES..}
于 2013-09-18T21:05:07.837 回答
3

您可以使用 urllib2 或 requests 库制作 python 脚本来模拟 POST 到 Web UI

import urllib2
import urllib
import cookielib
import uuid
import unittest
import sys
from StringIO import StringIO


class ForceBuildApi():
    MAX_RETRY = 3

    def __init__(self, server):
        self.server = server
        cookiejar = cookielib.CookieJar()
        self.urlOpener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar))

    def login(self, user, passwd):
        data = urllib.urlencode(dict(username=user,
                                     passwd=passwd))
        url = self.server + "login"
        request = urllib2.Request(url, data)
        res = self.urlOpener.open(request).read()
        if res.find("The username or password you entered were not correct") > 0:
            raise Exception("invalid password")

    def force_build(self, builder, reason, **kw):
        """Create a buildbot build request
        several attempts are created in case of errors
        """
        reason = reason + " ID="+str(uuid.uuid1())
        kw['reason'] = reason
        data_str = urllib.urlencode(kw)
        url = "%s/builders/%s/force" % (self.server, builder)
        print url
        request = urllib2.Request(url, data_str)
        file_desc = None
        for i in xrange(self.MAX_RETRY):
            try:
                file_desc = self.urlOpener.open(request)
                break
            except Exception as e:
                print >>sys.stderr, "error when doing force build", e
        if file_desc is None:
            print >>sys.stderr, "too many errors, giving up"
            return None
        for line in file_desc:
            if 'alert' in line:
                print >>sys.stderr, "invalid arguments", url, data_str
                return None

            if 'Authorization Failed' in line:
                print >>sys.stderr, "Authorization Failed"
                return
        return reason


class ForceBuildApiTest(unittest.TestCase):

    def setUp(self):
        from mock import Mock  # pip install mock for test
        self.api = ForceBuildApi("server/")
        self.api.urlOpener = Mock()
        urllib2.Request = Mock()
        uuid.uuid1 = Mock()
        uuid.uuid1.return_value = "myuuid"
        sys.stderr = StringIO()

    def test_login(self):
        from mock import call
        self.api.login("log", "pass")
        self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
        req = urllib2.Request.call_args_list
        self.assertEquals([call('server/login', 'passwd=pass&username=log')], req)

    def test_force(self):
        from mock import call
        self.api.urlOpener.open.return_value = ["blabla"]
        r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
        self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
        req = urllib2.Request.call_args_list
        self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid&param2=bar&param1=foo')], req)
        self.assertEquals(r, "reason ID=myuuid")

    def test_force_fail1(self):
        from mock import call
        self.api.urlOpener.open.return_value = ["alert bla"]
        r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
        self.assertEquals(len(self.api.urlOpener.open.call_args_list), 1)
        req = urllib2.Request.call_args_list
        self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid&param2=bar&param1=foo')], req)
        self.assertEquals(sys.stderr.getvalue(), "invalid arguments server//builders/builder1/force reason=reason+ID%3Dmyuuid&param2=bar&param1=foo\n")
        self.assertEquals(r, None)

    def test_force_fail2(self):
        from mock import call

        def raise_exception(*a, **kw):
            raise Exception("oups")

        self.api.urlOpener.open = raise_exception
        r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
        req = urllib2.Request.call_args_list
        self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid&param2=bar&param1=foo')], req)
        self.assertEquals(sys.stderr.getvalue(), "error when doing force build oups\n"*3 + "too many errors, giving up\n")
        self.assertEquals(r, None)

    def test_force_fail3(self):
        from mock import call
        self.api.urlOpener.open.return_value = ["bla", "blu", "Authorization Failed"]
        r = self.api.force_build("builder1", reason="reason", param1="foo", param2="bar")
        req = urllib2.Request.call_args_list
        self.assertEquals([call('server//builders/builder1/force', 'reason=reason+ID%3Dmyuuid&param2=bar&param1=foo')], req)
        self.assertEquals(sys.stderr.getvalue(), "Authorization Failed\n")
        self.assertEquals(r, None)

if __name__ == '__main__':
    unittest.main()
于 2014-01-02T16:35:47.740 回答