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