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

Contents of /build_system/web/index.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2756 - (show annotations) (download)
Sun Jan 22 17:11:47 2012 UTC (12 years, 5 months ago) by pterjan
File size: 15260 byte(s)
Oops remove garbage <
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 * @author Michael Scherer
11 *
12 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU GPL v2
13 *
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License aspublished by the
16 * Free Software Foundation; either version 2 of the License, or (at your
17 * option) any later version.
18 *
19 *
20 * Shows submitted packages in the past $max_modified 24 hours and their
21 * status (built & uploaded, failed build, rejected, etc.).
22 *
23 * This was written anew in Jan. 2011 because existing Mandriva build-system
24 * web report code was not clearly licensed at this very time.
25 */
26
27 error_reporting(E_ALL);
28
29 /**
30 * @param array $pkg
31 *
32 * @return string
33 */
34 function pkg_gettype($pkg) {
35 if (array_key_exists("rejected", $pkg["status"]))
36 return "rejected";
37 if (array_key_exists("upload", $pkg["status"]))
38 return "uploaded";
39 if (array_key_exists("failure", $pkg["status"]))
40 return "failure";
41 if (array_key_exists("done", $pkg["status"]))
42 return "partial";
43 if (array_key_exists("build", $pkg["status"]))
44 return "building";
45 if (array_key_exists("todo", $pkg["status"]))
46 return "todo";
47 return "unknown";
48 }
49
50 /**
51 * @param integer $num
52 *
53 * @return string
54 */
55 function plural($num) {
56 if ($num > 1)
57 return "s";
58 }
59
60 /**
61 * Return timestamp from package key
62 * @param string $key package submission key
63 *
64 * @return integer
65 */
66
67 function key2timestamp($key) {
68 global $tz;
69
70 $date = DateTime::createFromFormat("YmdHis", $key+0, $tz);
71 if ($date <= 0)
72 return null;
73
74 return $date->getTimestamp();
75 }
76
77 function timediff($start, $end) {
78 /**
79 * Return human-readable time difference
80 *
81 * @param integer $start timestamp
82 * @param integer $end timestamp, defaults to now
83 *
84 * @return string
85 */
86 if (is_null($end)) {
87 $end = time();
88 }
89 $diff = $end - $start;
90 if ($diff<60)
91 return $diff . " second" . plural($diff);
92 $diff = round($diff/60);
93 if ($diff<60)
94 return $diff . " minute" . plural($diff);
95 $diff = round($diff/60);
96 if ($diff<24)
97 return $diff . " hour" . plural($diff);
98 $diff = round($diff/24);
99
100 return $diff . " day" . plural($diff);
101 }
102
103 $g_user = isset($_GET['user']) ? htmlentities(strip_tags($_GET['user'])) : null;
104
105 $upload_dir = '/home/schedbot/uploads';
106 $max_modified = 2;
107 $title = '<a href="http://mageia.org/">Mageia</a> build system status';
108 $robots = 'index,nofollow,nosnippet,noarchive';
109 if ($g_user) {
110 $title .= ' for ' . $g_user . "'s packages";
111 $robots = 'no' . $robots;
112 }
113 $tz = new DateTimeZone('UTC');
114 $date_gen = date('c');
115
116 # Temporary until initial mirror is ready
117 chdir("data");
118 $missing_deps = file("missing-deps.i586.txt");
119 #########################################
120 $unmaintained = file('unmaintained.txt');
121
122 chdir($upload_dir);
123
124 $all_files = shell_exec("find \( -name '*.rpm' -o -name '*.src.rpm.info' -o -name '*.lock' -o -name '*.done' -o -name '*.upload' \) -ctime -$max_modified -printf \"%p\t%T@\\n\"");
125 $re = "!^\./(\w+)/((\w+)/(\w+)/(\w+)/(\d+)\.(\w+)\.(\w+)\.(\d+))_?(.*)(\.src\.rpm(?:\.info)?|\.lock|\.done|\.upload)\s+(\d+\.\d+)$!m";
126 $r = preg_match_all($re,
127 $all_files,
128 $matches,
129 PREG_SET_ORDER);
130
131 $pkgs = array();
132 $hosts = array();
133
134 $buildtime_total = array();
135 $buid_dates = 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.rpm') {
167 $pkgs[$key]['status']['src'] = 1;
168 } else if ($ext == '.upload') {
169 $pkgs[$key]['status']['upload'] = 1;
170 } else if ($ext == '.lock') {
171 preg_match("!(.*)\.iurt\.(.*)\.\d+\.\d+!", $data, $buildhost);
172 if (!$hosts[$buildhost[2]]) {
173 $hosts[$buildhost[2]]= array();
174 }
175 $hosts[$buildhost[2]][$buildhost[1]] = $key;
176 if ($pkgs[$key]['status']['build'])
177 array_push($pkgs[$key]['status']['build'], $buildhost[2]);
178 else
179 $pkgs[$key]['status']['build'] = array($buildhost[2]);
180 } else if ($ext == '.done') {
181 // beware! this block is called twice for a given $key
182
183 $pkgs[$key]['buildtime']['start'] = key2timestamp($val[6]);
184 $pkgs[$key]['buildtime']['end'] = round($val[12]);
185 $pkgs[$key]['buildtime']['diff'] = $pkgs[$key]['buildtime']['end'] - $pkgs[$key]['buildtime']['start'];
186
187 @$build_dates[date('H', $pkgs[$key]['buildtime']['start'])] += 1;
188
189 // keep obviously dubious values out of there
190 // 12 hours is be an acceptable threshold given current BS global perfs
191 // as of April 2011
192 if ($pkgs[$key]['buildtime']['diff'] < 43200) {
193 $buildtime_total[$key] = $pkgs[$key]['buildtime']['diff'];
194 }
195 }
196 }
197 // sort by key in reverse order to have more recent pkgs first
198 krsort($pkgs);
199 ksort($build_dates);
200
201 $build_count = count($buildtime_total);
202 $buildtime_total = array_sum($buildtime_total);
203
204 // count all packages statuses
205 $stats = array(
206 'uploaded' => 0,
207 'failure' => 0,
208 'todo' => 0,
209 'building' => 0,
210 'partial' => 0,
211 'built' => 0,
212 );
213 $total = count($pkgs);
214
215 // count users' packages
216 $users = array();
217
218 if ($total > 0) {
219 foreach ($pkgs as $key => $p) {
220 $pkgs[$key]['type'] = pkg_gettype($p);
221
222 $stats[$pkgs[$key]['type']] += 1;
223
224 if (!array_key_exists($p['user'], $users))
225 $users[$p['user']] = 1;
226 else
227 $users[$p['user']] += 1;
228 }
229 }
230
231 // check if emi is running
232 $stat = stat("/var/lib/schedbot/tmp/upload");
233 if ($stat) {
234 $upload_time = $stat['mtime'];
235 }
236
237 // publish stats as headers
238 foreach ($stats as $k => $v) {
239 Header("X-BS-Queue-$k: $v");
240 }
241
242 $w = $stats['todo'] - 10;
243 if($w < 0)
244 $w = 0;
245 $w = $w * 60;
246 Header("X-BS-Throttle: $w");
247
248 $buildtime_total = $buildtime_total / 60;
249 header(sprintf('X-BS-Buildtime: %d', round($buildtime_total)));
250 $buildtime_avg = round($buildtime_total / $build_count, 2);
251 header(sprintf('X-BS-Buildtime-Average: %5.2f', $buildtime_avg));
252 ?>
253 <!DOCTYPE html>
254 <html lang="en">
255 <head>
256 <meta charset="utf-8">
257 <title><?php echo strip_tags($title); ?></title>
258 <meta name="robots" content="<?php echo $robots; ?>">
259 <link rel="icon" type="image/png" href="favicon.png" />
260 <style type="text/css">
261 body, table {
262 font-family: Verdana, "Trebuchet MS", "Lucida Grande", "Lucida Sans", Verdana, Tahoma, Arial, sans-serif;
263 }
264 body { font-size: 80%; }
265 .clear { clear: both; }
266 table {
267 border-spacing: 0;
268 border: 1px solid #ccc;
269 float: left;
270 }
271 table tr { padding: 0; margin: 0; }
272 table th { padding: 0.2em 0.5em; margin: 0; border-bottom: 2px solid #ccc; border-right: 1px solid #ccc; }
273 table td { padding: 0; margin: 0; padding: 0.2em 0.5em; border-bottom: 1px solid #ccc; }
274
275 tr { background: transparent; }
276 tr.uploaded { background: #bbffbb; }
277 tr.failure, tr.rejected { background: #ffbbbb; }
278 tr.todo { background: white; }
279 tr.building { background: #ffff99; }
280 tr.partial { background: #bbbbff; }
281 tr.built { background: #cceeff; }
282
283 td.status-box { width: 1em; height: 1em; }
284 tr.uploaded td.status-box { background: green; }
285 tr.failure td.status-box, tr.rejected td.status-box { background: red; }
286 tr.todo td.status-box { background: white; }
287 tr.building td.status-box { background: yellow; }
288 tr.partial td.status-box { background: blue; }
289 tr.built td.status-box { background: #00ccff; }
290
291 #stats { float: right; }
292 #score { margin-bottom: 2em; font-family: Helvetica, Verdana, Arial, sans-serif; }
293 #score-box { width: 100px; height: 100px; background: #faa; }
294 #score-meter { width: 100px; background: #afa; }
295 </style>
296 </head>
297 <body>
298 <h1><?php echo $title ?></h1>
299
300 <?php
301 if (!is_null($g_user))
302 echo '<a href="/">&laquo;&nbsp;Back to full list</a>';
303
304 # Temporary until initial mirror is ready
305 echo sprintf(
306 '<p><a href="%s">%s broken dependencies</a>. <a href="%s">%s unmaintained packages</a>. <strong><a href="%s">You can help!</a></strong></p>',
307 'data/missing-deps.i586.txt', count($missing_deps) == 0 ? 'no' : count($missing_deps),
308 'data/unmaintained.txt', count($unmaintained),
309 'https://wiki.mageia.org/en/Importing_packages'
310 );
311
312 #########################################
313
314 if ($upload_time) {
315 echo sprintf('<p>Upload in progress for %s.</p>', timediff($upload_time));
316 }
317
318 $buildtime_stats = array();
319
320 // Builds in progress
321 $s = '';
322 $tmpl = <<<TB
323 <tr>
324 <td>%s</td>
325 <td>%s</td>
326 <td><a href="?user=%s">%s</a></td>
327 <td>%s</td>
328 <td>%s</td>
329 <td>%s/%s</td>
330 </tr>
331 TB;
332 foreach ($hosts as $machine => $b) {
333 foreach ($b as $arch => $key) {
334 $s .= sprintf($tmpl,
335 $machine,
336 $arch,
337 $pkgs[$key]['user'], $pkgs[$key]['user'],
338 $pkgs[$key]['package'],
339 $pkgs[$key]['version'],
340 $pkgs[$key]['media'], $pkgs[$key]['section']);
341 }
342 }
343 echo '<div align="center"><table>',
344 '<caption>', count($hosts), ' builds in progress.</caption>',
345 '<tr><th>Machine</th><th>Arch</th><th>User</th><th>Package</th><th>Target</th><th>Media</th></tr>',
346 $s,
347 '</table></div>';
348 echo '<div class="clear"></div>';
349
350 $s = '';
351 $tmpl = <<<T
352 <tr class="%s">
353 <td>%s</td>
354 <td><a href="?user=%s">%s</a></td>
355 <td><a href="http://svnweb.mageia.org/packages?view=revision&revision=%d" title="%s">%s</a></td>
356 <td>%s</td>
357 <td>%s/%s</td>
358 <td class="status-box"></td>
359 T;
360
361 if ($total > 0) {
362 foreach ($pkgs as $key => $p) {
363 $s .= sprintf($tmpl,
364 $p['type'],
365 timediff(key2timestamp($key)) . ' ago',
366 $p['user'], $p['user'],
367 $p['revision'],
368 addslashes($p['summary']),
369 $p['package'],
370 $p['version'],
371 $p['media'], $p['section']
372 );
373
374 $typelink = '';
375 if ($p['type'] == 'failure') {
376 $typelink = '/uploads/' . $p['type'] . '/' . $p['path'];
377 } elseif ($p['type'] == 'rejected') {
378 $typelink = '/uploads/' . $p['type'] . '/' . $p['path'] . '.youri';
379 }
380 $typestr = $p['type'];
381 if ($p['status']['build']) {
382 $typealt = 'Building on';
383 foreach ($p['status']['build'] as $h)
384 $typealt .= " $h";
385 $typestr = "<span title='$typealt'>$typestr</a>";
386 }
387
388 $s .= '<td>';
389 $s .= ($typelink != '') ?
390 sprintf('<a href="%s">%s</a>', $typelink, $typestr) :
391 $typestr;
392
393 $s .= '</td><td>';
394 if ($p['type'] == 'uploaded') {
395 $tdiff = timediff($p['buildtime']['start'], $p['buildtime']['end']); // use $p['buildtime']['diff']; instead?
396 $s .= $tdiff;
397 @$buildtime_stats[$tdiff] += 1;
398 }
399 $s .= '</td>';
400 $s .= '</tr>';
401 }
402 // Table
403 echo '<table>',
404 '<caption>', $total, ' packages submitted in the past ', $max_modified * 24, '&nbsp;hours.</caption>',
405 '<tr><th>Submitted</th><th>User</th>
406 <th>Package</th><th>Target</th><th>Media</th>
407 <th colspan="2">Status</th><th>Build time</th></tr>',
408 $s,
409 '</table>';
410
411 // Stats
412 $s = '<div id="stats">';
413 $score = round($stats['uploaded']/$total * 100);
414 $s .= sprintf('<div id="score"><h3>Score: %d/100</h3>
415 <div id="score-box"><div id="score-meter" style="height: %dpx;"></div></div></div>',
416 $score, $score);
417
418 $s .= '<table style="width: 100%"><caption>Stats.</caption><tr><th colspan="2">Status</th><th>Count</th><th>%</th></tr>';
419 foreach ($stats as $k => $v) {
420 $s .= sprintf('<tr class="%s"><td class="status-box"></td><td>%s</td><td>%d</td><td>%d%%</td></tr>',
421 $k, $k, $v, round($v/$total*100));
422 }
423
424 $s .= '</table><br /><br />';
425
426 $s .= '<table style="width: 100%"><caption>Packagers</caption><tr><th>User</th><th>Packages</th></tr>';
427 arsort($users);
428 foreach ($users as $k => $v)
429 $s .= sprintf('<tr><td><a href="/?user=%s">%s</a></td><td>%d</td></tr>',
430 $k, $k, $v);
431
432 $s .= '</table><br /><br />';
433
434 /**
435 */
436 function timesort($a, $b)
437 {
438 $a = explode(' ', trim($a));
439 $b = explode(' ', trim($b));
440
441 if ($a[1] == 'hour' || $a[1] == 'hours')
442 $a[0] *= 3600;
443
444 if ($b[1] == 'hour' || $a[1] == 'hours')
445 $b[0] *= 3600;
446
447 if ($a[0] > $b[0])
448 return 1;
449 elseif ($a[0] < $b[0])
450 return -1;
451
452 return 0;
453 }
454 uksort($buildtime_stats, "timesort");
455
456 $bts = '';
457 $max = max($buildtime_stats);
458 foreach ($buildtime_stats as $time => $count) {
459 $bts .= sprintf('<tr><td>%s</td><td><span style="width: %dpx; height: 10px; background: #aaa; display: block;" title="%d"></span></td></tr>',
460 $time,
461 round($count/$max*100),
462 $count);
463
464 $tmp = explode(' ', $time);
465 }
466
467 $s .= '<table style="width: 100%;"><caption>Build time</caption>';
468
469 $s .= sprintf('<tr><td>Total time</td><td>%s hours</td></tr>
470 <tr><td>Average</td><td>%s minutes</td></tr>
471 <tr><td>Builds count</td><td>%s</td></tr>',
472 round($buildtime_total / 60, 2),
473 $buildtime_avg,
474 $buildtime_cnt);
475
476 $s .= '<tr><th title="Build time">Duration</th><th title="Packages number">Pack. nb.</th></tr>';
477 $s .= $bts;
478 $s .= '</table><span style="font-size: 85%;">Does not take<br />build failures<br />into account.</span>';
479
480 $s .= '<table><caption>Build times</caption>';
481 $max = max($build_dates);
482 foreach ($build_dates as $time => $count)
483 $s .= sprintf('<tr><td>%d</td><td><span style="width: %dpx; height: 10px; background: #aaa; display: block;" title="%d"></span></td></tr>',
484 $time,
485 round($count / $max * 100),
486 $count);
487 $s .= '</table>';
488
489 $s .= '</div>';
490
491 echo $s;
492 }
493 else
494 {
495 echo sprintf('<p>No package has been submitted in the past %d&nbsp;hours.</p>',
496 $max_modified * 24);
497 }
498
499 ?>
500 <div class="clear"></div>
501 <hr />
502 <p>Generated at <?php echo $date_gen; ?>.
503 Code for this page is in <a href="http://svnweb.mageia.org/soft/build_system/web/">http://svnweb.mageia.org/soft/build_system/web/</a>.</p>
504 </body>
505 </html>

  ViewVC Help
Powered by ViewVC 1.1.30