public static function getBugsFromHgWeb()

in app/classes/ReleaseInsights/Bugzilla.php [50:146]


    public static function getBugsFromHgWeb(string $query, bool $detect_backouts = false, int $cache_ttl = 0): array
    {
        if (json_validate($query)) {
            // We sometimes pass directly the result of a JSON response
            $results = Json::toArray($query)['pushes'] ?? null;
        } else {
            $results = Json::load($query, $cache_ttl)['pushes'] ?? null;
        }

        // Handle the lack of data from HG
        if (empty($results)) {
            return [
                'bug_fixes' => [],
                'backouts'  => [],
                'total'     => [],
                'no_data'   => true,
            ];
        }

        $changesets = array_column($results, 'changesets');
        $bug_fixes  = [];
        $backouts   = [];

        // Extract bug number from commit message
        $get_bugs = function (string $str): array {
            if (preg_match_all("/bug \d+/", $str, $matches)) {
                $matches[0] = array_map(
                    fn (string $str) => str_replace('bug', '', $str),
                    $matches[0]
                );

                $matches[0] = array_map('trim', $matches[0]);
            }
            return count($matches[0]) > 1 ? [$matches[0][0]] : $matches[0];
        };

        foreach ($changesets as $items) {
            foreach ($items as $subitem) {
                $subitem = explode("\n", (string) $subitem['desc'])[0];
                $subitem = strtolower(Utils::mtrim($subitem));

                if (Utils::startsWith($subitem, ['no bug', 'automatic version bump'])) {
                    continue;
                }

                // Commits can be ignored if they contain one of these strings
                $ignore_list = [
                    'a=test-only', 'a=release', 'a=npotb', 'a=searchfox-only',
                    'try-staging', 'taskcluster', 'a=tomprince', 'a=aki', 'a=testing',
                    '[mozharness]', 'r=aki', 'r=tomprince', 'r=mtabara', 'a=jorgk',
                    'beetmover', '[taskgraph]', 'a=testonly', 'a=bustage',
                    'a=expectation-update-for-worker-image',
                    'a=repo-update',
                ];

                if (Utils::inString($subitem, $ignore_list)) {
                    continue;
                }

                if (Utils::inString($subitem, ['Backed out', 'backed out', 'back out', 'Back out']) && $detect_backouts === true) {
                    $counter = count($bug_fixes);
                    $bug_fixes = array_diff($bug_fixes, $get_bugs($subitem));
                    if ($counter === count($bug_fixes)) {
                        $backouts[] = $subitem;
                    }
                    continue;
                }

                // We only include the first bug number mentionned for normal cases
                $bug_fixes = array_merge($bug_fixes, array_slice($get_bugs($subitem), 0, 1));
            }
        }

        $bug_fixes = array_unique($bug_fixes);

        $backed_out_bugs = [];

        foreach ($backouts as $backout) {
            $backed_out_bugs = [...$backed_out_bugs, ...$get_bugs($backout)];
        }

        $backed_out_bugs = array_unique($backed_out_bugs);

        // Substract bug_fixes that were backed out later
        $clean_bug_fixes = $bug_fixes;
        $clean_backed_out_bugs = array_diff($backed_out_bugs, $bug_fixes);

        $clean_bug_fixes = array_map('intval', $clean_bug_fixes);
        $clean_backed_out_bugs = array_map('intval', $clean_backed_out_bugs);

        return [
            'bug_fixes' => array_values($clean_bug_fixes),
            'backouts'  => array_values($clean_backed_out_bugs),
            'total'     => array_values([...$clean_bug_fixes, ...$clean_backed_out_bugs]),
            'no_data'   => false,
        ];
    }