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

Contents of /build_system/web/index.php

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.30