From 4aad31e5a8951101ec93ed56c04a8b00422338a9 Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Sat, 10 Oct 2026 12:59:56 +0100 Subject: [PATCH 1/3] Generate release notes with semantic line breaks --- .github/towncrier_template.md.jinja | 26 ++++++++++++++++++++++++++ pyproject.toml | 4 +++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 .github/towncrier_template.md.jinja diff --git a/.github/towncrier_template.md.jinja b/.github/towncrier_template.md.jinja new file mode 100644 index 000000000..5761afffb --- /dev/null +++ b/.github/towncrier_template.md.jinja @@ -0,0 +1,26 @@ +{# Preserve semantic lines in fragments and keep issue links on a separate line. #} +{%- set newline = "\n" -%} +{{- "# " ~ versiondata.version ~ " (" ~ versiondata.date ~ ")" ~ newline ~ newline }} +{%- for section, categories in sections.items() %} + {%- if section %} + {{- "## " ~ section ~ newline ~ newline }} + {%- endif %} + {%- for category, definition in definitions.items() if category in categories %} + {{- ("### " if section else "## ") ~ definition.name ~ newline ~ newline }} + {%- for text, issues in categories[category].items() %} + {%- if text %} + {{- text.replace("\n ", "\n") if text.startswith("- ") else "- " ~ text }} + {%- if issues %} + {%- set separate_paragraph = "\n - " in text or "\n * " in text or not text.rstrip().endswith((".", "!", "?")) %} + {{- newline ~ (newline if separate_paragraph else "") ~ " (" ~ issues | join(", ") ~ ")" }} + {%- endif %} + {%- elif issues %} + {{- "- " ~ issues | join(", ") }} + {%- endif %} + {{- newline }} + {%- endfor %} + {{- newline }} + {%- else %} + {{- "No significant changes." ~ newline ~ newline }} + {%- endfor %} +{%- endfor %} diff --git a/pyproject.toml b/pyproject.toml index a594a86f1..f194e903f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -448,7 +448,9 @@ report.show_missing = true # Write the same native Markdown file used by documentation and GitHub releases. directory = "newsfragments" filename = "docs/source/changelog/{version}.md" -title_format = "# {version} ({project_date})" +# The template renders the release heading and preserves semantic line breaks. +template = ".github/towncrier_template.md.jinja" +title_format = false issue_format = "[#{issue}](https://github.com/VWS-Python/vws-python/issues/{issue})" single_file = false # Reject invalid fragment names instead of silently losing release entries. From 829b093da1b159e5b8fa726e394328d387d7c319 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Sat, 10 Oct 2026 12:01:38 +0000 Subject: [PATCH 2/3] [autofix.ci] apply automated fixes --- docs/source/changelog/2026.10.09.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/source/changelog/2026.10.09.md b/docs/source/changelog/2026.10.09.md index 8fa163cc5..585a8c525 100644 --- a/docs/source/changelog/2026.10.09.md +++ b/docs/source/changelog/2026.10.09.md @@ -2,9 +2,14 @@ ## Changes -- Cover server errors from synchronous and asynchronous cloud recognition queries. ([#3214](https://github.com/VWS-Python/vws-python/issues/3214)) -- Model test credentials as pairs and name OAuth endpoint metadata precisely, avoiding secret false positives. ([#3215](https://github.com/VWS-Python/vws-python/issues/3215)) -- Remove supported inline type-checking comments by teaching Ruff about runtime-evaluated `beartype` annotations and postponing test annotations. ([#3216](https://github.com/VWS-Python/vws-python/issues/3216)) -- Validate query and Model Target report response values at construction time. ([#3218](https://github.com/VWS-Python/vws-python/issues/3218)) -- Type decoded report response dictionaries as JSON values. ([#3223](https://github.com/VWS-Python/vws-python/issues/3223)) +- Cover server errors from synchronous and asynchronous cloud recognition queries. + ([#3214](https://github.com/VWS-Python/vws-python/issues/3214)) +- Model test credentials as pairs and name OAuth endpoint metadata precisely, avoiding secret false positives. + ([#3215](https://github.com/VWS-Python/vws-python/issues/3215)) +- Remove supported inline type-checking comments by teaching Ruff about runtime-evaluated `beartype` annotations and postponing test annotations. + ([#3216](https://github.com/VWS-Python/vws-python/issues/3216)) +- Validate query and Model Target report response values at construction time. + ([#3218](https://github.com/VWS-Python/vws-python/issues/3218)) +- Type decoded report response dictionaries as JSON values. + ([#3223](https://github.com/VWS-Python/vws-python/issues/3223)) - Publish native Markdown release notes and use the same notes in documentation where available. From 987c62502355bdf84ee67a74eb91068f105decdd Mon Sep 17 00:00:00 2001 From: Adam Dangoor Date: Sat, 10 Oct 2026 13:15:57 +0100 Subject: [PATCH 3/3] Format release notes with Snapper after Towncrier --- .github/towncrier_template.md.jinja | 26 -------------------------- .github/workflows/release.yml | 1 + pyproject.toml | 4 +--- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 .github/towncrier_template.md.jinja diff --git a/.github/towncrier_template.md.jinja b/.github/towncrier_template.md.jinja deleted file mode 100644 index 5761afffb..000000000 --- a/.github/towncrier_template.md.jinja +++ /dev/null @@ -1,26 +0,0 @@ -{# Preserve semantic lines in fragments and keep issue links on a separate line. #} -{%- set newline = "\n" -%} -{{- "# " ~ versiondata.version ~ " (" ~ versiondata.date ~ ")" ~ newline ~ newline }} -{%- for section, categories in sections.items() %} - {%- if section %} - {{- "## " ~ section ~ newline ~ newline }} - {%- endif %} - {%- for category, definition in definitions.items() if category in categories %} - {{- ("### " if section else "## ") ~ definition.name ~ newline ~ newline }} - {%- for text, issues in categories[category].items() %} - {%- if text %} - {{- text.replace("\n ", "\n") if text.startswith("- ") else "- " ~ text }} - {%- if issues %} - {%- set separate_paragraph = "\n - " in text or "\n * " in text or not text.rstrip().endswith((".", "!", "?")) %} - {{- newline ~ (newline if separate_paragraph else "") ~ " (" ~ issues | join(", ") ~ ")" }} - {%- endif %} - {%- elif issues %} - {{- "- " ~ issues | join(", ") }} - {%- endif %} - {{- newline }} - {%- endfor %} - {{- newline }} - {%- else %} - {{- "No significant changes." ~ newline ~ newline }} - {%- endfor %} -{%- endfor %} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8c021288e..b974a0a88 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -52,6 +52,7 @@ jobs: RELEASE: ${{ steps.calver.outputs.release }} run: | uv run --group=release towncrier build --yes --version "$RELEASE" + uv run --group=dev snapper --native --max-width 0 --in-place "docs/source/changelog/$RELEASE.md" cp "docs/source/changelog/$RELEASE.md" release-notes.md - uses: stefanzweifel/git-auto-commit-action@v7 diff --git a/pyproject.toml b/pyproject.toml index f194e903f..a594a86f1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -448,9 +448,7 @@ report.show_missing = true # Write the same native Markdown file used by documentation and GitHub releases. directory = "newsfragments" filename = "docs/source/changelog/{version}.md" -# The template renders the release heading and preserves semantic line breaks. -template = ".github/towncrier_template.md.jinja" -title_format = false +title_format = "# {version} ({project_date})" issue_format = "[#{issue}](https://github.com/VWS-Python/vws-python/issues/{issue})" single_file = false # Reject invalid fragment names instead of silently losing release entries.