Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Side by Side Diff: buildbot/status/web/build_orig.py

Issue 20095: Add the time it takes to run a step in the build (Closed) Base URL: svn://chrome-svn.corp.google.com/chrome/trunk/tools/buildbot/pylibs/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « buildbot/status/web/build.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1
2 from twisted.web import html
3 from twisted.web.util import Redirect, DeferredResource
4 from twisted.internet import defer, reactor
5
6 import urllib, time
7 from twisted.python import log
8 from buildbot.status.web.base import HtmlResource, make_row, make_stop_form, \
9 css_classes, path_to_builder
10
11 from buildbot.status.web.tests import TestsResource
12 from buildbot.status.web.step import StepsResource
13 from buildbot import version, util
14
15 # /builders/$builder/builds/$buildnum
16 class StatusResourceBuild(HtmlResource):
17 addSlash = True
18
19 def __init__(self, build_status, build_control, builder_control):
20 HtmlResource.__init__(self)
21 self.build_status = build_status
22 self.build_control = build_control
23 self.builder_control = builder_control
24
25 def getTitle(self, request):
26 return ("Buildbot: %s Build #%d" %
27 (html.escape(self.build_status.getBuilder().getName()),
28 self.build_status.getNumber()))
29
30 def body(self, req):
31 b = self.build_status
32 status = self.getStatus(req)
33 projectURL = status.getProjectURL()
34 projectName = status.getProjectName()
35 data = ('<div class="title"><a href="%s">%s</a></div>\n'
36 % (self.path_to_root(req), projectName))
37 # the color in the following line gives python-mode trouble
38 builder_name = b.getBuilder().getName()
39 data += ("<h1><a href=\"%s\">Builder %s</a>: Build #%d</h1>\n"
40 % (path_to_builder(req, b.getBuilder()),
41 builder_name, b.getNumber()))
42
43 if not b.isFinished():
44 data += "<h2>Build In Progress</h2>"
45 when = b.getETA()
46 if when is not None:
47 when_time = time.strftime("%H:%M:%S",
48 time.localtime(time.time() + when))
49 data += "<div>ETA %ds (%s)</div>\n" % (when, when_time)
50
51 if self.build_control is not None:
52 stopURL = urllib.quote(req.childLink("stop"))
53 data += make_stop_form(stopURL)
54
55 if b.isFinished():
56 results = b.getResults()
57 data += "<h2>Results:</h2>\n"
58 text = " ".join(b.getText())
59 data += '<span class="%s">%s</span>\n' % (css_classes[results],
60 text)
61 if b.getTestResults():
62 url = req.childLink("tests")
63 data += "<h3><a href=\"%s\">test results</a></h3>\n" % url
64
65 ss = b.getSourceStamp()
66 data += "<h2>SourceStamp:</h2>\n"
67 data += " <ul>\n"
68 if ss.branch:
69 data += " <li>Branch: %s</li>\n" % html.escape(ss.branch)
70 if ss.revision:
71 data += " <li>Revision: %s</li>\n" % html.escape(str(ss.revision))
72 if ss.patch:
73 data += " <li>Patch: YES</li>\n" # TODO: provide link to .diff
74 if ss.changes:
75 data += " <li>Changes: see below</li>\n"
76 if (ss.branch is None and ss.revision is None and ss.patch is None
77 and not ss.changes):
78 data += " <li>build of most recent revision</li>\n"
79 got_revision = None
80 try:
81 got_revision = b.getProperty("got_revision")
82 except KeyError:
83 pass
84 if got_revision:
85 got_revision = str(got_revision)
86 if len(got_revision) > 40:
87 got_revision = "[revision string too long]"
88 data += " <li>Got Revision: %s</li>\n" % got_revision
89 data += " </ul>\n"
90
91 # TODO: turn this into a table, or some other sort of definition-list
92 # that doesn't take up quite so much vertical space
93 data += "<h2>Buildslave:</h2>\n %s\n" % html.escape(b.getSlavename())
94 data += "<h2>Reason:</h2>\n%s\n" % html.escape(b.getReason())
95
96 data += "<h2>Steps and Logfiles:</h2>\n"
97 # TODO:
98 # urls = self.original.getURLs()
99 # ex_url_class = "BuildStep external"
100 # for name, target in urls.items():
101 # text.append('[<a href="%s" class="%s">%s</a>]' %
102 # (target, ex_url_class, html.escape(name)))
103 if b.getLogs():
104 data += "<ol>\n"
105 for s in b.getSteps():
106 name = s.getName()
107 data += (" <li><a href=\"%s\">%s</a> [%s]\n"
108 % (req.childLink("steps/%s" % urllib.quote(name)),
109 name,
110 " ".join(s.getText())))
111 if s.getLogs():
112 data += " <ol>\n"
113 for logfile in s.getLogs():
114 logname = logfile.getName()
115 logurl = req.childLink("steps/%s/logs/%s" %
116 (urllib.quote(name),
117 urllib.quote(logname)))
118 data += (" <li><a href=\"%s\">%s</a></li>\n" %
119 (logurl, logfile.getName()))
120 data += " </ol>\n"
121 data += " </li>\n"
122 data += "</ol>\n"
123
124 data += "<h2>Build Properties:</h2>\n"
125 data += "<table><tr><th valign=\"left\">Name</th><th valign=\"left\">Val ue</th><th valign=\"left\">Source</th></tr>\n"
126 for name, value, source in b.getProperties().asList():
127 value = str(value)
128 if len(value) > 500:
129 value = value[:500] + " .. [property value too long]"
130 data += "<tr>"
131 data += "<td>%s</td>" % html.escape(name)
132 data += "<td>%s</td>" % html.escape(value)
133 data += "<td>%s</td>" % html.escape(source)
134 data += "</tr>\n"
135 data += "</table>"
136
137 data += "<h2>Blamelist:</h2>\n"
138 if list(b.getResponsibleUsers()):
139 data += " <ol>\n"
140 for who in b.getResponsibleUsers():
141 data += " <li>%s</li>\n" % html.escape(who)
142 data += " </ol>\n"
143 else:
144 data += "<div>no responsible users</div>\n"
145
146 if ss.changes:
147 data += "<h2>All Changes</h2>\n"
148 data += "<ol>\n"
149 for c in ss.changes:
150 data += "<li>" + c.asHTML() + "</li>\n"
151 data += "</ol>\n"
152 #data += html.PRE(b.changesText()) # TODO
153
154 if b.isFinished() and self.builder_control is not None:
155 data += "<h3>Resubmit Build:</h3>\n"
156 # can we rebuild it exactly?
157 exactly = (ss.revision is not None) or b.getChanges()
158 if exactly:
159 data += ("<p>This tree was built from a specific set of \n"
160 "source files, and can be rebuilt exactly</p>\n")
161 else:
162 data += ("<p>This tree was built from the most recent "
163 "revision")
164 if ss.branch:
165 data += " (along some branch)"
166 data += (" and thus it might not be possible to rebuild it \n"
167 "exactly. Any changes that have been committed \n"
168 "after this build was started <b>will</b> be \n"
169 "included in a rebuild.</p>\n")
170 rebuildURL = urllib.quote(req.childLink("rebuild"))
171 data += ('<form action="%s" class="command rebuild">\n'
172 % rebuildURL)
173 data += make_row("Your name:",
174 "<input type='text' name='username' />")
175 data += make_row("Reason for re-running build:",
176 "<input type='text' name='comments' />")
177 data += '<input type="submit" value="Rebuild" />\n'
178 data += '</form>\n'
179
180 # TODO: this stuff should be generated by a template of some sort
181 data += '<hr /><div class="footer">\n'
182
183 welcomeurl = self.path_to_root(req) + "index.html"
184 data += '[<a href="%s">welcome</a>]\n' % welcomeurl
185 data += "<br />\n"
186
187 data += '<a href="http://buildbot.sourceforge.net/">Buildbot</a>'
188 data += "-%s " % version
189 if projectName:
190 data += "working for the "
191 if projectURL:
192 data += "<a href=\"%s\">%s</a> project." % (projectURL,
193 projectName)
194 else:
195 data += "%s project." % projectName
196 data += "<br />\n"
197 data += ("Page built: " +
198 time.strftime("%a %d %b %Y %H:%M:%S",
199 time.localtime(util.now()))
200 + "\n")
201 data += '</div>\n'
202
203 return data
204
205 def stop(self, req):
206 b = self.build_status
207 c = self.build_control
208 log.msg("web stopBuild of build %s:%s" % \
209 (b.getBuilder().getName(), b.getNumber()))
210 name = req.args.get("username", ["<unknown>"])[0]
211 comments = req.args.get("comments", ["<no reason specified>"])[0]
212 reason = ("The web-page 'stop build' button was pressed by "
213 "'%s': %s\n" % (name, comments))
214 c.stopBuild(reason)
215 # we're at http://localhost:8080/svn-hello/builds/5/stop?[args] and
216 # we want to go to: http://localhost:8080/svn-hello
217 r = Redirect("../..")
218 d = defer.Deferred()
219 reactor.callLater(1, d.callback, r)
220 return DeferredResource(d)
221
222 def rebuild(self, req):
223 b = self.build_status
224 bc = self.builder_control
225 builder_name = b.getBuilder().getName()
226 log.msg("web rebuild of build %s:%s" % (builder_name, b.getNumber()))
227 name = req.args.get("username", ["<unknown>"])[0]
228 comments = req.args.get("comments", ["<no reason specified>"])[0]
229 reason = ("The web-page 'rebuild' button was pressed by "
230 "'%s': %s\n" % (name, comments))
231 if not bc or not b.isFinished():
232 log.msg("could not rebuild: bc=%s, isFinished=%s"
233 % (bc, b.isFinished()))
234 # TODO: indicate an error
235 else:
236 bc.resubmitBuild(b, reason)
237 # we're at
238 # http://localhost:8080/builders/NAME/builds/5/rebuild?[args]
239 # Where should we send them?
240 #
241 # Ideally it would be to the per-build page that they just started,
242 # but we don't know the build number for it yet (besides, it might
243 # have to wait for a current build to finish). The next-most
244 # preferred place is somewhere that the user can see tangible
245 # evidence of their build starting (or to see the reason that it
246 # didn't start). This should be the Builder page.
247 r = Redirect("../..") # the Builder's page
248 d = defer.Deferred()
249 reactor.callLater(1, d.callback, r)
250 return DeferredResource(d)
251
252 def getChild(self, path, req):
253 if path == "stop":
254 return self.stop(req)
255 if path == "rebuild":
256 return self.rebuild(req)
257 if path == "steps":
258 return StepsResource(self.build_status)
259 if path == "tests":
260 return TestsResource(self.build_status)
261
262 return HtmlResource.getChild(self, path, req)
263
264 # /builders/$builder/builds
265 class BuildsResource(HtmlResource):
266 addSlash = True
267
268 def __init__(self, builder_status, builder_control):
269 HtmlResource.__init__(self)
270 self.builder_status = builder_status
271 self.builder_control = builder_control
272
273 def getChild(self, path, req):
274 try:
275 num = int(path)
276 except ValueError:
277 num = None
278 if num is not None:
279 build_status = self.builder_status.getBuild(num)
280 if build_status:
281 if self.builder_control:
282 build_control = self.builder_control.getBuild(num)
283 else:
284 build_control = None
285 return StatusResourceBuild(build_status, build_control,
286 self.builder_control)
287
288 return HtmlResource.getChild(self, path, req)
289
OLDNEW
« no previous file with comments | « buildbot/status/web/build.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698