Skip to content

Commit cf5b1de

Browse files
Changelog.md: put the 153.0 entry below the header, not above it
prepend_changelog prepended to the whole file, so the newest release landed above the document title. Changelog.md opened with the 153.0 entry and only reached "# Changelog" on line 100. The function now splits the file at the first "## [version]" heading and only rewrites the entry list below it, leaving the title block where it belongs. The header-only case is handled too, so the first entry ever added to a fresh changelog also lands under the title rather than on top of it. The 153.0 entry was moved by restoring the file to its pre-153.0 state and re-inserting through the fixed function, so this is the same text in the right place: entry count and byte length are unchanged.
1 parent ec6c7c5 commit cf5b1de

2 files changed

Lines changed: 32 additions & 10 deletions

File tree

Automation/publish.py

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,21 @@ def sync_docs_files(repo_dir, source_dir, logger=None) -> list:
182182

183183
_CHANGELOG_SEPARATOR = "\n\n---\n\n"
184184
_CHANGELOG_HEADING = re.compile(r"^## \[([^\]]+)\]")
185+
_FIRST_ENTRY = re.compile(r"^## \[", re.MULTILINE)
186+
187+
188+
def _split_changelog(text):
189+
"""(header, entries). The header is the document title block that must stay at the top:
190+
everything before the first "## [version]" entry, including its trailing divider.
191+
192+
Changelog.md opens with a title, a one-line description and a divider. Prepending to the
193+
file as a whole buries all of that under the newest release, which is what happened to
194+
the 153.0 entry: the file led with a release and only reached "# Changelog" on line 100.
195+
"""
196+
match = _FIRST_ENTRY.search(text)
197+
if not match:
198+
return text, ""
199+
return text[:match.start()], text[match.start():]
185200

186201

187202
def prepend_changelog(repo_dir, changelog_entry_text, logger=None) -> Path:
@@ -198,10 +213,13 @@ def prepend_changelog(repo_dir, changelog_entry_text, logger=None) -> Path:
198213
entry = changelog_entry_text.rstrip("\n")
199214
new_version = _CHANGELOG_HEADING.match(entry)
200215

216+
# The title block stays put; only the entry list below it is touched.
217+
header, entries = _split_changelog(existing)
218+
201219
# Docs/Changelog.md's own convention (confirmed against the real file): entries
202220
# separated by a "---" divider.
203-
if existing.strip():
204-
head, separator, tail = existing.partition(_CHANGELOG_SEPARATOR)
221+
if entries.strip():
222+
head, separator, tail = entries.partition(_CHANGELOG_SEPARATOR)
205223
head_version = _CHANGELOG_HEADING.match(head.lstrip())
206224
replacing = (
207225
separator
@@ -213,9 +231,13 @@ def prepend_changelog(repo_dir, changelog_entry_text, logger=None) -> Path:
213231
if logger:
214232
logger.info("changelog already has an entry for %s, replacing it in place",
215233
new_version.group(1))
216-
new_content = entry + _CHANGELOG_SEPARATOR + tail
234+
entries = entry + _CHANGELOG_SEPARATOR + tail
217235
else:
218-
new_content = f"{entry}{_CHANGELOG_SEPARATOR}{existing.lstrip()}"
236+
entries = f"{entry}{_CHANGELOG_SEPARATOR}{entries.lstrip()}"
237+
new_content = header + entries
238+
elif header.strip():
239+
# Header present but no entries yet: keep the header, add the first entry under it.
240+
new_content = header.rstrip("\n") + "\n\n" + entry + "\n"
219241
else:
220242
new_content = entry + "\n"
221243
changelog_path.write_text(new_content, encoding="utf-8")

Docs/Changelog.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Changelog
2+
3+
All releases of ducksteps. Newest first.
4+
5+
---
6+
17
## [153.0] (16/August/2026)
28

39
⛐ It's the "thirteen versions of catching up" release!
@@ -97,12 +103,6 @@ Low severity:
97103

98104
---
99105

100-
# Changelog
101-
102-
All releases of ducksteps. Newest first.
103-
104-
---
105-
106106
## [140.13.0] (21/July/2026)
107107

108108
⛐ It's the "exploit code's already out there" release!

0 commit comments

Comments
 (0)