From bf645cc6da5acdd59bbcdb05d24759e2c9bce105 Mon Sep 17 00:00:00 2001 From: Miuna Date: Wed, 9 Aug 2023 15:19:16 -0400 Subject: [PATCH 1/2] build: improve changelog parsing and order --- buildtools/changelog.php | 156 +++++++++++++++++++++++++++++++-------- 1 file changed, 126 insertions(+), 30 deletions(-) diff --git a/buildtools/changelog.php b/buildtools/changelog.php index 654515fbb4..aa945fe7d0 100755 --- a/buildtools/changelog.php +++ b/buildtools/changelog.php @@ -2,6 +2,20 @@ // D++ changelog generator, saves 15 minutes for each release :-) +// Categories, in display order +$catgroup = [ + '💣 Breaking Changes' => [], + '✨ New Features' => [], + '🐞 Bug Fixes' => [], + '🚀 Performance Improvements' => [], + '♻️ Refactoring' => [], + '🚨 Testing' => [], + '📚 Documentation' => [], + '💎 Style Changes' => [], + '🔧 Chore' => [], + '📜 Miscellaneous Changes' => [] +]; + // Pattern list $categories = [ 'break' => '💣 Breaking Changes', @@ -42,23 +56,16 @@ 'updated' => '📜 Miscellaneous Changes', ]; -$catgroup = []; $changelog = []; $githubstyle = true; if (count($argv) > 2 && $argv[1] == '--discord') { $githubstyle = false; } +$errors = []; // Magic sauce exec("git log --format=\"%s\" $(git log --no-walk --tags | head -n1 | cut -d ' ' -f 2)..HEAD | grep -v '^Merge '", $changelog); -// Leadin -if ($githubstyle) { - echo "The changelog is listed below:\n\nRelease Changelog\n===========\n"; -} else { - echo "The changelog is listed below:\n\n__**Release Changelog**__\n"; -} - // Case insensitive removal of duplicates $changelog = array_intersect_key($changelog, array_unique(array_map("strtolower", $changelog))); @@ -78,6 +85,21 @@ } } +function add_change(string $change, string $category, string $scope = null) { + global $catgroup; + + if (isset($scope) && !empty($scope)) { + // Group by feature inside the section + if (!isset($catgroup[$category][$scope])) { + $catgroup[$category][$scope] = []; + } + $catgroup[$category][$scope][] = $change; + } + else { + $catgroup[$category][] = $change; + } +} + foreach ($changelog as $change) { // Wrap anything that looks like a symbol name in backticks @@ -92,41 +114,111 @@ $change = preg_replace("/\b(was|is|wo)nt\b/i", '$1n\'t', $change); $change = preg_replace("/\bfreebsd\b/", 'FreeBSD', $change); $change = preg_replace("/``/", "`", $change); + $change = trim($change); - // Match keywords against categories $matched = false; - foreach ($categories as $cat => $header) { - // Purposefully ignored: comments that are one word, merge commits, and version bumps - if (strpos($change, ' ') === false || preg_match("/^Merge (branch|pull request|remote-tracking branch) /", $change) || preg_match("/version bump/i", $change)) { - $matched = true; - continue; - } - // Groupings - if ((preg_match("/^" . $cat . ":/i", $change)) || (preg_match("/^\[" . $cat . "\//i", $change)) || (preg_match("/^\[" . $cat . "\]/i", $change)) || (preg_match("/^\[" . $cat . ":/i", $change)) || (preg_match("/^" . $cat . "\//i", $change)) || (preg_match("/^" . $cat . ":/i", $change))) { - if (!isset($catgroup[$header])) { - $catgroup[$header] = []; + $matches = []; + // Extract leading category section + if (preg_match("/^((?:(?:[\w_]+(?:\([\w_]+\))?+)(?:[\s]*[,\/][\s]*)?)+):/i", $change, $matches) || preg_match("/^\[((?:(?:[\w_]+(?:\([\w_]+\))?+)(?:[\s]*[,\/][\s]*)?)+)\](?:\s*:)?/i", $change, $matches)) { + $categorysection = $matches[0]; + $changecategories = $matches[1]; + $matchflags = PREG_SET_ORDER | PREG_UNMATCHED_AS_NULL; + // Extract each category and scope + if (preg_match_all("/(?:[\s]*)([\w_]+)(?:\(([\w_]+)\))?(?:[\s]*)(?:[,\/]+)?/i", $changecategories, $matches, $matchflags) !== false) { + /** + * Given a commit "foo, bar(foobar): add many foos and bars" : + * $matches is [ + * 0 => [[0] => 'foo,', [1] => 'foo', [2] => null], + * 1 => [[0] => ' bar(foobar)', [1] => 'bar', [2] => 'foobar'], + * ] + * In other words, for a matched category N, matches[N][1] is the category, matches[N][2] is the scope + */ + $header = $matches[0][1]; + $scope = $matches[0][2]; + $change = trim(substr($change, strlen($categorysection))); + // List in breaking if present + foreach ($matches as $nb => $match) { + if ($nb == 0) // Skip the first category which will be added anyways + continue; + $category = $match[1]; + if (isset($categories[$category]) && $categories[$category] === '💣 Breaking Changes') + add_change($change, $categories[$category], $scope); + } + if (!isset($categories[$header])) { + $errors[] = "could not find category \"" . $header . "\" for commit \"" . $change . "\", adding it to misc"; + $header = $categories['misc']; + } + else { + $header = $categories[$header]; } - $matched = true; - $catgroup[$header][] = preg_replace("/^\S+\s+/", "", $change); - break; - } else if (preg_match("/^" . $cat . " /i", $change)) { if (!isset($catgroup[$header])) { $catgroup[$header] = []; } $matched = true; - $catgroup[$header][] = $change; - break; + // Ignore version bumps + if (!preg_match("/^(version )?bump/i", $change)) { + add_change($change, $header, $scope); + } + } + } + if (!$matched) { // Could not parse category section, try keywords + // Match keywords against categories + foreach ($categories as $cat => $header) { + // Purposefully ignored: comments that are one word, merge commits, and version bumps + if (strpos($change, ' ') === false || preg_match("/^Merge (branch|pull request|remote-tracking branch) /", $change) || preg_match("/^(version )?bump/i", $change)) { + $matched = true; + break; + } + if (preg_match("/^" . $cat . " /i", $change)) { + if (!isset($catgroup[$header])) { + $catgroup[$header] = []; + } + $matched = true; + $catgroup[$header][] = $change; + break; + } } } + if (!$matched) { + $errors[] = "could not guess category for commit \"" . $change . "\", adding it to misc"; + $header = $categories['misc']; + if (!isset($catgroup[$header])) { + $catgroup[$header] = []; + } + $matched = true; + $catgroup[$header][] = $change; + } +} + +// Leadin +if ($githubstyle) { + echo "The changelog is listed below:\n\nRelease Changelog\n===========\n"; +} else { + echo "The changelog is listed below:\n\n__**Release Changelog**__\n"; +} + +function print_change(string $change) { + global $githubstyle; + + // Exclude bad commit messages like 'typo fix', 'test push' etc by pattern + if (!preg_match("/^(typo|test|fix)\s\w+$/", $change) && strpos($change, ' ') !== false) { + echo ($githubstyle ? '-' : '•') . ' ' . ucfirst(str_replace('@', '', $change)) . "\n"; + } } // Output tidy formatting foreach ($catgroup as $cat => $list) { - echo "\n" . ($githubstyle ? '## ' : '__**') . $cat . ($githubstyle ? '' : '**__') . "\n"; - foreach ($list as $item) { - // Exclude bad commit messages like 'typo fix', 'test push' etc by pattern - if (!preg_match("/^(typo|test|fix)\s\w+$/", $item) && strpos($item, ' ') !== false) { - echo ($githubstyle ? '-' : '•') . ' ' . ucfirst(str_replace('@', '', $item)) . "\n"; + if (!empty($list)) { + echo "\n" . ($githubstyle ? '## ' : '__**') . $cat . ($githubstyle ? '' : '**__') . "\n"; + foreach ($list as $key => $item) { + if (is_array($item)) { + foreach ($item as $change) { + print_change("$key: $change"); + } + } + else { + print_change($item); + } } } } @@ -138,3 +230,7 @@ echo 'The ' . $version . ' download can be found here: '; echo "\n"; } + +foreach ($errors as $err) { + trigger_error($err, E_USER_WARNING); +} From 8e2b1040b99efd1ff7ad914ff23fd780bf372620 Mon Sep 17 00:00:00 2001 From: Miuna Date: Thu, 10 Aug 2023 12:30:01 -0400 Subject: [PATCH 2/2] =?UTF-8?q?build:=20fix=20codacy=20not=20liking=20"els?= =?UTF-8?q?e"=20for=20some=20reason=20=F0=9F=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- buildtools/changelog.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/buildtools/changelog.php b/buildtools/changelog.php index aa945fe7d0..f6bb57d378 100755 --- a/buildtools/changelog.php +++ b/buildtools/changelog.php @@ -94,10 +94,9 @@ function add_change(string $change, string $category, string $scope = null) { $catgroup[$category][$scope] = []; } $catgroup[$category][$scope][] = $change; + return; } - else { - $catgroup[$category][] = $change; - } + $catgroup[$category][] = $change; } foreach ($changelog as $change) {