1
2 from twisted.web import html
3 from twisted.web.util import Redirect
4
5 import re, urllib, time
6 from twisted.python import log
7 from buildbot import interfaces
8 from buildbot.status.web.base import HtmlResource, BuildLineMixin, \
9 path_to_build, path_to_slave, path_to_builder, path_to_change, \
10 path_to_root, getAndCheckProperties, ICurrentBox, build_get_class, \
11 map_branches, path_to_authfail
12 from buildbot.sourcestamp import SourceStamp
13
14 from buildbot.status.builder import BuildRequestStatus
15 from buildbot.status.web.build import BuildsResource, StatusResourceBuild
16 from buildbot import util
17
18
20 addSlash = True
21
25
27 return "Buildbot: %s" % self.builder_status.getName()
28
54
55 - def content(self, req, cxt):
56 b = self.builder_status
57
58 cxt['name'] = b.getName()
59 req.setHeader('Cache-Control', 'no-cache')
60 slaves = b.getSlaves()
61 connected_slaves = [s for s in slaves if s.isConnected()]
62
63 cxt['current'] = [self.builder(x, req) for x in b.getCurrentBuilds()]
64
65 cxt['pending'] = []
66 for pb in b.getPendingBuilds():
67 source = pb.getSourceStamp()
68 changes = []
69
70 if source.changes:
71 for c in source.changes:
72 changes.append({ 'url' : path_to_change(req, c),
73 'who' : c.who})
74 if source.revision:
75 reason = source.revision
76 else:
77 reason = "no changes specified"
78
79 cxt['pending'].append({
80 'when': time.strftime("%b %d %H:%M:%S", time.localtime(pb.getSubmitTime())),
81 'delay': util.formatInterval(util.now() - pb.getSubmitTime()),
82 'reason': reason,
83 'id': pb.brid,
84 'changes' : changes
85 })
86
87 numbuilds = int(req.args.get('numbuilds', ['5'])[0])
88 recent = cxt['recent'] = []
89 for build in b.generateFinishedBuilds(num_builds=int(numbuilds)):
90 recent.append(self.get_line_values(req, build, False))
91
92 sl = cxt['slaves'] = []
93 connected_slaves = 0
94 for slave in slaves:
95 s = {}
96 sl.append(s)
97 s['link'] = path_to_slave(req, slave)
98 s['name'] = slave.getName()
99 c = s['connected'] = slave.isConnected()
100 if c:
101 s['admin'] = unicode(slave.getAdmin() or '', 'utf-8')
102 connected_slaves += 1
103 cxt['connected_slaves'] = connected_slaves
104
105 cxt['authz'] = self.getAuthz(req)
106 cxt['builder_url'] = path_to_builder(req, b)
107
108 template = req.site.buildbot_service.templates.get_template("builder.html")
109 return template.render(**cxt)
110
111 - def force(self, req, auth_ok=False):
112 name = req.args.get("username", ["<unknown>"])[0]
113 reason = req.args.get("comments", ["<no reason specified>"])[0]
114 branch = req.args.get("branch", [""])[0]
115 revision = req.args.get("revision", [""])[0]
116 repository = req.args.get("repository", [""])[0]
117 project = req.args.get("project", [""])[0]
118
119 r = "The web-page 'force build' button was pressed by '%s': %s\n" \
120 % (html.escape(name), html.escape(reason))
121 log.msg("web forcebuild of builder '%s', branch='%s', revision='%s',"
122 " repository='%s', project='%s' by user '%s'" % (
123 self.builder_status.getName(), branch, revision, repository,
124 project, name))
125
126
127 if not auth_ok:
128 if not self.getAuthz(req).actionAllowed('forceBuild', req, self.builder_status):
129 log.msg("..but not authorized")
130 return Redirect(path_to_authfail(req))
131
132
133
134 if not re.match(r'^[\w.+/~-]*$', branch):
135 log.msg("bad branch '%s'" % branch)
136 return Redirect(path_to_builder(req, self.builder_status))
137 if not re.match(r'^[ \w\.\-\/]*$', revision):
138 log.msg("bad revision '%s'" % revision)
139 return Redirect(path_to_builder(req, self.builder_status))
140 properties = getAndCheckProperties(req)
141 if properties is None:
142 return Redirect(path_to_builder(req, self.builder_status))
143 if not branch:
144 branch = None
145 if not revision:
146 revision = None
147
148
149
150
151
152
153
154
155 s = SourceStamp(branch=branch, revision=revision, project=project, repository=repository)
156 try:
157 c = interfaces.IControl(self.getBuildmaster(req))
158 bc = c.getBuilder(self.builder_status.getName())
159 bc.submitBuildRequest(s, r, properties)
160 except interfaces.NoSlaveError:
161
162
163 pass
164
165 return Redirect(path_to_builder(req, self.builder_status))
166
167 - def ping(self, req):
177
179 try:
180 request_id = req.args.get("id", [None])[0]
181 if request_id == "all":
182 cancel_all = True
183 else:
184 cancel_all = False
185 request_id = int(request_id)
186 except:
187 request_id = None
188
189 authz = self.getAuthz(req)
190 if request_id:
191 c = interfaces.IControl(self.getBuildmaster(req))
192 bc = c.getBuilder(self.builder_status.getName())
193 for build_req in bc.getPendingBuilds():
194 if cancel_all or (build_req.brid == request_id):
195 log.msg("Cancelling %s" % build_req)
196 if authz.actionAllowed('cancelPendingBuild', req, build_req):
197 build_req.cancel()
198 else:
199 return Redirect(path_to_authfail(req))
200 if not cancel_all:
201 break
202 return Redirect(path_to_builder(req, self.builder_status))
203
232
246
247
248
307
308
309
311 title = "Builders"
312 addSlash = True
313
314 - def content(self, req, cxt):
315 status = self.getStatus(req)
316
317 builders = req.args.get("builder", status.getBuilderNames())
318 branches = [b for b in req.args.get("branch", []) if b]
319
320 cxt['branches'] = branches
321 bs = cxt['builders'] = []
322
323 building = 0
324 online = 0
325 base_builders_url = path_to_root(req) + "builders/"
326 for bn in builders:
327 bld = { 'link': base_builders_url + urllib.quote(bn, safe=''),
328 'name': bn }
329 bs.append(bld)
330
331 builder = status.getBuilder(bn)
332 builds = list(builder.generateFinishedBuilds(map_branches(branches),
333 num_builds=1))
334 if builds:
335 b = builds[0]
336 bld['build_url'] = (bld['link'] + "/builds/%d" % b.getNumber())
337 try:
338 label = b.getProperty("got_revision")
339 except KeyError:
340 label = None
341 if not label or len(str(label)) > 20:
342 label = "#%d" % b.getNumber()
343
344 bld['build_label'] = label
345 bld['build_text'] = " ".join(b.getText())
346 bld['build_css_class'] = build_get_class(b)
347
348 current_box = ICurrentBox(builder).getBox(status)
349 bld['current_box'] = current_box.td()
350
351 builder_status = builder.getState()[0]
352 if builder_status == "building":
353 building += 1
354 online += 1
355 elif builder_status != "offline":
356 online += 1
357
358 cxt['authz'] = self.getAuthz(req)
359 cxt['num_building'] = building
360 cxt['num_online'] = online
361
362 template = req.site.buildbot_service.templates.get_template("builders.html")
363 return template.render(**cxt)
364
374