Skip to content

Commit f1b9396

Browse files
authored
chore: add bin/generate-changelog (#466)
1 parent f467c2a commit f1b9396

File tree

2 files changed

+163
-0
lines changed

2 files changed

+163
-0
lines changed

.php-cs-fixer.dist.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
__FILE__,
2323
'.github/scripts/continuous-integration',
2424
'.github/scripts/update-license',
25+
'bin/generate-changelog',
2526
'bin/generate-page',
2627
'bin/test',
2728
'bin/update-en-comments',

bin/generate-changelog

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
declare(strict_types=1);
5+
6+
/**
7+
* This file is part of CodeIgniter 4 framework.
8+
*
9+
* (c) CodeIgniter Foundation <[email protected]>
10+
*
11+
* For the full copyright and license information, please view
12+
* the LICENSE file that was distributed with this source code.
13+
*/
14+
15+
use CodeIgniter\CLI\CLI;
16+
use Translations\Tests\AbstractTranslationTestCase;
17+
18+
require __DIR__ . '/../vendor/codeigniter4/codeigniter4/system/Test/bootstrap.php';
19+
20+
if (! isset($argv[1]) || ! in_array($argv[1], ['--major', '--minor', '--patch'], true)) {
21+
CLI::error(
22+
'Please provide the tagging strategy for this release: --major, --minor, --patch.',
23+
'light_gray',
24+
'red'
25+
);
26+
27+
exit(1);
28+
}
29+
30+
if (! function_usable('exec')) {
31+
CLI::error('The `exec()` function is needed but is disabled.', 'light_gray', 'red');
32+
33+
exit(1);
34+
}
35+
36+
$resultCode = 0;
37+
/** @var list<string> $output */
38+
$output = [];
39+
40+
exec('git describe --tags --abbrev=0 2>/dev/null', $output, $resultCode);
41+
42+
if ($resultCode !== 0) {
43+
CLI::error('Failed getting the latest tag.', 'light_gray', 'red');
44+
45+
exit($resultCode);
46+
}
47+
48+
$latestTag = $output[0];
49+
/** @var list<string> $changelog */
50+
$changelog = [];
51+
52+
exec(sprintf('git log --format=%%s %s...HEAD --reverse 2>/dev/null', $latestTag), $changelog, $resultCode);
53+
54+
if ($resultCode !== 0) {
55+
CLI::error('Failed getting the changelog from git.', 'light_gray', 'red');
56+
57+
exit($resultCode);
58+
}
59+
60+
$localeChanges = [];
61+
$otherChanges = [];
62+
63+
$nextTag = preg_replace_callback(
64+
'/^v(\d+)\.(\d+)\.(\d+)$/',
65+
static function (array $matches) use ($argv): string {
66+
switch ($argv[1]) {
67+
case '--patch':
68+
return sprintf('v%d.%d.%d', $matches[1], $matches[2], ++$matches[3]);
69+
70+
case '--minor':
71+
return sprintf('v%d.%d.0', $matches[1], ++$matches[2]);
72+
73+
case '--major':
74+
return sprintf('v%d.0.0', ++$matches[1]);
75+
}
76+
},
77+
$latestTag
78+
);
79+
80+
CLI::write(sprintf('Generating changelog for %s...', $nextTag), 'green');
81+
82+
sleep(1); // for cinematic effect
83+
84+
foreach ($changelog as $log) {
85+
if (preg_match('/^\[([a-zA-Z-]+)\].+/', $log, $match) === 1) {
86+
$locale = $match[1];
87+
88+
if (array_key_exists($locale, $localeChanges)) {
89+
continue;
90+
}
91+
92+
if (in_array($locale, AbstractTranslationTestCase::$locales, true)) {
93+
$class = array_search($locale, AbstractTranslationTestCase::$locales, true);
94+
95+
if (! is_string($class)) {
96+
continue;
97+
}
98+
99+
$localeChanges[$locale] = preg_replace_callback(
100+
'/\ATranslations\\\\Tests\\\\(\S+)TranslationTest\z/',
101+
static fn (array $matches): string => preg_replace(
102+
'/(?<!^)((?=[\p{Lu}][^\p{Lu}])|(?<![\p{Lu}])(?=[\p{Lu}]))/u',
103+
' ',
104+
$matches[1]
105+
),
106+
$class
107+
);
108+
109+
continue;
110+
}
111+
}
112+
113+
$otherChanges[] = $log;
114+
}
115+
116+
ksort($localeChanges);
117+
118+
CLI::write('Copy the following to the CHANGELOG.md file and edit the subheadings:', 'yellow');
119+
CLI::newLine();
120+
CLI::write(sprintf(
121+
<<<'CHANGELOG'
122+
## [%1$s](https://github.com/codeigniter4/translations/compare/%2$s...%1$s) - %3$s
123+
124+
### Changed
125+
126+
%4$s
127+
128+
### Others
129+
130+
- %5$s
131+
CHANGELOG,
132+
$nextTag,
133+
$latestTag,
134+
(new DateTimeImmutable('now', new DateTimeZone('UTC')))->format('Y-m-d'),
135+
implode("\n", array_map(
136+
static fn (string $value, string $key): string => sprintf('- %s (%s)', $key, $value),
137+
array_values($localeChanges),
138+
array_keys($localeChanges)
139+
)) ?: '- <none>',
140+
implode("\n- ", $otherChanges) ?: '<none>'
141+
));
142+
143+
sleep(1); // for cinematic effect
144+
145+
CLI::newLine();
146+
CLI::write('For reference, here is the complete changelog:', 'yellow');
147+
CLI::write(sprintf('- %s', implode("\n- ", $changelog) ?: '<none>'));
148+
149+
sleep(1); // for cinematic effect
150+
151+
CLI::newLine();
152+
CLI::write('After editing the CHANGELOG.md file, execute the following commands.', 'green');
153+
CLI::write(implode("\n", [
154+
'git add CHANGELOG.md',
155+
sprintf('git commit -S -m "Prepare changelog for %s"', $nextTag),
156+
'git push upstream develop',
157+
'git switch master',
158+
'git merge --ff develop',
159+
'git push upstream master',
160+
sprintf('git tag -s %1$s -m "CodeIgniter %1$s Translations"', $nextTag),
161+
'git push upstream --tags',
162+
]));

0 commit comments

Comments
 (0)