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
41 changes: 13 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,36 +52,21 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Get the changelog underline
id: changelog_underline
# towncrier writes the rendered notes to stdout (informational
# chatter goes to stderr), so this is the curated release body for
# this version, not github-tag-action's commit-derived changelog.
- name: Generate the GitHub release notes
env:
RELEASE: ${{ steps.calver.outputs.release }}
run: |
underline="$(echo "$RELEASE" | tr -c '\n' '-')"
echo "underline=${underline}" >> "$GITHUB_OUTPUT"

- name: Update changelog
id: update_changelog
uses: jacobtomlinson/gha-find-replace@v3
with:
find: "Next\n----"
replace: |
Next
----

${{ steps.calver.outputs.release }}
${{ steps.changelog_underline.outputs.underline }}
include: CHANGELOG.rst
regex: false
run: uv run --extra=release towncrier build --draft --version "$RELEASE" >
release-notes.md

- name: Check Update changelog was modified
# Assemble the same fragments into CHANGELOG.rst under a new
# ``$RELEASE`` section and delete the consumed fragment files.
- name: Update the changelog
env:
MODIFIED_FILES: ${{ steps.update_changelog.outputs.modifiedFiles }}
run: |
if [ "$MODIFIED_FILES" = "0" ]; then
echo "Error: No files were modified when updating changelog"
exit 1
fi
RELEASE: ${{ steps.calver.outputs.release }}
run: uv run --extra=release towncrier build --yes --version "$RELEASE"

- name: Update VERSION file for Nix flake
env:
Expand All @@ -93,7 +78,7 @@ jobs:
id: commit
with:
commit_message: Bump CHANGELOG and VERSION
file_pattern: CHANGELOG.rst VERSION
file_pattern: CHANGELOG.rst newsfragments VERSION
# Error if there are no changes.
skip_dirty_check: true

Expand Down Expand Up @@ -203,7 +188,7 @@ jobs:
tag: ${{ steps.tag_version.outputs.new_tag }}
makeLatest: true
name: Release ${{ steps.tag_version.outputs.new_tag }}
body: ${{ steps.tag_version.outputs.changelog }}
bodyFile: release-notes.md

build-linux:
name: Build Linux binary (${{ matrix.binary.name }})
Expand Down
3 changes: 1 addition & 2 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
Changelog
=========

Next
----
.. towncrier release notes start

2026.02.22
----------
Expand Down
9 changes: 9 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,20 @@
extensions = [
"sphinx_copybutton",
"sphinxcontrib.spelling",
"sphinxcontrib.towncrier.ext",
"sphinx_click.ext",
"sphinx_inline_tabs",
"sphinx_substitution_extensions",
]

# Render the unreleased ``newsfragments/`` entries into
# ``docs/source/unreleased.rst`` so the Sphinx spelling, doc-build and
# link-checking gates cover the prose before it is assembled into
# CHANGELOG.rst at release time.
towncrier_draft_autoversion_mode = "draft"
towncrier_draft_include_empty = True
towncrier_draft_working_directory = f"{_pyproject_file.parent}"

templates_path = ["_templates"]
source_suffix = ".rst"
master_doc = "index"
Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ Reference
commands
contributing
release-process
unreleased
changelog
8 changes: 8 additions & 0 deletions docs/source/unreleased.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Unreleased changes
==================

Changes that have landed on the main branch but are not yet part of a
tagged release. These entries are assembled into the
:doc:`changelog` when the next release is published.

.. towncrier-draft-entries::
14 changes: 14 additions & 0 deletions docs/towncrier_template.rst.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

{% for section_name, section in sections.items() %}
{% if section %}
{% for category, entries in section.items() %}
{% for text, _ in entries.items() %}
- {{ text }}

{% endfor %}
{% endfor %}
{% else %}
No significant changes.

{% endif %}
{% endfor %}
Empty file added newsfragments/.gitkeep
Empty file.
33 changes: 33 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,16 @@ optional-dependencies.dev = [
"sphinx-pyproject==0.3.0",
"sphinx-substitution-extensions==2026.1.12",
"sphinxcontrib-spelling==8.0.2",
# ``sphinxcontrib-towncrier`` renders unreleased news fragments
# into docs/source/unreleased.rst during Sphinx builds.
"sphinxcontrib-towncrier==0.5.0a0",
# Listed explicitly (despite being transitive via vws-python-mock) so that
# [tool.uv.sources] can redirect to the CPU-only PyTorch index.
# See: https://vws-python.github.io/vws-python-mock/installation.html#faster-installation
"strict-kwargs==2026.5.19.post3",
"torch>=2.5.1",
"torchvision>=0.20.1",
"towncrier==25.8.0",
"ty==0.0.38",
"types-pyyaml==6.0.12.20260518",
"vulture==2.16",
Expand Down Expand Up @@ -277,6 +281,8 @@ ignore = [
"*.enc",
".pre-commit-config.yaml",
"CHANGELOG.rst",
"newsfragments",
"newsfragments/**",
"CODE_OF_CONDUCT.rst",
"CONTRIBUTING.rst",
"LICENSE",
Expand Down Expand Up @@ -350,6 +356,30 @@ report.exclude_also = [
]
report.show_missing = true

[tool.towncrier]
# The changelog and the per-release GitHub release notes are both built
# from news fragments under ``newsfragments/``. The release workflow
# runs ``towncrier build`` to assemble them; contributors add one
# fragment file per user-facing change.
directory = "newsfragments"
filename = "CHANGELOG.rst"
# Custom template so an assembled version reproduces the historical
# style exactly: a bare ``<version>`` heading (no project name, no
# date) followed by a flat bullet list with no per-type sub-headings.
template = "docs/towncrier_template.rst.jinja"
title_format = "{version}"
# ``title_format`` underline first, then any nested headings. A bare
# version such as ``2026.05.18`` underlined with ``-`` matches every
# pre-towncrier entry in CHANGELOG.rst.
underlines = [ "-", "~", "^" ]
issue_format = "#{issue}"
type = [
# A single, unnamed fragment type keeps the assembled output as one
# flat bullet list, matching the historical changelog (which never
# grouped entries under "Features"/"Bugfixes"/... sub-headings).
{ directory = "change", name = "", showcontent = true },
]

[tool.pydocstringformatter]
write = true
split-summary-body = false
Expand Down Expand Up @@ -410,6 +440,9 @@ ignore_names = [
"spelling_word_list_filename",
"templates_path",
"warning_is_error",
"towncrier_draft_autoversion_mode",
"towncrier_draft_include_empty",
"towncrier_draft_working_directory",
]
exclude = [
# Duplicate some of .gitignore
Expand Down
30 changes: 30 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading