Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/scripts/build_release_body.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


def extract_changelog_block(changelog: str, version: str) -> str:
"""Return lines from "Version {version}..." until the next long-dash separator."""
"""Return a version heading and its block, skipping the heading separator."""
if not version or not re.match(r"^[\d.]+$", version):
return ""
lines = changelog.splitlines()
Expand All @@ -31,6 +31,8 @@ def extract_changelog_block(changelog: str, version: str) -> str:
for j in range(start_idx, len(lines)):
line = lines[j]
if j > start_idx and sep.match(line):
if j == start_idx + 1:
continue
break
out.append(line)
return "\n".join(out) + "\n" if out else ""
Expand Down
40 changes: 40 additions & 0 deletions .github/scripts/test_build_release_body.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
"""Regression tests for extracting release notes from the root ChangeLog."""

import unittest

from build_release_body import extract_changelog_block


class ExtractChangelogBlockTests(unittest.TestCase):
def test_skips_heading_separator_and_stops_at_next_release(self):
changelog = "\n".join(
[
"--------------------------------------------------------------------------------",
"Version 5.0.2, 2026-09-28",
"--------------------------------------------------------------------------------",
"- Security fixes & hardening",
" - Reporter credit: Thanks to @KHr00t.",
"--------------------------------------------------------------------------------",
"Version 5.0.1, 2026-05-04",
"--------------------------------------------------------------------------------",
"- Older changes",
]
)

result = extract_changelog_block(changelog, "5.0.2")

self.assertIn("- Security fixes & hardening", result)
self.assertIn("@KHr00t", result)
self.assertNotIn("Version 5.0.1", result)
self.assertNotIn("--------------------------------------------------------------------------------", result)

def test_returns_empty_for_missing_or_invalid_version(self):
changelog = "Version 5.0.2, 2026-09-28\n- Notes\n"

self.assertEqual("", extract_changelog_block(changelog, "5.0.3"))
self.assertEqual("", extract_changelog_block(changelog, "5.0.2/extra"))


if __name__ == "__main__":
unittest.main()
8 changes: 8 additions & 0 deletions .github/workflows/php-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ on:
workflow_dispatch:

jobs:
release-notes:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Test ChangeLog release-note extraction
run: python3 .github/scripts/test_build_release_body.py

php-lint:
runs-on: ubuntu-latest
strategy:
Expand Down
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Version 5.0.2, 2026-09-28
--------------------------------------------------------------------------------
- Security fixes & hardening
- **Reporter credit:** Thank you to [@KHr00t](https://github.com/KHr00t) for responsibly reporting the security issues addressed in this release.
- Prevent SQL injection in chart ordering and database-source mappings by validating supported identifiers and using parameterized database operations, including validation of persisted mappings.
- Harden reflected and stored HTML output across administration, source, user, error, and confirmation views; constrain redirects to safe internal destinations.
- Restrict disk-source reads to canonical, readable regular files beneath configured allowed directories, including protection against traversal, symlink escapes, and path-prefix collisions.
Expand Down
Loading