/[soft]/build_system/web/index.php
ViewVC logotype

Contents of /build_system/web/index.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 950 - (show annotations) (download)
Tue Apr 19 12:09:23 2011 UTC (13 years ago) by rda
File size: 12695 byte(s)
count only once time for a given package
1 <?php
2 /**
3 * Mageia build-system quick status report script.
4 *
5 * @copyright Copyright (C) 2011 Mageia.Org
6 *
7 * @author Olivier Blin
8 * @author Pascal Terjan
9 * @author Romain d'Alverny
10 *
11 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU GPL v2
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License aspublished by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 *
18 *
19 * Shows submitted packages in the past $max_modified 24 hours and their
20 * status (built & uploaded, failed build, rejected, etc.).
21 *
22 * This was written anew in Jan. 2011 because existing Mandriva build-system
23 * web report code was not clearly licensed at this very time.
24 */
25
26 error_reporting(E_ALL);
27
28 /**
29 * @param array $pkg
30 *
31 * @return string
32 */
33 function pkg_gettype($pkg) {
34 if (array_key_exists("rejected", $pkg["status"]))
35 return "rejected";
36 if (array_key_exists("youri", $pkg["status"])) {
37 if (array_key_exists("src", $pkg["status"]))
38 return "youri";
39 else
40 return "uploaded";
41 }
42 if (array_key_exists("failure", $pkg["status"]))
43 return "failure";
44 if (array_key_exists("done", $pkg["status"]))
45 return "partial";
46 if (array_key_exists("build", $pkg["status"]))
47 return "building";
48 if (array_key_exists("todo", $pkg["status"]))
49 return "todo";
50 return "unknown";
51 }
52
53 /**
54 * @param integer $num
55 *
56 * @return string
57 */
58 function plural($num) {
59 if ($num > 1)
60 return "s";
61 }
62
63 /**
64 * Return timestamp from package key
65 * @param string $key package submission key
66 *
67 * @return integer
68 */
69
70 function key2timestamp($key) {
71 global $tz;
72
73 $date = DateTime::createFromFormat("YmdHis", $key+0, $tz);
74 if ($date <= 0)
75 return null;
76
77 return $date->getTimestamp();
78 }
79
80 function timediff($start, $end) {
81 /**
82 * Return human-readable time difference
83 *
84 * @param integer $start timestamp
85 * @param integer $end timestamp, defaults to now
86 *
87 * @return string
88 */
89 if (is_null($end)) {
90 $end = time();
91 }
92 $diff = $end - $start;
93 if ($diff<60)
94 return $diff . " second" . plural($diff);
95 $diff = round($diff/60);
96 if ($diff<60)
97 return $diff . " minute" . plural($diff);
98 $diff = round($diff/60);
99 if ($diff<24)
100 return $diff . " hour" . plural($diff);
101 $diff = round($diff/24);
102
103 return $diff . " day" . plural($diff);
104 }
105
106 $g_user = isset($_GET['user']) ? htmlentities(strip_tags($_GET['user'])) : null;
107
108 $upload_dir = '/home/schedbot/uploads';
109 $max_modified = 2;
110 $title = '<a href="http://mageia.org/">Mageia</a> build system status';
111 $robots = 'index,nofollow,nosnippet,noarchive';
112 if ($g_user) {
113 $title .= ' for ' . $g_user . "'s packages";
114 $robots = 'no' . $robots;
115 }
116 $tz = new DateTimeZone('UTC');
117 $date_gen = date('c');
118
119 # Temporary until initial mirror is ready
120 chdir("data");
121 $missing_deps = file("missing-deps.i586.txt");
122 #########################################
123
124 chdir($upload_dir);
125
126 $all_files = shell_exec("find \( -name '*.rpm' -o -name '*.src.rpm.info' -o -name '*.youri' -o -name '*.lock' -o -name '*.done' \) -ctime -$max_modified -printf \"%p\t%T@\\n\"");
127 $re = "!^\./(\w+)/((\w+)/(\w+)/(\w+)/(\d+)\.(\w+)\.(\w+)\.(\d+))_?(.*)(\.src\.rpm(?:\.info)?|\.youri|\.lock|\.done)\s+(\d+\.\d+)$!m";
128 $r = preg_match_all($re,
129 $all_files,
130 $matches,
131 PREG_SET_ORDER);
132
133 $pkgs = array();
134
135 $buildtime_total = array();
136
137 foreach ($matches as $val) {
138
139 if ($_GET['user'] && ($_GET['user'] != $val[7])) {
140 continue;
141 }
142 $key = $val[6] . $val[7];
143 if (!is_array($pkgs[$key])) {
144
145 $pkgs[$key] = array(
146 'status' => array(),
147 'path' => $val[2],
148 'version' => $val[3],
149 'media' => $val[4],
150 'section' => $val[5],
151 'user' => $val[7],
152 'host' => $val[8],
153 'job' => $val[9]
154 );
155 }
156 $status = $val[1];
157 $data = $val[10];
158 if (preg_match("/@(\d+):/", $data, $revision)) {
159 $pkgs[$key]['revision'] = $revision[1];
160 }
161 $pkgs[$key]['status'][$status] = 1;
162 $ext = $val[11];
163 if ($ext == '.src.rpm.info') {
164 preg_match("!^(?:@\d+:)?(.*)!", $data, $name);
165 $pkgs[$key]['package'] = $name[1];
166 } else if ($ext == '.src') {
167 $pkgs[$key]['status']['src'] = 1;
168 } else if ($ext == '.youri') {
169 $pkgs[$key]['status']['youri'] = 1;
170 } else if ($ext == '.lock') {
171 // parse build bot from $data
172 $pkgs[$key]['status']['build'] = 1;
173 } else if ($ext == '.done') {
174 $pkgs[$key]['buildtime']['start'] = key2timestamp($val[6]);
175 $pkgs[$key]['buildtime']['end'] = round($val[12]);
176 $pkgs[$key]['buildtime']['diff'] = $pkgs[$key]['buildtime']['end'] - $pkgs[$key]['buildtime']['start'];
177
178 // keep obviously dubious values out of there
179 // 12 hours is be an acceptable threshold given current BS global perfs
180 // as of April 2011
181 if ($pkgs[$key]['buildtime']['diff'] < 43200) {
182 $buildtime_total[$key] = $pkgs[$key]['buildtime']['diff'];
183 }
184 }
185 }
186 // sort by key in reverse order to have more recent pkgs first
187 krsort($pkgs);
188
189 $build_count = count($buildtime_total);
190 $buildtime_total = array_sum($buildtime_total);
191
192 // count all packages statuses
193 $stats = array(
194 'uploaded' => 0,
195 'failure' => 0,
196 'todo' => 0,
197 'building' => 0,
198 'partial' => 0,
199 'built' => 0,
200 );
201 $total = count($pkgs);
202
203 // count users' packages
204 $users = array();
205
206 if ($total > 0) {
207 foreach ($pkgs as $key => $p) {
208 $pkgs[$key]['type'] = pkg_gettype($p);
209
210 $stats[$pkgs[$key]['type']] += 1;
211
212 if (!array_key_exists($p['user'], $users))
213 $users[$p['user']] = 1;
214 else
215 $users[$p['user']] += 1;
216 }
217 }
218
219 foreach ($stats as $k => $v) {
220 Header("X-BS-Queue-$k: $v");
221 }
222
223 $w = $stats['todo'] - 10;
224 if($w < 0)
225 $w = 0;
226 $w = $w * 60;
227 Header("X-BS-Throttle: $w");
228
229 $buildtime_total = $buildtime_total / 60;
230 header(sprintf('X-BS-Buildtime: %d', round($buildtime_total)));
231 $buildtime_avg = round($buildtime_total / $build_count, 2);
232 header(sprintf('X-BS-Buildtime-Average: %5.2f', $buildtime_avg));
233 ?>
234 <!DOCTYPE html>
235 <html lang="en">
236 <head>
237 <meta charset="utf-8">
238 <title><?php echo strip_tags($title); ?></title>
239 <meta name="robots" content="<?php echo $robots; ?>">
240 <link rel="icon" type="image/png" href="favicon.png" />
241 <style type="text/css">
242 .clear { clear: both; }
243 table {
244 border-spacing: 0;
245 font-family: Helvetica, Verdana, Arial, sans-serif; font-size: 80%;
246 border: 1px solid #ccc;
247 float: left;
248 }
249 table tr { padding: 0; margin: 0; }
250 table th { padding: 0.2em 0.5em; margin: 0; border-bottom: 2px solid #ccc; border-right: 1px solid #ccc; }
251 table td { padding: 0; margin: 0; padding: 0.2em 0.5em; border-bottom: 1px solid #ccc; }
252
253 tr { background: transparent; }
254 tr.uploaded { background: #bbffbb; }
255 tr.failure, tr.rejected { background: #ffbbbb; }
256 tr.todo { background: white; }
257 tr.building { background: #ffff99; }
258 tr.partial { background: #bbbbff; }
259 tr.built { background: #cceeff; }
260 tr.youri { background: #aacc66; }
261
262 td.status-box { width: 1em; height: 1em; }
263 tr.uploaded td.status-box { background: green; }
264 tr.failure td.status-box, tr.rejected td.status-box { background: red; }
265 tr.todo td.status-box { background: white; }
266 tr.building td.status-box { background: yellow; }
267 tr.partial td.status-box { background: blue; }
268 tr.built td.status-box { background: #00ccff; }
269 tr.youri td.status-box { background: olive; }
270
271 #stats { float: right; }
272 #score { margin-bottom: 2em; font-family: Helvetica, Verdana, Arial, sans-serif; }
273 #score-box { width: 100px; height: 100px; background: #faa; }
274 #score-meter { width: 100px; background: #afa; }
275 </style>
276 </head>
277 <body>
278 <h1><?php echo $title ?></h1>
279
280 <?php
281 if (!is_null($g_user))
282 echo '<a href="/">&laquo;&nbsp;Back to full list</a>';
283
284 # Temporary until initial mirror is ready
285 echo sprintf(
286 '<p><a href="%s">%d broken dependencies</a>. <strong><a href="%s">You can help!</a></strong></p>',
287 'data/missing-deps.i586.txt', count($missing_deps),
288 'http://www.mageia.org/wiki/doku.php?id=packaging#starting_package_import'
289 );
290
291 #########################################
292
293 $buildtime_stats = array();
294
295 $s = '';
296 $tmpl = <<<T
297 <tr class="%s">
298 <td>%s</td>
299 <td><a href="?user=%s">%s</a></td>
300 <td><a href="http://svnweb.mageia.org/packages?view=revision&revision=%d" title="%s">%s</a></td>
301 <td>%s</td>
302 <td>%s/%s</td>
303 <td class="status-box"></td>
304 T;
305
306 if ($total > 0) {
307 foreach ($pkgs as $key => $p) {
308 $s .= sprintf($tmpl,
309 $p['type'],
310 timediff(key2timestamp($key)) . ' ago',
311 $p['user'], $p['user'],
312 $p['revision'],
313 addslashes($p['summary']),
314 $p['package'],
315 $p['version'],
316 $p['media'], $p['section']
317 );
318
319 $typelink = '';
320 if ($p['type'] == 'failure') {
321 $typelink = '/uploads/' . $p['type'] . '/' . $p['path'];
322 } elseif ($p['type'] == 'rejected') {
323 $typelink = '/uploads/' . $p['type'] . '/' . $p['path'] . '.youri';
324 }
325
326 $s .= '<td>';
327 $s .= ($typelink != '') ?
328 sprintf('<a href="%s">%s</a>', $typelink, $p['type']) :
329 $p['type'];
330
331 $s .= '</td><td>';
332 if ($p['type'] == 'uploaded') {
333 $tdiff = timediff($p['buildtime']['start'], $p['buildtime']['end']); // use $p['buildtime']['diff']; instead?
334 $s .= $tdiff;
335 @$buildtime_stats[$tdiff] += 1;
336 }
337 $s .= '</td>';
338 $s .= '</tr>';
339 }
340 // Table
341 echo '<table>',
342 '<caption>', $total, ' packages submitted in the past ', $max_modified * 24, '&nbsp;hours.</caption>',
343 '<tr><th>Submitted</th><th>User</th>
344 <th>Package</th><th>Target</th><th>Media</th>
345 <th colspan="2">Status</th><th>Build time</th></tr>',
346 $s,
347 '</table>';
348
349 // Stats
350 $s = '<div id="stats">';
351 $score = round($stats['uploaded']/$total * 100);
352 $s .= sprintf('<div id="score"><h3>Score: %d/100</h3>
353 <div id="score-box"><div id="score-meter" style="height: %dpx;"></div></div></div>',
354 $score, $score);
355
356 $s .= '<table style="width: 100%"><caption>Stats.</caption><tr><th colspan="2">Status</th><th>Count</th><th>%</th></tr>';
357 foreach ($stats as $k => $v) {
358 $s .= sprintf('<tr class="%s"><td class="status-box"></td><td>%s</td><td>%d</td><td>%d%%</td></tr>',
359 $k, $k, $v, round($v/$total*100));
360 }
361
362 $s .= '</table><br /><br />';
363
364 $s .= '<table style="width: 100%"><caption>Packagers</caption><tr><th>User</th><th>Packages</th></tr>';
365 arsort($users);
366 foreach ($users as $k => $v)
367 $s .= sprintf('<tr><td><a href="/?user=%s">%s</a></td><td>%d</td></tr>',
368 $k, $k, $v);
369
370 $s .= '</table><br /><br />';
371
372 /**
373 */
374 function timesort($a, $b)
375 {
376 $a = explode(' ', trim($a));
377 $b = explode(' ', trim($b));
378
379 if ($a[1] == 'hour' || $a[1] == 'hours')
380 $a[0] *= 3600;
381
382 if ($b[1] == 'hour' || $a[1] == 'hours')
383 $b[0] *= 3600;
384
385 if ($a[0] > $b[0])
386 return 1;
387 elseif ($a[0] < $b[0])
388 return -1;
389
390 return 0;
391 }
392 uksort($buildtime_stats, "timesort");
393
394 $bts = '';
395 foreach ($buildtime_stats as $time => $count) {
396 $bts .= sprintf('<tr><td>%s</td><td>%d</td></tr>',
397 $time, $count);
398
399 $tmp = explode(' ', $time);
400 }
401
402 $s .= '<table style="width: 100%;"><caption>Build time</caption>';
403
404 $s .= sprintf('<tr><td>Total time</td><td>%s hours</td></tr>
405 <tr><td>Average</td><td>%s minutes</td></tr>
406 <tr><td>Builds count</td><td>%s</td></tr>',
407 round($buildtime_total / 60, 2),
408 $buildtime_avg,
409 $buildtime_cnt);
410
411 $s .= '<tr><th title="Build time">Duration</th><th title="Packages number">Pack. nb.</th></tr>';
412 $s .= $bts;
413 $s .= '</table><span style="font-size: 85%;">Does not take<br />build failures<br />into account.</span>';
414
415 $s .= '</div>';
416
417 echo $s;
418 }
419 else
420 {
421 echo sprintf('<p>No package has been submitted in the past %d&nbsp;hours.</p>',
422 $max_modified * 24);
423 }
424
425 ?>
426 <div class="clear"></div>
427 <hr />
428 <p>Generated at <?php echo $date_gen; ?>.</p>
429 </body>
430 </html>

  ViewVC Help
Powered by ViewVC 1.1.30