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
43 changes: 43 additions & 0 deletions .github/workflows/changelog-checker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Check Changelog Entry

on:
pull_request:
types: [opened, synchronize, reopened, labeled, unlabeled]

permissions:
contents: read
pull-requests: read

jobs:
check-changelog:
if: >
!contains(github.event.pull_request.labels.*.name, 'no-changelog') &&
github.event.pull_request.user.login != 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Check for direct CHANGES file edits
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
echo "Checking for changelog file in PR #$PR_NUMBER"
changed_files=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/files" | jq -r '.[].filename')
echo "Changed files: $changed_files"
if echo "$changed_files" | grep -qE "^CHANGES\.rst$"; then
echo "Do not edit the changelog file directly."
echo "Create a new file in the \`changes\` directory, see \`changes/README.rst\` for details."
exit 1
fi
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.x"
- name: Install towncrier
run: python -m pip install -U pip towncrier
- name: Check changelog entry
run: towncrier check --compare-with origin/${{ github.event.pull_request.base.ref }}
28 changes: 3 additions & 25 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,32 +1,10 @@
Changelog
=========

16.5 (unreleased)
-----------------

Bug fixes
+++++++++

- Prevent a rerun when a fixture teardown raises an error matching
``--rerun-except``. Previously only the error from the current test stage
was considered, so a ``--rerun-except``-matching error raised during
teardown was ignored and the test was rerun anyway.
Fixes `#270 <https://github.com/pytest-dev/pytest-rerunfailures/issues/270>`_.

- Create a new test class instance for each rerun. Previously the instance of
the failed attempt was reused, so state stored on ``self`` leaked into the
rerun and broke test isolation. Fixtures cached at class scope or higher are
still not re-executed.
Fixes `#268 <https://github.com/pytest-dev/pytest-rerunfailures/issues/268>`_.

Features
++++++++

- Add ``--max-suite-reruns`` option to cap the total number of reruns across
the entire test suite. Once the limit is reached, no further reruns occur
regardless of per-test ``--reruns`` or ``@pytest.mark.flaky`` settings.
Fixes `#298 <https://github.com/pytest-dev/pytest-rerunfailures/issues/298>`_.
.. Do not edit this file manually any more, create a change log entry file in
.. the changes directory, see changes/README.rst for details.

.. towncrier release notes start

16.4 (2026-07-01)
-----------------
Expand Down
29 changes: 27 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,30 @@ Preparing Pull Requests

#. Follow **PEP 8** for naming and `black <https://github.com/psf/black>`_ for formatting.

#. Add a line item to the current **unreleased** version in ``CHANGES.rst``,
unless the change is trivial.
#. Add a change log entry, unless the change is trivial. Do **not** edit
``CHANGES.rst`` -- it is generated at release time. Instead create a file in
the ``changes/`` directory named after the GitHub issue or pull request
number, with an extension naming the kind of change, for example
``changes/270.bugfix.rst``. See `changes/README.rst
<https://github.com/pytest-dev/pytest-rerunfailures/blob/master/changes/README.rst>`_
for the available types and the expected style.


Making a release
----------------

Releases are made with `zest.releaser
<https://zestreleaser.readthedocs.io/>`_ together with the
``zestreleaser.towncrier`` plugin, which runs ``towncrier build`` at the right
moment so ``CHANGES.rst`` is assembled from the files in ``changes/``::

$ pip install --group release
$ fullrelease

``pip install --group release`` requires pip 25.1 or newer; with an older pip
use ``pip install "zest.releaser[recommended]" zestreleaser.towncrier``
instead.

To preview the change log for the next release without writing anything::

$ towncrier build --draft --version 17.0
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ exclude *.yaml
recursive-include docs *.py
recursive-include docs *.rst
recursive-include docs *.txt

