http://www.mediawiki.org/wiki/Special:Code/MediaWiki/84511
Revision: 84511
Author: demon
Date: 2011-03-22 01:13:01 +0000 (Tue, 22 Mar 2011)
Log Message:
-----------
Add weekly bug summary script
Added Paths:
-----------
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/weekly-bug-summary.html.tmpl
trunk/tools/bugzilla/bugzilla-4.0/weekly-bug-summary.cgi
Added:
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/weekly-bug-summary.html.tmpl
===================================================================
---
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/weekly-bug-summary.html.tmpl
(rev 0)
+++
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/weekly-bug-summary.html.tmpl
2011-03-22 01:13:01 UTC (rev 84511)
@@ -0,0 +1,94 @@
+[%# Wikimedia weekly bug summary template #%]
+
+[% PROCESS global/variables.none.tmpl %]
+
+[% PROCESS global/header.html.tmpl
+ title = "Wikimedia Weekly Bug Summary"
+%]
+
+<h3 style="text-align:center;">Total: [% totalbugs %] bugs and [% totalwishes
%] wishes</h3>
+
+<h4 style="text-align:center;">[% new_open_bugs %] bugs opened, [%
new_closed_bugs %] bugs closed in the last [% duration %] days<br>
+([% new_open_wishes %] wishes opened, [% new_closed_wishes %] wishes
closed)</h4>
+
+<form action="weekly-bug-summary.cgi" style="text-align:center;">Report top
+ [% sel = { name => 'tops'} %]
+ [% INCLUDE select %]
+summary over the last
+ [% sel = { name => 'days'} %]
+ [% INCLUDE select %]
+days and <input type="submit" value="Show" />
+</form>
+
+<h3 style="text-align:center;">Top [% top_number %] Wikimedia products with
the most bugs:</h3>
+
+<table align="center" border="0" cellspacing="2" cellpadding="5">
+<tr style="background-color: #EEF6FF;"><th>Product</th>
+<th>Open<br />bugs</th>
+<th>Opened in<br />last [% duration %] days</th>
+<th>Closed in<br />last [% duration %] days</th>
+<th>Change</th>
+<th>Open<br />wishes</th>
+<th>Opened in<br />last [% duration %] days</th>
+<th>Closed in<br />last [% duration %] days</th>
+<th>Change</th>
+<th> </th></tr>
+
+[%- FOREACH pr = product_bug_lists %]
+<tr>
+ <td><a href="component-report.cgi?product=[%- pr.name -%]">[%- pr.name
-%]</a></td>
+ <td style="text-align:right;"><a href="buglist.cgi?product=[%- pr.name
-%]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=critical&bug_severity=grave&bug_severity=major&bug_severity=crash&bug_severity=normal&bug_severity=minor">[%-
pr.count -%]</a></td>
+ <td style="text-align:right;">+[%- pr.bugs_opened -%]</td>
+ <td style="text-align:right;">-[%- pr.bugs_closed -%]</td>
+ <td style="text-align:right; background-color: [%- pr.bugs_change_color
-%];">[%- pr.bugs_change -%]</td>
+ <td style="text-align:right;"><a href="buglist.cgi?product=[%- pr.name
-%]&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_severity=wishlist">[%-
pr.total_wishes -%]</a></td>
+ <td style="text-align:right;">+[%- pr.open_wishes -%]</td>
+ <td style="text-align:right;">-[%- pr.closed_wishes -%]</td>
+ <td style="text-align:right; background-color: [%-
pr.wishes_change_color -%];">[%- pr.wishes_change -%]</td>
+ <td style="text-align:right;"><a href="reports.cgi?product=[%- pr.name
-%]&output=show_chart&datasets=NEW%3A&datasets=ASSIGNED%3A&datasets=REOPENED%3A&datasets=UNCONFIRMED%3A&datasets=RESOLVED%3A&banner=1">Graph</a></td>
+</tr>
+[% END %]
+</table>
+
+<h3 style="text-align:center;"><a name="closers">Top [% top_number %] people
who resolved the most reports in the last [% duration %] days:</a></h3>
+<table align="center" border="0" cellspacing="2" cellpadding="5">
+<tr style="background-color: #EEF6FF;">
+ <th>User</th><th># Resolved</th>
+</tr>
+[%- FOREACH bh = bug_hunters_list %]
+<tr>
+ <td>[% bh.user FILTER html %]</td>
+ <td>[% bh.count %]</td>
+<tr>
+[% END %]
+</table>
+
+<h3 style="text-align:center;"><a name="fixers">Top [% top_number %] people
who most quickly fixed a report in the last [% duration %] days:</a></h3>
+<table align="center" border="0" cellspacing="2" cellpadding="5">
+<tr style="background-color: #EEF6FF;">
+<th>User</th><th>Elapsed time</th></tr>
+[%- FOREACH bf = bug_fixers_list %]
+<tr>
+ <td>[% bf.name FILTER html %]</td>
+ <td>[% bf.formatted_elapsed %] (<a href="show_bug.cgi?id=[% bf.bugid
%]">[% bf.bugid %]</a>)</td>
+</tr>
+[% END %]
+</table>
+
+[% PROCESS global/footer.html.tmpl %]
+
+
+[%##########################################################################%]
+[%# Block for SELECT fields #%]
+[%##########################################################################%]
+
+[% BLOCK select %]
+ <select name="[% sel.name %]">
+ [%- FOREACH x = ${sel.name} %]
+ <option value="[% x FILTER html %]"
+ [% " selected=\"selected\"" IF x == default.${sel.name} %]>
+ [% x FILTER html %]
+ </option>
+ [% END %]
+ </select>
+[% END %]
Property changes on:
trunk/tools/bugzilla/bugzilla-4.0/template/en/custom/reports/weekly-bug-summary.html.tmpl
___________________________________________________________________
Added: svn:eol-style
+ native
Added: trunk/tools/bugzilla/bugzilla-4.0/weekly-bug-summary.cgi
===================================================================
--- trunk/tools/bugzilla/bugzilla-4.0/weekly-bug-summary.cgi
(rev 0)
+++ trunk/tools/bugzilla/bugzilla-4.0/weekly-bug-summary.cgi 2011-03-22
01:13:01 UTC (rev 84511)
@@ -0,0 +1,385 @@
+#!/usr/bin/perl -wT
+
+# its stolen from somewhere but was mostly re-written by Dirk Mueller
<[email protected]>, 08/2006
+# templatized by Matt Rogers <[email protected]>, 12/2007
+use strict;
+use lib ".";
+
+use Bugzilla;
+use Bugzilla::Constants;
+use Bugzilla::Util;
+use Bugzilla::Error;
+use Bugzilla::Field;
+
+sub total_bugs_in_bugzilla()
+{
+ my $dbh = Bugzilla->dbh;
+
+ # figure out total bugs
+ my (@totalbugs) = $dbh->selectrow_array(
+ "SELECT count(bugs.bug_id) FROM bugs WHERE bugs.bug_severity !=
'wishlist' AND
+ ( bugs.bug_status = 'NEW' or bugs.bug_status = 'ASSIGNED' or
+ bugs.bug_status = 'REOPENED' or bugs.bug_status = 'UNCONFIRMED')"
+ );
+
+ # figure out total number of wishes
+ my (@totalwishes) = $dbh->selectrow_array (
+ "SELECT count(bugs.bug_id) FROM bugs WHERE bugs.bug_severity =
'wishlist' AND
+ ( bugs.bug_status = 'NEW' or bugs.bug_status = 'ASSIGNED' or
+ bugs.bug_status = 'REOPENED' or bugs.bug_status = 'UNCONFIRMED')"
+ );
+
+ return ($totalbugs[0], $totalwishes[0]);
+}
+
+sub bugs_opened()
+{
+ my($product, $days) = @_;
+
+ my $sqlproduct = "";
+ $sqlproduct = "AND bugs.product_id=$product"
+ if(defined $product and $product ne "%");
+
+ my ($count) = Bugzilla->dbh->selectrow_array(
+ "SELECT count(bugs.bug_id) FROM bugs
+ WHERE creation_ts >= from_days(to_days(NOW())-?)
+ $sqlproduct AND bugs.bug_severity != 'wishlist'", undef, ($days)
+ );
+
+ return $count;
+}
+
+sub wishes_opened()
+{
+ my($product, $days) = @_;
+
+ my $sqlproduct = "";
+ $sqlproduct = "AND bugs.product_id=" . Bugzilla->dbh->quote($product)
+ if(defined $product and $product ne "%");
+
+ my ($count) = Bugzilla->dbh->selectrow_array(
+ "SELECT count(bugs.bug_id) FROM bugs
+ WHERE creation_ts >= from_days(to_days(NOW())-?)
+ $sqlproduct AND bugs.bug_severity = 'wishlist'", undef, ($days)
+ );
+
+ return $count;
+}
+
+sub bugs_closed()
+{
+ my($product, $days) = @_;
+ my $query = "";
+ my $sqlproduct = "";
+ $sqlproduct = "AND bugs.product_id=" . Bugzilla->dbh->quote($product)
+ if(defined $product and $product ne "%");
+
+ my ($count) = Bugzilla->dbh->selectrow_array("
+select
+ count(distinct bugs.bug_id)
+from
+ bugs, bugs_activity
+where
+ bugs.bug_severity != 'wishlist' AND
+ (bugs_activity.added='RESOLVED' or bugs_activity.added='CLOSED' or
+ bugs_activity.added='NEEDSINFO')
+and
+ bugs_activity.bug_when >= FROM_DAYS(TO_DAYS(NOW())-?)
+and
+ bugs.bug_id = bugs_activity.bug_id
+ $sqlproduct
+ ", undef, ($days));
+
+ return($count);
+}
+
+sub wishes_closed()
+{
+ my($product, $days) = @_;
+ my $query = "";
+ my $sqlproduct = "";
+ $sqlproduct = "AND bugs.product_id=" . Bugzilla->dbh->quote($product)
+ if(defined $product and $product ne "%");
+
+ # We are going to build a long SQL query.
+ my ($count) = Bugzilla->dbh->selectrow_array("
+select
+ count(distinct bugs.bug_id)
+from
+ bugs, bugs_activity
+where
+ bugs.bug_severity = 'wishlist' AND
+ (bugs_activity.added='RESOLVED' or bugs_activity.added='CLOSED' or
+ bugs_activity.added='NEEDSINFO')
+and
+ bugs_activity.bug_when >= FROM_DAYS(TO_DAYS(NOW())-?)
+and
+ bugs.bug_id = bugs_activity.bug_id
+ $sqlproduct
+ ", undef, ($days));
+
+ return($count);
+}
+
+sub open_wishes()
+{
+ my($product) = @_;
+
+ my $sqlproduct = "";
+ $sqlproduct = "AND bugs.product_id=" . Bugzilla->dbh->quote($product)
+ if(defined $product and $product ne "%");
+
+ # We are going to build a long SQL query.
+ my ($count) = Bugzilla->dbh->selectrow_array("
+SELECT
+ count(bugs.bug_id)
+FROM bugs
+WHERE bugs.bug_severity = 'wishlist' AND
+ (bugs.bug_status = 'NEW' or bugs.bug_status = 'ASSIGNED' or
+ bugs.bug_status = 'REOPENED' or bugs.bug_status = 'UNCONFIRMED')
+$sqlproduct");
+
+ return $count;
+}
+
+
+# $format can be HTML or XML
+sub print_product_bug_lists() {
+ my($number, $days, $format, $fh) = @_;
+
+ my $query;
+
+ my @results;
+
+ # We are going to build a long SQL query.
+ my $sth = Bugzilla->dbh->prepare("
+select
+ products.name, bugs.product_id, count(bugs.product_id) as n
+from
+ bugs, products
+where
+ (bugs.bug_status = 'NEW' or bugs.bug_status = 'ASSIGNED' or
+ bugs.bug_status = 'REOPENED' or bugs.bug_status = 'UNCONFIRMED')
+and
+ bugs.bug_severity != 'wishlist'
+and
+ products.id = bugs.product_id
+
+group by product_id
+order by n desc
+limit $number
+ ");
+ $sth->execute;
+
+ # For each product we want to show the difference in the last period.
+ # But this will involve two sql connections at once, which the bugzilla
+ # functions don't handle too nicely.
+ # So lets collect the data first and then print the table.
+ my %product_count;
+ my %product_id;
+
+ while (my ($product, $p_id, $count) = $sth->fetchrow_array) {
+ $product_count{$product} = $count;
+ $product_id{$product} = $p_id;
+ }
+
+
+ foreach my $product (reverse sort
+ {$product_count{$a} <=> $product_count{$b}}
+ keys (%product_count)) {
+ my %product_results;
+ my $bopened = &bugs_opened($product_id{$product}, $days);
+ my $bclosed = &bugs_closed($product_id{$product}, $days);
+ $product_results{'id'} = $product_id{$product};
+ $product_results{'name'} = $product;
+ $product_results{'count'} = $product_count{$product};
+ $product_results{'bugs_opened'} = $bopened;
+ $product_results{'bugs_closed'} = $bclosed;
+ $product_results{'bugs_change'} = $bopened - $bclosed;
+ if( $product_results{'bugs_change'} > 0 ) {
+ $product_results{'bugs_change_color'} = "#FF9999";
+ } elsif( $product_results{'bugs_change'} < 0 ) {
+ $product_results{'bugs_change_color'} = "#99FF99";
+ }
+ $product_results{'total_wishes'} = &open_wishes($product_id{$product});
+ $product_results{'open_wishes'} =
&wishes_opened($product_id{$product}, $days);
+ $product_results{'closed_wishes'} =
&wishes_closed($product_id{$product}, $days);
+ $product_results{'wishes_change'} = $product_results{'open_wishes'} -
+ $product_results{'closed_wishes'};
+ if( $product_results{'wishes_change'} > 0 ) {
+ $product_results{'wish_change_color'} = "#FF9999";
+ } elsif( $product_results{'wishes_change'} < 0 ) {
+ $product_results{'wish_change_color'} = "#99FF99";
+ }
+ push @results, \%product_results;
+ }
+
+ return \@results;
+}
+
+sub print_bug_hunters_list() {
+ my($number, $days) = @_;
+ my @results;
+ my $query;
+
+ my $sth = Bugzilla->dbh->prepare("
+select
+ assign.login_name, count(assign.login_name), count(assign.login_name) as n
+from
+ bugs, bugs_activity, profiles assign
+where
+ (bugs_activity.added='RESOLVED' or bugs_activity.added = 'CLOSED' or
+ bugs_activity.added='NEEDSINFO')
+and
+ bugs_activity.bug_when >= from_days(TO_DAYS(NOW()) - ?)
+and
+ bugs_activity.who = assign.userid
+and
+ bugs.bug_id = bugs_activity.bug_id
+and
+ (bugs.bug_status = 'RESOLVED' or bugs.bug_status = 'CLOSED')
+group by assign.login_name
+order by n desc
+limit ?
+ ");
+
+ $sth->execute($days, $number);
+ while (my ($user, $count, $n) = $sth->fetchrow_array()) {
+
+ my %bh_results;
+
+ # defang the email address
+ $user =~ y/\@\./ / if (Bugzilla->user->id == 0);
+ $bh_results{'user'} = $user;
+ $bh_results{'count'} = $count;
+
+ push @results, \%bh_results;
+ }
+
+ return \@results;
+}
+
+sub print_bug_fixers_list() {
+ my($number, $days) = @_;
+ my @results;
+
+ my $sth = Bugzilla->dbh->prepare("
+SELECT
+ profiles.login_name, bugs.bug_id,
+
MIN(UNIX_TIMESTAMP(bugs_activity.bug_when)-UNIX_TIMESTAMP(bugs.creation_ts))
+ AS open_time
+FROM
+ bugs, bugs_activity, profiles, longdescs
+WHERE
+ bugs.resolution='FIXED'
+AND
+ bugs.bug_status='RESOLVED'
+AND
+ bugs_activity.bug_when >= FROM_DAYS(TO_DAYS(NOW())-?)
+AND
+ bugs.bug_id=bugs_activity.bug_id
+AND
+ bugs_activity.added='FIXED'
+AND
+ bugs_activity.who=profiles.userid
+AND
+ bugs.reporter != bugs_activity.who
+AND
+ longdescs.bug_id = bugs.bug_id
+AND
+ longdescs.who = bugs_activity.who
+AND
+ longdescs.thetext like \"SVN commit%\"
+GROUP BY
+ profiles.login_name, bugs.bug_id
+ORDER BY
+ open_time ASC
+LIMIT ?");
+
+ $sth->execute($days, $number);
+
+ while (my ($user, $bugid, $elapsed) = $sth->fetchrow_array) {
+
+ my %bf_results;
+
+ # defang the email address
+ $user =~ y/\@\./ / if (Bugzilla->user->id == 0);
+ $bf_results{'name'} = $user;
+ $bf_results{'elapsed'} = ${elapsed};
+ my $html_elapsed = "${elapsed}s";
+ $html_elapsed = int($elapsed/60) . " min" if ($elapsed > 60);
+ $html_elapsed = int($elapsed/(60*60)) . " h" if ($elapsed > (4*60*60));
+ $html_elapsed = int($elapsed/(60*60*24)) . " days" if ($elapsed >
(58*60*60));
+ $bf_results{'formatted_elapsed'} = $html_elapsed;
+ $bf_results{'bugid'} = $bugid;
+
+ push @results, \%bf_results;
+ }
+
+ return \@results;
+}
+
+
+Bugzilla->login(LOGIN_OPTIONAL);
+
+# For most scripts we don't make $cgi and $template global variables. But
+# when preparing Bugzilla for mod_perl, this script used these
+# variables in so many subroutines that it was easier to just
+# make them globals.
+local our $cgi = Bugzilla->cgi;
+local our $template = Bugzilla->template;
+local our $vars = {};
+
+# Output appropriate HTTP response headers
+print $cgi->header(-type => 'text/html', -expires => '+3M');
+
+my %defaults;
+
+# If they didn't tell us a time period we choose the last week.
+my $current_days = 7;
+$current_days = $cgi->param('days') if (defined $cgi->param('days'));
+$current_days = 7 if (!detaint_natural($current_days));
+$defaults{'days'} = $current_days;
+
+my $current_tops = 20;
+$current_tops = $cgi->param('tops') if (defined $cgi->param('tops'));
+$current_tops = 20 if (!detaint_natural($current_tops));
+$defaults{'tops'} = $current_tops;
+
+$vars->{'duration'} = $current_days;
+$vars->{'top_number'} = $current_tops;
+
+($vars->{'totalbugs'}, $vars->{'totalwishes'}) = &total_bugs_in_bugzilla();
+
+my $bo = &bugs_opened("%", $current_days);
+my $wo = &wishes_opened("%", $current_days);
+my $bc = &bugs_closed("%", $current_days);
+my $wc = &wishes_closed("%", $current_days);
+
+$vars->{'new_open_bugs'} = $bo;
+$vars->{'new_closed_bugs'} = $bc;
+$vars->{'new_open_wishes'} = $wo;
+$vars->{'new_closed_wishes'} = $wc;
+
+my @tops = (10, 20, 30, 50, 100);
+$vars->{'tops'} = \@tops;
+
+my @days = (1, 2, 7, 14, 31, 180, 365);
+$vars->{'days'} = \@days;
+
+$vars->{'default'} = \%defaults;
+
+$vars->{'product_bug_lists'} = &print_product_bug_lists($current_tops,
$current_days, "HTML");
+
+$vars->{'bug_hunters_list'} = &print_bug_hunters_list($current_tops,
$current_days);
+
+$vars->{'bug_fixers_list'} = &print_bug_fixers_list($current_tops,
$current_days);
+
+$template->process("reports/weekly-bug-summary.html.tmpl", $vars)
+ || ThrowTemplateError($template->error());
+
+
+
+
+
+print "</div>\n";
Property changes on: trunk/tools/bugzilla/bugzilla-4.0/weekly-bug-summary.cgi
___________________________________________________________________
Added: svn:eol-style
+ native
_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs