$matches[1], 'version' => $matches[2]);
} else {
return false;
}
}
$db = new SQLite3('autobuild.db');
$runs = Array();
$handle = opendir('cauldron/x86_64/core/');
while (false !== ($entry = readdir($handle))) {
if (preg_match("/^....-..-..$/", $entry, $matches)) {
array_push($runs, $matches[0]);
}
}
closedir($handle);
$handle = opendir('cauldron/aarch64/core/');
while (false !== ($entry = readdir($handle))) {
if (preg_match("/^....-..-..$/", $entry, $matches)) {
array_push($runs, $matches[0]);
}
}
closedir($handle);
sort($runs);
$latestlinks = glob("cauldron/*/core/latest");
$latest = 0;
foreach ($latestlinks as $link) {
# This is ugly but readlink() returns false even if is_link() returns
# true and readlink() as user apache in php cli works.
$date = trim(`readlink $link`);
if ($date > $latest) {
$latest = $date;
}
}
$run = $_GET['run'];
if (!$run || $run=="latest") {
$run = $latest;
}
foreach ($runs as $r) {
if ($r==$run) {
break;
}
$prev = $r;
}
$runepoc = strtotime($run);
$packages = Array();
if ($handle = opendir('/distrib/bootstrap/distrib/cauldron/SRPMS/core/release/')) {
while (false !== ($entry = readdir($handle))) {
if ($parsed = parse_package($entry)) {
$packages[$parsed['package']] = $entry;
}
}
closedir($handle);
}
$prev_failure = Array();
if ($prev) {
$status_name = array_shift(glob("cauldron/*/core/$prev/status.core.log"));
$status_file = fopen($status_name, "r");
if ($status_file !== false) {
// The file should always be there but better not get an infinite loop flooding the logs when it disappears
while (!feof($status_file)) {
$line = fgets($status_file);
if (preg_match("/^(.*): (.*)$/", $line, $matches)) {
$rpm = parse_package($matches[1]);
$status = $matches[2];
if ($status != "ok" && $status != "unknown" && $status != "not_on_this_arch") {
$prev_failure[$rpm['package']] = 1;
}
}
}
fclose($status_file);
}
}
$success = Array();
$failure = Array();
$fixed = Array();
$removed = Array();
$broken = Array();
$base_dir = array_shift(glob("cauldron/*/core/$run"));
$status_name = "$base_dir/status.core.log";
if (!file_exists($status_name)) {
echo "Invalid run";
exit;
}
$start_time = 0;
if (file_exists("$base_dir/VERSION")) {
#Mageia 5 Devel-i586-Download 20140311 15:50
#Mageia 5 Devel-x86_64-Download 20140311 15:50
$version = file_get_contents("$base_dir/VERSION");
preg_match('/ (\d{8} \d{2}:\d{2})$/', $version, $matches);
$start_time = strtotime($matches[1]);
}
$status_file = fopen($status_name, "r");
while (!feof($status_file)) {
$line = fgets($status_file);
if (preg_match("/^(.*): (.*)$/", $line, $matches)) {
$rpm = $matches[1];
$status = $matches[2];
if ($start_time == 0 && $status != 'recreate_srpm_failure' && $status != 'not_on_this_arch') {
$build_stat = stat("$base_dir/$rpm");
if ($build_stat && $build_stat['mtime']) {
$start_time = $build_stat['mtime'];
}
}
if ($status == "ok") {
array_push($success, $rpm);
} elseif ($status != "unknown" && $status != "not_on_this_arch"){
$failure[$rpm] = $status;
$parsed = parse_package($rpm);
$package = $parsed['package'];
if(!array_key_exists($package, $prev_failure)) {
$broken[$rpm] = 1;
}
if(!array_key_exists($package, $packages)) {
$removed[$rpm] = 1;
} else {
# For recreate_srpm_failure, $rpm is the one that was in the repo
# For other failures, mga release may be incorrect so use something less reliable
if ($status == 'recreate_srpm_failure' && $rpm != $packages[$package]) {
$fixed[$rpm] = 1;
} else {
$file = '/distrib/bootstrap/distrib/cauldron/SRPMS/core/release/' . $packages[$package];
if (file_exists($file)) {
$pkg_stat = stat($file);
if ($pkg_stat['mtime'] > $start_time) {
$fixed[$rpm] = 1;
}
}
}
}
}
}
}
fclose($status_file);
sort($success);
ksort($failure);
$nb_failed = count($failure);
$nb_success = count($success);
$nb_fixed = count($fixed);
$nb_removed = count($removed);
$nb_still_broken = $nb_failed - $nb_fixed - $nb_removed;
$nb_tried = $nb_failed + $nb_success;
$succes_percent = round($nb_success*1000/$nb_tried)/10;
$estimated_percent = round(($nb_success+$nb_fixed)*1000/($nb_tried-$nb_removed))/10;
$title = "Autobuild results for $run";
echo "
$title\n";
?>
= 4;
}
function get_package_id($package) {
global $db;
return $db->querySingle("SELECT Id FROM Packages WHERE Name = '$package'");
}
function get_build_history($package_id) {
global $db;
if ($package_id) {
# TODO: optimize by retrieving Runs.Id once at the start
$result = $db->query("SELECT ResultValues.Name FROM Runs, Results, ResultValues WHERE Runs.Id = Results.Run AND Results.Result = ResultValues.Id AND Results.Package = '$package_id' ORDER BY Start DESC LIMIT 10");
if ($result) {
$build_stats = Array();
while ($entry = $result->fetchArray(SQLITE3_ASSOC)) {
array_push($build_stats, $entry['Name']);
}
return $build_stats;
}
}
return false;
}
function get_package_attributes($package_id) {
global $db, $runepoc;
if ($package_id) {
# TODO: optimize by retrieving Runs.Id once at the start
$attributes = $db->querySingle("SELECT Attr FROM Attributes, Runs WHERE Runs.Id = Attributes.Run AND Runs.Start = $runepoc AND Attributes.Package = '$package_id';");
}
return $attributes;
}
function get_all_attributes() {
global $db, $runepoc;
$attributes = Array();
$attr_types = Array();
$result = $db->query("SELECT Attr FROM Attributes, Runs WHERE Runs.Id = Attributes.Run AND Runs.Start = $runepoc;");
if ($result) {
while ($entry = $result->fetchArray(SQLITE3_ASSOC)) {
foreach (explode(" ", $entry['Attr']) as $attr) {
if ($attr) {
$attributes[$attr] = True;
$attr_types[explode("_", $attr)[0]] = Array();
}
}
}
foreach (array_keys($attributes) as $attr) {
$parts = explode("_", $attr);
array_push($attr_types[$parts[0]], $parts[1]);
}
foreach ($attr_types as $attr_type => $attrs) {
sort($attr_types[$attr_type]);
}
}
ksort($attr_types);
return $attr_types;
}
function get_package_maintainers() {
global $failure;
$pkgs = Array();
$maintdb = file('/var/www/bs/data/maintdb.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($maintdb as $l) {
list($pkg, $m) = explode(" ", $l);
if ($m == "") {
$m = "nobody";
}
$pkgs[$pkg] = $m;
}
$failedpkgs = Array();
foreach ($failure as $rpm => $error) {
$parsed = parse_package($rpm);
$pkg = $parsed["package"];
$failedpkgs[$pkg] = $pkgs[$pkg];
}
return $failedpkgs;
}
echo "\n";
echo "";
if (array_key_exists('include_success', $_GET) && $_GET['include_success'] === 'true') {
echo "Only failures";
} else {
echo "Include successful packages";
}
echo "\n";
echo "Changes since this run
\n";
echo "\n";
echo "Fixed | $nb_fixed |
\n";
echo "Removed | $nb_removed |
\n";
echo "Unchanged | $nb_still_broken |
\n";
echo "
\n";
echo "
If no new package was broken, success rate next time should be $estimated_percent%.\n";
$all_attrs = get_all_attributes();
$pkg_maintainers = get_package_maintainers();
$maintainers_package_count = array_count_values($pkg_maintainers);
arsort($maintainers_package_count);
$filters = Array();
if ($all_attrs) {
echo "Filters
\n";
echo "If nothing is checked on a line, that category is not filtered, else only the values checked appear.";
echo "";
}
echo "Failed builds ($nb_failed/$nb_tried)
\n";
echo "\n";
echo " | Status | Failure type | Build step | | Languages | Detected errors |
\n";
foreach ($failure as $rpm => $error) {
$parsed = parse_package($rpm);
$history_link = 'History';
$status_html = "";
if (array_key_exists($rpm, $fixed)) {
$status_html = " Fixed";
} elseif (array_key_exists($rpm, $removed)) {
$status_html = " Removed";
} elseif (array_key_exists($rpm, $broken)) {
$status_html = " New";
}
$error_html = $error;
if (file_exists("icons/error-$error.png")) {
$error_html = " $error";
}
$packageid = get_package_id($parsed['package']);
$history = get_build_history($packageid);
if (is_flaky($history)) {
$history_link = $history_link . " ";
}
$langs = "";
$errors = "";
$stage = "";
$attributes = get_package_attributes($packageid);
if (isset($pkg_maintainers[$parsed['package']])) {
$maintainer = $pkg_maintainers[$parsed['package']];
} else {
$maintainer = "nobody";
}
$attributes .= " maintainer_$maintainer";
if ($attributes) {
# Attributes are space separated words of the form "TYPE_SPECIFIER", e.g., "lang_php"
# Types are currently build (use of a particular build system),
# lang (use of a programming language) or err (a common build error).
$to_filter = $filters;
foreach (explode(" ", $attributes) as $attr) {
if (empty($attr)) {
continue;
}
$attrtype = explode("_", $attr)[0];
$attrname = explode("_", $attr)[1];
if ($to_filter[$attrtype]) {
if (in_array($attrname, $filters[$attrtype])) {
# This package matches one of the wanted attributes for this type,
# no need to check further.
$to_filter[$attrtype] = Array();
}
}
if ($attrtype === "lang") {
$lang = ucfirst($attrname);
$icon_fn = "icons/" . str_replace("_", "-", $attr) . ".png";
if (file_exists($icon_fn)) {
$langs = $langs . " ";
} else {
$langs = $langs . " $lang";
}
} elseif ($attrtype === "err") {
$errors = "$errors $attrname";
} elseif ($attrtype === "stage") {
if ($attrname != 'nobuild') {
if ($attrname == 'preprep') {
$stage = 'Before %prep';
} else {
$stage = "%$attrname";
}
}
}
}
# If filters on any type of attribute is not satisfied, skip the package
foreach ($to_filter as $attr_type => $attrs) {
if ($attrs) {
continue 2;
}
}
}
echo "";
if (file_exists("$base_dir/$rpm/")) {
echo "$rpm | ";
} else {
echo "$rpm | ";
}
echo "$status_html | $error_html | $stage | $history_link | $langs | $errors |
\n";
}
$db->close();
?>
Successful builds ($nb_success/$nb_tried)\n\n";
foreach ($success as $rpm) {
$parsed = parse_package($rpm);
$history_link = '[h]';
if (file_exists("$base_dir/$rpm/")) {
echo "- $rpm $history_link
\n";
} else {
echo "- $rpm $history_link
\n";
}
}
echo "
\n";
}
?>