From 83577c195581ec89b5ea7b24c8b9b8257e275f18 Mon Sep 17 00:00:00 2001 From: Sebastian Abrahamsson Date: Wed, 14 Oct 2026 11:17:10 +0200 Subject: [PATCH] Name the release notes of the next release unreleased.md release_notes/0.2.0.md becomes release_notes/unreleased.md, so the notes of the next release don't name a version before it is decided. The commit bumping the version renames the file to release_notes/.md, which the release workflow publishes, and tools/release.py validate --tag fails while unreleased.md still exists. The docs list unreleased.md first, titled Unreleased. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish.yml | 3 ++- docs/conf.py | 7 ++++--- release_notes/{0.2.0.md => unreleased.md} | 0 tools/release.py | 10 +++++++++- 4 files changed, 15 insertions(+), 5 deletions(-) rename release_notes/{0.2.0.md => unreleased.md} (100%) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 12b38af..f968113 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -165,7 +165,8 @@ jobs: name: distribution path: dist - # The release says what release_notes/.md says, or else what was written + # The release says what release_notes/.md says, renamed from + # release_notes/unreleased.md in the commit bumping the version, or else what was written # when the tag was made, or else what GitHub generates from the merged pull requests. - name: '🏷️ Create the release' env: diff --git a/docs/conf.py b/docs/conf.py index c137c1d..af62e19 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,10 +46,11 @@ } -# The release notes page, generated from release_notes/*.md, newest first +# The release notes page, generated from release_notes/*.md: unreleased.md, then the releases, newest first _notes = ["Release notes", "=============", ""] -for _path in sorted((ROOT / "release_notes").glob("*.md"), key=lambda path: Version(path.stem), reverse=True): - _title = _path.stem if Version(_path.stem) <= Version(release) else "Unreleased" +_releases = sorted((ROOT / "release_notes").glob("[0-9]*.md"), key=lambda path: Version(path.stem), reverse=True) +for _path in sorted((ROOT / "release_notes").glob("unreleased.md")) + _releases: + _title = _path.stem.capitalize() _notes += [_title, "-" * len(_title), "", f".. include:: ../release_notes/{_path.name}"] _notes += [" :parser: myst_parser.sphinx_", ""] (ROOT / "docs" / "release_notes.rst").write_text("\n".join(_notes)) diff --git a/release_notes/0.2.0.md b/release_notes/unreleased.md similarity index 100% rename from release_notes/0.2.0.md rename to release_notes/unreleased.md diff --git a/tools/release.py b/tools/release.py index 2242953..219516b 100644 --- a/tools/release.py +++ b/tools/release.py @@ -14,7 +14,8 @@ python tools/release.py version print the version of pyproject.toml python tools/release.py validate check that the version is a release version python tools/release.py validate --tag v1.2.3 - check the tag against it as well + check the tag against it as well, and that + release_notes/unreleased.md was renamed """ import argparse @@ -24,6 +25,7 @@ from pathlib import Path PYPROJECT = Path(__file__).parent.parent.resolve() / "pyproject.toml" +UNRELEASED_NOTES = PYPROJECT.parent / "release_notes" / "unreleased.md" # The versions a release may have: MAJOR.MINOR.PATCH, optionally a pre-release of it. RELEASE_VERSION = re.compile(r"\d+\.\d+\.\d+(a\d+|b\d+|rc\d+)?") @@ -55,6 +57,12 @@ def validate(tag) -> None: f"Expected the tag v{project_version}." ) + if tag is not None and UNRELEASED_NOTES.exists(): + raise SystemExit( + f"{UNRELEASED_NOTES} still exists. Rename it to release_notes/{project_version}.md " + "in the commit bumping the version." + ) + print(f"Version {project_version}" + ("" if tag is None else f", tagged {tag}"))