mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-08-04 15:12:12 +00:00
ci: source release notes from CHANGELOG.md (#713)
Port of the 2.x change to 3.x, with the same extractor script. Registration sent the GitHub release body to the updater, so the notes every install sees were written at publish time — after review, outside the repo, with nothing checking they existed or matched what shipped. CHANGELOG.md becomes the source. It is written and reviewed alongside the change itself, so what installs are offered cannot drift from what was merged, and the release body can simply point at it. A release with no section for its tag fails the job rather than registering an empty changelog. A manual dispatch falls back to the release body, since re-registering a release older than this file is legitimate — which covers 3.0.0-alpha.1. Backfilled with 3.0.0-alpha.1.
This commit is contained in:
committed by
GitHub
parent
00cb1a6389
commit
3308f3b2fa
71
.github/scripts/changelog-section.php
vendored
Normal file
71
.github/scripts/changelog-section.php
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Print the CHANGELOG.md section for a released version.
|
||||
*
|
||||
* Usage: php .github/scripts/changelog-section.php <version> [changelog-path]
|
||||
*
|
||||
* Exits 1 when the version has no section, so a release whose notes were
|
||||
* forgotten stops the pipeline rather than registering an empty changelog on
|
||||
* the updater.
|
||||
*
|
||||
* Section boundaries are found by matching *version* headings, not any "## ",
|
||||
* because release notes routinely contain their own second-level headings. A
|
||||
* section therefore runs until the next heading that looks like a version.
|
||||
*/
|
||||
$version = $argv[1] ?? '';
|
||||
$path = $argv[2] ?? dirname(__DIR__, 2).'/CHANGELOG.md';
|
||||
|
||||
if ($version === '') {
|
||||
fwrite(STDERR, "usage: changelog-section.php <version> [changelog-path]\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (! is_readable($path)) {
|
||||
fwrite(STDERR, "changelog not readable: {$path}\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
$lines = preg_split('/\R/', (string) file_get_contents($path));
|
||||
|
||||
// A leading "v" is tolerated on either side so v2.4.2 and 2.4.2 both resolve.
|
||||
$isVersionHeading = static fn (string $line): bool => (bool) preg_match('/^##\s+v?\d+\.\d+\.\d+/i', $line);
|
||||
$wanted = ltrim($version, 'vV');
|
||||
|
||||
$section = [];
|
||||
$capturing = false;
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if ($isVersionHeading($line)) {
|
||||
if ($capturing) {
|
||||
break;
|
||||
}
|
||||
|
||||
// "## 2.4.2 — 2026-07-29" and "## 2.4.2" both match; a date or any other
|
||||
// trailing text is ignored, but 2.4.2 must not match 2.4.20.
|
||||
$capturing = (bool) preg_match(
|
||||
'/^##\s+v?'.preg_quote($wanted, '/').'(?![\w.-])/i',
|
||||
$line
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($capturing) {
|
||||
$section[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
$body = trim(implode("\n", $section));
|
||||
|
||||
if (! $capturing && $body === '') {
|
||||
fwrite(STDERR, "no CHANGELOG.md section found for {$version}\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ($body === '') {
|
||||
fwrite(STDERR, "CHANGELOG.md section for {$version} is empty\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo $body, "\n";
|
||||
Reference in New Issue
Block a user