buildbot 中没有 grid/console 个视图,构建视图始终为空,尽管构建成功

No grid/console views in buildbot, build view always empty, despite successful build

我已经安装了 buildbot -- 一个 docker 图像带有主图像,另一个图像带有工人图像。允许容器间联网,共享同一个网络;我也有一个 gitea 实例,并安装了 buildbot_gitea 插件。

到目前为止,我得到了一个小项目 运行 make 在推送之后,buildbot 正确地向 gitea 报告成功(我可以从日志中看出,gitea 也显示回购协议上的绿色支票图像)。

然而,

主日志上唯一看起来奇怪的是周期性超时消息,一些连接断开消息:

2020-03-21 12:11:26+0000 [-] Timing out client: IPv4Address(type='TCP', host='172.27.0.1', port=56388)
2020-03-21 12:11:26+0000 [-] Timing out client: IPv4Address(type='TCP', host='172.27.0.1', port=56380)
2020-03-21 12:11:26+0000 [-] Timing out client: IPv4Address(type='TCP', host='172.27.0.1', port=56392)

2020-03-21 12:19:40+0000 [-] dropping connection to peer tcp4:172.27.0.1:56598 with abort=False: None

还有这个:

2020-03-21 12:10:49+0000 [-] Unhandled error in Deferred:
2020-03-21 12:10:49+0000 [-] Unhandled Error
    Traceback (most recent call last):
      File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
        self.run()
      File "/usr/lib/python3.8/threading.py", line 870, in run
        self._target(*self._args, **self._kwargs)
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/_threads/_threadworker.py", line 46, in work
        task()
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/_threads/_team.py", line 190, in doWork
        task()
    --- <exception caught here> ---
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/python/threadpool.py", line 250, in inContext
        result = inContext.theWork()
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/python/threadpool.py", line 266, in <lambda>
        inContext.theWork = lambda: context.call(ctx, func, *args, **kw)
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/python/context.py", line 122, in callWithContext
        return self.currentContext().callWithContext(ctx, func, *args, **kw)
      File "/bbot/sandbox/lib/python3.8/site-packages/twisted/python/context.py", line 85, in callWithContext
        return func(*args,**kw)
      File "/bbot/sandbox/lib/python3.8/site-packages/buildbot/buildbot_net_usage_data.py", line 204, in _sendBuildbotNetUsageData
        res = _sendWithRequests(PHONE_HOME_URL, data)
      File "/bbot/sandbox/lib/python3.8/site-packages/buildbot/buildbot_net_usage_data.py", line 197, in _sendWithRequests
        r = requests.post(url, json=data)
      File "/bbot/sandbox/lib/python3.8/site-packages/requests/api.py", line 119, in post
        return request('post', url, data=data, json=json, **kwargs)
      File "/bbot/sandbox/lib/python3.8/site-packages/requests/api.py", line 61, in request
        return session.request(method=method, url=url, **kwargs)
      File "/bbot/sandbox/lib/python3.8/site-packages/requests/sessions.py", line 530, in request
        resp = self.send(prep, **send_kwargs)
      File "/bbot/sandbox/lib/python3.8/site-packages/requests/sessions.py", line 643, in send
        r = adapter.send(request, **kwargs)
      File "/bbot/sandbox/lib/python3.8/site-packages/requests/adapters.py", line 516, in send
        raise ConnectionError(e, request=request)
    requests.exceptions.ConnectionError: HTTPSConnectionPool(host='events.buildbot.net', port=443): Max retries exceeded with url: /events/phone_home (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7ff7297704f0>: Failed to establish a new connection: [Errno 110] Operation timed out'))

这似乎只发生过一次(为什么 buildbot 仍然试图 phone 回家?在我的任何配置文件中都没有提到 events.buildbot.net

docker 容器具有完整的网络访问权限,ipv6、路由和 DNS 都很好(使用 buildbot-master 图像测试)。

这是我的 master.cfg:

import os

from twisted.application import service
from buildbot.master import BuildMaster

from buildbot.plugins import *
from buildbot_gitea.auth import GiteaAuth
from buildbot_gitea import *

basedir = '/bbot/bbot-master'
rotateLength = 10000000
maxRotatedFiles = 10
configfile = 'master.cfg'

umask = None

if basedir == '.':
    basedir = os.path.abspath(os.path.dirname(__file__))
application = service.Application('buildmaster')
from twisted.python.logfile import LogFile
from twisted.python.log import ILogObserver, FileLogObserver
logfile = LogFile.fromFullPath(os.path.join(basedir, "twistd.log"), rotateLength=rotateLength,
                                maxRotatedFiles=maxRotatedFiles)
application.setComponent(ILogObserver, FileLogObserver(logfile).emit)

m = BuildMaster(basedir, configfile, umask)
m.setServiceParent(application)
m.log_rotation.rotateLength = rotateLength
m.log_rotation.maxRotatedFiles = maxRotatedFiles# -*- python -*-                                                                                                                                                                                                                                                       
# ex: set filetype=python:                                                                                                                                                                                                                                                                                             

from buildbot.plugins import *


c = BuildmasterConfig = {}
####### WORKERS                                                                                                                                                                                                                                                                                                        

c['workers'] = [worker.Worker("bbot-worker", "BUILDBOT_PASSWORD")]

c['protocols'] = {'pb': {'port': 9989}}

####### CHANGESOURCES                                                                                                                                                                                                                                                                                                  

c['change_source'] = []
c['change_source'].append(changes.PBChangeSource())

####### SCHEDULERS                                                                                                                                                                                                                                                                                                     

c['schedulers'] = []


c['schedulers'].append(schedulers.SingleBranchScheduler(
                            name="all",
                            change_filter=util.ChangeFilter(branch='master'),
                            treeStableTimer=None,
                            builderNames=["runtests"]))
c['schedulers'].append(schedulers.ForceScheduler(
                            name="force",
                            builderNames=["runtests"]))

####### BUILDERS                                                                                                                                                                                                                                                                                                       

factory = util.BuildFactory()
factory.addStep(steps.Gitea(repourl='gitea@gitea.mydomain:myself/repo.git',
    mode='incremental',
        workdir="build",
        branch="master",
        progress=True,
        logEnviron=False,
))

factory.addStep(steps.ShellCommand(command=["make"]))

c['builders'] = []

c['builders'].append(
    util.BuilderConfig(name="runtests",
      workernames=["bbot-worker"],
      factory=factory))

####### BUILDBOT SERVICES                                                                                                                                                                                                                                                                                              

c['services'] = [
    reporters.GiteaStatusPush(
    baseURL="https://gitea.mydomain/",
        token="GITEA_API_ACCESS_TOKEN",
        verbose=True)
]


####### PROJECT IDENTITY                                                                                                                                                                                                                                                                                               

c['title'] = "My Domain!"
c['titleURL'] = "https://buildbot.mydomain"


c['buildbotURL'] = "https://buildbot.mydomain/"

c['www'] = dict(port=8010,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))

c['www']['authz'] = util.Authz(
        allowRules = [
            util.AnyEndpointMatcher(role="admins")
        ],
        roleMatchers = [
            util.RolesFromUsername(roles=['admins'], usernames=['myself'])
        ]
)

c['www']['auth'] = GiteaAuth(
    endpoint="https://gitea.mydomain/",
    client_id="MY_CLIENT_ID_FROM_GITEA",
    client_secret='MY_CLIENT_SECRET_FROM_GITEA')

c['www']['change_hook_dialects'] = {
                                  'gitea': {
                                  'secret': 'THE_GITEA_WEBHOOK_SECRET',
                                  'onlyIncludePushCommit': True
                                  }
}

####### DB URL                                                                                                                                                                                                                                                                                                         

c['db'] = {
    'db_url' : "postgresql://buildbot:MY_SECRET_DB_PASSWORD@172.25.0.2/buildbot",
}

master 的 Dockerfile 是

FROM alpine:3.11.3
EXPOSE 9989

RUN apk update
RUN apk add python3 bash    busybox-extras w3m gcc python3-dev libffi-dev openssl-dev musl-dev postgresql-dev
RUN mkdir /bbot
COPY entrypoint.sh /root/
RUN chmod a+x /root/entrypoint.sh
RUN mkdir /root/.ssh && chmod og-rwx /root/.ssh/
COPY bbot-gitea bbot-gitea.pub /root/.ssh/
RUN chmod og-w /root/.ssh/bbot-gitea*


RUN cd /bbot && \
    python3 -m venv sandbox && \
    source sandbox/bin/activate && \
    pip3 install 'buildbot[bundle]' && \
    pip3 install 'requests[security]' && \
    pip3 -v install buildbot_gitea && \
    pip3 install treq && \
    pip3 install psycopg2
RUN apk del gcc python3-dev libffi-dev openssl-dev musl-dev

RUN ls -la /root
RUN cat /root/entrypoint.sh

ENTRYPOINT [ "/root/entrypoint.sh" ]

入口点没有什么特别的——就是这样,

#!/bin/bash                                                                                                                                                                                                                                                                                                            

cd /bbot

echo " BBOT MASTER ENTRYPOINT"

source sandbox/bin/activate
buildbot upgrade-master bbot-master

# debug: check everything that was pip-installed:
echo "\n\n=====\n"
pip3 list
echo "=====\n\n"

if [ ! -f bbot-master/buildbot.tac ]; then
        buildbot create-master bbot-master
fi

buildbot start bbot-master
tail -f /bbot/bbot-master/twistd.log

pip3 list 行,运行 在启动时用于调试,显示我有

buildbot                2.7.0     
buildbot-console-view   2.7.0     
buildbot-gitea          1.2.0     
buildbot-grid-view      2.7.0     
buildbot-waterfall-view 2.7.0     
buildbot-worker         2.7.0     
buildbot-www            2.7.0     

edit: 检查了Firefox中的JS控制台,通过websockets连接到服务器似乎有问题:

Firefox can’t establish a connection to the server at wss://buildbot.mydomain/ws.

来自Chrome,这是我看到的:

WebSocket connection to 'wss://buildbot.aleph0.info/ws' failed: Error during WebSocket handshake: Unexpected response code: 200

(200?为什么是 200?)

我不明白为什么它不起作用。 Apache 配置为进行反向代理,如下所示:

RewriteEngine On
RewriteCond ${HTTP:Upgrade} websocket [NC]
RewriteCond ${HTTP:Connection} upgrade [NC]
RewriteRule .* "wss:/localhost:8010/" [P,L]
ProxyPass        / http://localhost:8010/
ProxyPassReverse / http://localhost:8010/

所以...我还能做些什么来继续调试它?

(顺便说一句,buildbot 邮件列表看起来确实不是很活跃——在发布这个问题后我查看了档案,发现非常低 activity。Buildbot 的用户在哪里这些天去是为了获得和分享建议?)

我找到问题了!

这是没有正确配置 websockets 的反向代理。

我在我的 apache 虚拟主机配置中使用了它,

    <Location /ws>
              ProxyPass ws://127.0.0.1:8010/ws
              ProxyPassReverse ws://127.0.0.1:8010/ws
    </Location>

    ProxyPass /ws !
    ProxyPass        / http://localhost:8010/
    ProxyPassReverse / http://localhost:8010/

现在可以使用了!

( 搜索了很多,在这里找到了解决方案: https://docs.buildbot.net/0.9.2/manual/cfg-www.html )

就在这里,以备不时之需。