$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 "

$title

\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 "\n"; echo "\n"; echo "\n"; echo "
Fixed$nb_fixed
Removed$nb_removed
Unchanged$nb_still_broken
\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 "
\n"; if ($_GET["run"]) { echo "\n"; } foreach ($all_attrs as $attr_type => $attrs) { echo "$attr_type: "; $filters[$attr_type] = Array(); foreach ($attrs as $attr) { if ($_GET["attr_$attr_type_$attr"]) { $checked = "checked"; array_push($filters[$attr_type], $attr); } else { $checked=""; } echo "$attr\n"; } echo "
\n"; } echo "maintainer: "; $filters["maintainer"] = Array(); echo "\n"; echo "\n"; echo "
"; } echo "

Failed builds ($nb_failed/$nb_tried)

\n"; echo "\n"; echo "\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 ""; } else { echo ""; } echo "\n"; } $db->close(); ?>
StatusFailure typeBuild stepLanguagesDetected errors
$rpm$rpm$status_html$error_html$stage$history_link$langs$errors
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"; } ?>