This repository has been archived by the owner on Jun 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
web.py
173 lines (141 loc) · 6.43 KB
/
web.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import time
from buildbot.status.web.base import HtmlResource, map_branches, build_get_class, path_to_builder, path_to_build
from buildbot.status.web.hooks.github import GitHubEventHandler
from buildbot.status.builder import SUCCESS, WARNINGS, FAILURE, SKIPPED, EXCEPTION, RETRY
from buildbot.status import html
from buildbot.util import formatInterval
from twisted.web.util import Redirect
from twisted.internet import defer
from twisted.web.template import tags, flattenString
_backgroundColors = {
SUCCESS: "green",
WARNINGS: "orange",
FAILURE: "red",
SKIPPED: "blue",
EXCEPTION: "purple",
RETRY: "purple",
# This is a buildbot bug or something.
None: "yellow",
}
# /boxes[-things]
# accepts builder=, branch=, num_builds=
class TenBoxesPerBuilder(HtmlResource):
"""This shows a narrow table with one row per build. The leftmost column
contains the builder name. The next column contains the results of the
most recent build. The right-hand column shows the builder's current
activity.
builder=: show only builds for this builder. Multiple builder= arguments
can be used to see builds from any builder in the set.
"""
title = "Latest Build"
def __init__(self, categories=None):
HtmlResource.__init__(self)
self.categories = categories
@defer.inlineCallbacks
def content(self, req, context):
body = yield self.body(req)
context['content'] = body
template = req.site.buildbot_service.templates.get_template("empty.html")
defer.returnValue(template.render(**context))
@defer.inlineCallbacks
def body(self, req):
status = self.getStatus(req)
authz = self.getAuthz(req)
builders = req.args.get("builder", status.getBuilderNames(categories=self.categories))
branches = [b for b in req.args.get("branch", []) if b]
if not branches:
branches = ["trunk"]
if branches and "trunk" not in branches:
defaultCount = "1"
else:
defaultCount = "10"
num_builds = int(req.args.get("num_builds", [defaultCount])[0])
tag = tags.div()
tag(tags.script(src="txbuildbot.js"))
tag(tags.h2(style="float:left; margin-top:0")("Latest builds: ", ", ".join(branches)))
form = tags.form(method="get", action="", style="float:right",
onsubmit="return checkBranch(branch.value)")
form(tags.input(type="test", name="branch", placeholder=branches[0], size="40"))
form(tags.input(type="submit", value="View"))
if (yield authz.actionAllowed('forceAllBuilds', req)):
# XXX: Unsafe interpolation
form(tags.button(type="button",
onclick="forceBranch(branch.value || %r, %r)"
% (branches[0], self.categories,)
)("Force"))
tag(form)
table = tags.table(style="clear:both")
tag(table)
for bn in builders:
builder = status.getBuilder(bn)
state = builder.getState()[0]
if state == 'building':
state = 'idle'
row = tags.tr()
table(row)
builderLink = path_to_builder(req, builder)
row(tags.td(class_="box %s" % (state,))(tags.a(href=builderLink)(bn)))
builds = sorted([
build for build in builder.getCurrentBuilds()
if build.getSourceStamps()[0].branch in map_branches(branches)
], key=lambda build: build.getNumber(), reverse=True)
builds.extend(builder.generateFinishedBuilds(map_branches(branches),
num_builds=num_builds))
if builds:
for b in builds:
url = path_to_build(req, b)
try:
label = b.getProperty("got_revision")
except KeyError:
label = None
# Label should never be "None", but sometimes
# buildbot has disgusting bugs.
if not label or label == "None" or len(str(label)) > 20:
label = "#%d" % b.getNumber()
if b.isFinished():
text = b.getText()
else:
when = b.getETA()
if when:
text = [
"%s" % (formatInterval(when),),
"%s" % (time.strftime("%H:%M:%S", time.localtime(time.time() + when)),)
]
else:
text = []
row(tags.td(
align="center",
bgcolor=_backgroundColors[b.getResults()],
class_=("LastBuild box ", build_get_class(b)))([
(element, tags.br)
for element
in [tags.a(href=url)(label)] + text]) )
else:
row(tags.td(class_="LastBuild box")("no build"))
defer.returnValue((yield flattenString(req, tag)))
class TwistedWebStatus(html.WebStatus):
"""
Customization of the resources available via the webstatus.
"""
def __init__(self, **kwargs):
html.WebStatus.__init__(self, **kwargs)
self.putChild("boxes-supported", TenBoxesPerBuilder(categories=['supported']))
self.putChild("boxes-unsupported", TenBoxesPerBuilder(categories=['unsupported']))
self.putChild("boxes-all", TenBoxesPerBuilder(categories=['supported', 'unsupported']))
self.putChild("boxes-benchmark", TenBoxesPerBuilder(categories=['benchmark']))
# These are are expensive, so disable them
# http://trac.buildbot.net/ticket/2268
self.putChild("grid", Redirect("boxes-supported"))
self.putChild("tgrid", Redirect("boxes-supported"))
class TwistedGitHubEventHandler(GitHubEventHandler):
"""
Custom handling of GitHub hooks.
"""
def handle_pull_request(self, payload):
"""
For now triggering builds on PR is disabled.
The hook should not be called for non-push events, but this is here
as a fallback and to document that for now we don't want to execute
build on PRs as we don't trust the external contributors.
"""
return [], 'git'