changelog: dispatch write methods on entries vs legacy layout (PR 3b)#4524
Closed
Copilot wants to merge 2 commits into
Closed
changelog: dispatch write methods on entries vs legacy layout (PR 3b)#4524Copilot wants to merge 2 commits into
Copilot wants to merge 2 commits into
Conversation
✅ Deploy Preview for nifty-bassi-e26446 ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Agent-Logs-Url: https://github.com/envoyproxy/toolshed/sessions/a8deba8f-472f-4ee5-9fa0-88aa508e9db2 Co-authored-by: phlax <454682+phlax@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Implement PR 3b of the per-entry changelog plan
changelog: dispatch write methods on entries vs legacy layout (PR 3b)
May 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Write-path half of the per-entry changelog plan. Dispatches four mutating
AChangelogsmethods on_entries_layout(singleis_dir()againstchangelogs/current). Legacy branch of every method is byte-for-byte unchanged.Changes
write_version— entries branchcurrent/<section>/*.rstviaAChangelog.get_data_from_entries; propagatesChangelogParseErrorwith no side effects (no version file written, no rmtree)<version>.yamlviadump_yamlcurrent.yamltodate: Pending\nbefore rmtree (atomic ordering: file correct even if rmtree fails)_entries_layoutbeforeshutil.rmtree; recreates emptycurrent/immediately after so_entries_layoutstaysTruewhenwrite_currentruns nextwrite_current— entries branchWrites slim
date: Pending\nand recreatescurrent/with.gitkeep, preserving_entries_layout = Trueacrossrelease → devcycles. Documents the design choice in a comment.write_date— entries branchSlim current.yaml contains only the date key; literal
f"date: {date}\n"write is sufficient — no YAML round-trip needed.changes_for_commit— entries branchAdds
CHANGELOG_CURRENT_DIR_PATHto the changed set.changes_for_commitis called afterwrite_versionhas rmtree'd the directory, so globbing**/*.rstwould return nothing. Including the directory path is correct:git add <dir>stages deletions of tracked files removed from the working tree.is_pendingNo code change; added comment that it dispatches correctly via
AChangelog.dataon both layouts.Tests
All four methods parametrised across
entries_layout=[True, False]. Newtest_abstract_changelogs_write_version_entries_parse_errorexplicitly tests the no-side-effects safeguard onChangelogParseError. Coverage onchangelog.pyremains 100%.Original prompt
Context
Implements PR 3b of the per-entry changelog plan (see #4498, #4499,
plans/per-entry-changelog-4498.md). This is the write-path half of "Toolshed PR 3"; the read-path half landed as #4523.Dependencies (all landed on main):
envoy.base.utils: Add per-entry RST directory reader #4518 / py/envoy.base.utils: Add per file changelog read in util #4523 —AChangelog.get_data_from_entries(yaml_path, entry_dir), plus module-level constantsCHANGELOG_CURRENT_DIR_PATH,CHANGELOG_ENTRY_GLOB,ENTRY_SEPARATOR.envoy.base.utils: Switch to runtime validation for changelog sections #4519 —AChangelogs.validate_sections(data, path=None).envoy.base.utils: Add per file changelog read in util #4523 —AChangelogs._entries_layout(@property, uncached, singleis_dir()against<project_path>/changelogs/current),current_dir_path,rel_current_dir_path.AChangelog.dataalready dispatches on_entries_layout and _is_current.envoy.code.check: Add per-entry changelog validation #4522 —envoy.code.checkenforces filename / content / section rules per entry; per-file errors survive parse failures.Main is at
ee9b62f5661abb7b76ed02c01a06b55774c06928.Backward-compatibility principle (non-negotiable)
Single
is_dir()check on<project_path>/changelogs/current. Both layouts must continue to work indefinitely:release/v1.xx) cut before the migration use legacy and stay legacy.If
changelogs/current/is a directory → entries layout. Otherwise → legacy. Strict dispatch: the entries branch must never operate on a repo without the directory; the legacy branch must never look at the directory.What this PR does
File:
py/envoy.base.utils/envoy/base/utils/abstract/project/changelog.pyDispatches four mutating methods on
AChangelogs._entries_layout. The legacy branch of each method is byte-for-byte the existing implementation — do not refactor existing behaviour. Only the entries branch is new.1.
write_version— release moment, the dangerous oneCurrent behaviour (legacy branch — keep unchanged):
This copies the full
current.yamlcontent (with all entries) intochangelogs/<version>.yaml, thenwrite_currentrecreates a blankcurrent.yaml.On the entries layout, the slim
current.yamlhas onlydate: ...; the entries live incurrent/<section>/<area>__<slug>.rst. Sowrite_versionmust:AChangelog.get_data_from_entries(current_path, current_dir_path)— same code path used bydata.ChangelogDictto YAML at<version>.yaml. Use the same dumper the file already uses for any existing YAML emission — look fordump_yaml,yaml.dump, or similar in this module / the package. Match the byte format other historical<version>.yamlfiles use (block style, key order:datefirst then sections insections.yamlorder if possible; otherwise alphabetical / insertion-ordered to match what the current pipeline produces).shutil.rmtree(current_dir_path)to remove the entries directory. The nextdevcycle'swrite_currentwill recreate it.Critical safeguards:
Refuse on parse failure. If
get_data_from_entriesraisesChangelogParseError, propagate it without writing<version>.yamland withoutrmtree. A bad aggregation must not corrupt the historical record.Re-check
_entries_layoutbeforermtree. Guard the destructive step:Defensive — covers the (unlikely) race where the directory disappeared between dispatch and rmtree.
Atomic-ish ordering. Write the new
<version>.yamlfirst, thenrmtree. Ifrmtreefails, the version file is already correct; the next run will retry the rmtree (or surface the failure visibly). Do NOT rmtree first.Add
import shutilat the top of the module if not already present.2.
write_current— start of new dev cycleCurrent behaviour (legacy branch — keep unchanged):
The legacy template renders a full YAML scaffold with
date: Pendingplus empty section keys.On the entries layout, write a slim YAML containing only
date: Pending:That's it — no template, no section keys. The entries directory does not need to exist at this point; contributors create
current/<section>/on demand when they add the first entry. Do not create an emptycurrent/directory.Detection: at the moment
write_currentis called (duringdev), the previouswrite_versionstep may have just rmtree'd the directory, so_entries_layoutis nowFalse. But the layout the project is **going to be on...This pull request was created from Copilot chat.