graft changes
prune changes
1 change: 1 addition & 0 deletions changes/268.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Create a new test class instance for each rerun. Previously the instance of the failed attempt was reused, so state stored on ``self`` leaked into the rerun and broke test isolation. Fixtures cached at class scope or higher are still not re-executed.
1 change: 1 addition & 0 deletions changes/270.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent a rerun when a fixture teardown raises an error matching ``--rerun-except``. Previously only the error from the current test stage was considered, so a ``--rerun-except``-matching error raised during teardown was ignored and the test was rerun anyway.
1 change: 1 addition & 0 deletions changes/298.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add ``--max-suite-reruns`` option to cap the total number of reruns across the entire test suite. Once the limit is reached, no further reruns occur regardless of per-test ``--reruns`` or ``@pytest.mark.flaky`` settings.
63 changes: 63 additions & 0 deletions changes/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Writing change log entries
==========================

.. caution::
Do not edit the ``CHANGES.rst`` file manually, this file is now autogenerated
at release time. This prevents getting conflicts in that file during merge
time.

File name
---------

To add an entry to the change log, take the number of the GitHub issue and you
create a file inside of the ``changes/`` directory, named after that issue
number with an extension telling the type of change, followed by ``.rst``. The
allowed types are:

* ``feature``: You added a new feature.
* ``bugfix``: You fixed a bug.
* ``doc``: You improved the documentation.
* ``removal``: You deprecated or removed a public API.
* ``breaking``: You changed the public API in a way which requires changes in
the consumers of the API.
* ``misc``: You changed something which is of minor interest to the users of
this package, e. g. the development or test setup.

Example: If your GitHub issue number is 270 and you fixed the bug reported
there, you create a file named ``270.bugfix.rst`` in the ``changes/``
directory. You can also let towncrier create it for you::

$ towncrier create --content "Fix the thing." 270.bugfix

If your pull request does not have an issue, use the number of the pull request
itself.

Each type is rendered as a sub-headline in the change log. If your changes match
multiple types and should show up below different sub-headlines in the change
log or you resolved multiple issues just create multiple files in ``changes/``.
If the files contain the same text, the entries in the changelog will get
deduplicated.

The part before the type must be the plain issue number -- do not add a
description to it, as it ends up in the change log as the issue reference. If
you need more than one entry of the *same* type for the *same* issue, append a
counter between the type and the extension, e. g. ``270.misc.rst`` and
``270.misc.2.rst``. The counter is only used to keep the file names unique and
to order the entries, it does not show up in the change log.

Contents of a changes entry
---------------------------

In the contents of the file you tell what you have changed. You can use
reStructuredText markup here. Please do *not* repeat the issue number in the
file: the link to the GitHub issue is added automatically from the file name.

Do not hard wrap the text of an entry: towncrier re-wraps each paragraph to fit
the change log, and hard wrapping produces a ragged result.

In order to maintain a consistent style in the change log, it is preferred to
keep the entries to the point, in sentence case, and in an imperative tone -- an
entry should complete the sentence “This change will …”. In rare cases, where
one line is not enough, use a summary line in an imperative tone followed by a
blank line separating it from a description of the feature/change in one or more
paragraphs.
27 changes: 27 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ entry-points.pytest11.rerunfailures = "pytest_rerunfailures"
[dependency-groups]
dev = [
"mypy>=2.1",
"towncrier>=25.8",
]
release = [
"zest-releaser[recommended]>=9.9",
"zestreleaser-towncrier>=2",
]

[tool.setuptools.dynamic]
Expand Down Expand Up @@ -78,6 +83,28 @@ lint.pydocstyle.convention = "google"
[tool.check-manifest]
ignore = [ ".pre-commit-config.yaml" ]

[tool.towncrier]
directory = "changes"
filename = "CHANGES.rst"
title_format = "{version} ({project_date})"
issue_format = "`#{issue} <https://github.com/pytest-dev/pytest-rerunfailures/issues/{issue}>`_"
underlines = [
"-",
"+",
"~",
]
wrap = true
# An empty ignore list turns on strict validation of news fragment file names.
ignore = [ ]
type = [
{ directory = "breaking", name = "Breaking Changes", showcontent = true },
{ directory = "removal", name = "Deprecations and Removals", showcontent = true },
{ directory = "feature", name = "Features", showcontent = true },
{ directory = "bugfix", name = "Bug Fixes", showcontent = true },
{ directory = "doc", name = "Documentation", showcontent = true },
{ directory = "misc", name = "Misc", showcontent = true },
]

[tool.mypy]
python_version = "3.10"
warn_return_any = true
Expand Down
Loading