From 99fbeb0283eae6d380464b66d7a763529e95e838 Mon Sep 17 00:00:00 2001 From: ckunki Date: Thu, 19 Mar 2026 09:04:29 +0100 Subject: [PATCH 1/6] #740: Added nox session `release:update` --- doc/changes/unreleased.md | 4 ++ exasol/toolbox/nox/_release.py | 34 ++++++++++----- exasol/toolbox/util/release/changelog.py | 55 ++++++++++++++++++------ test/unit/util/release/changelog_test.py | 20 ++++----- 4 files changed, 78 insertions(+), 35 deletions(-) diff --git a/doc/changes/unreleased.md b/doc/changes/unreleased.md index a4f3ffcf8..ff1875599 100644 --- a/doc/changes/unreleased.md +++ b/doc/changes/unreleased.md @@ -2,6 +2,10 @@ ## Summary +## Features + +* #740: Added nox session `release:update` + ## Security Issues * #748: Updated dependency to `black` diff --git a/exasol/toolbox/nox/_release.py b/exasol/toolbox/nox/_release.py index e93cf41a6..db5756ffb 100644 --- a/exasol/toolbox/nox/_release.py +++ b/exasol/toolbox/nox/_release.py @@ -33,7 +33,7 @@ def _create_parser() -> argparse.ArgumentParser: "-t", "--type", type=ReleaseTypes, - help="specifies which type of upgrade is to be performed", + help="Specifies which part of the version number to increase.", required=True, default=argparse.SUPPRESS, ) @@ -41,19 +41,19 @@ def _create_parser() -> argparse.ArgumentParser: "--no-add", default=False, action="store_true", - help="Neither add nor commit the changes", + help="Neither add nor commit the changes.", ) parser.add_argument( "--no-branch", default=False, action="store_true", - help="Do not create a branch to commit the changes on", + help="Do not create a branch to commit the changes on.", ) parser.add_argument( "--no-pr", default=False, action="store_true", - help="Do not create a pull request for the changes", + help="Do not create a pull request for the changes.", ) return parser @@ -64,6 +64,14 @@ def _update_project_version(session: Session, version: Version) -> Version: return version +def _get_changelogs(version: Version) -> Changelogs: + return Changelogs( + changes_path=PROJECT_CONFIG.documentation_path / "changes", + root_path=PROJECT_CONFIG.root_path, + version=version, + ) + + def _add_files_to_index(session: Session, files: list[Path]) -> None: for file in files: session.run("git", "add", f"{file}") @@ -124,13 +132,11 @@ def prepare_release(session: Session) -> None: _ = _update_project_version(session, new_version) - changelogs = Changelogs( - changes_path=PROJECT_CONFIG.documentation_path / "changes", - root_path=PROJECT_CONFIG.root_path, - version=new_version, + changed_files = ( + _get_changelogs(version=new_version) + .prepare_release() + .get_changed_files() ) - changelogs.update_changelogs_for_release() - changed_files = changelogs.get_changed_files() pm = NoxTasks.plugin_manager(PROJECT_CONFIG) pm.hook.prepare_release_update_version( @@ -163,8 +169,14 @@ def prepare_release(session: Session) -> None: '""', ) +@nox.session(name="release:update", python=False) +def release_update(session: Session) -> None: + """Update the changelog of the release already prepared.""" + version = Version.from_poetry() + _get_changelogs(version).update_latest() + @nox.session(name="release:trigger", python=False) def trigger_release(session: Session) -> None: - """trigger an automatic project release""" + """Trigger an automatic project release.""" print(f"new version: {_trigger_release(PROJECT_CONFIG)}") diff --git a/exasol/toolbox/util/release/changelog.py b/exasol/toolbox/util/release/changelog.py index 682c432cf..706a83b9e 100644 --- a/exasol/toolbox/util/release/changelog.py +++ b/exasol/toolbox/util/release/changelog.py @@ -1,5 +1,6 @@ from __future__ import annotations +import re from collections import OrderedDict from datetime import datetime from inspect import cleandoc @@ -19,6 +20,8 @@ ## Summary """) + "\n" +DEPENDENCY_UPDATES = "## Dependency Updates\n" + class Changelogs: def __init__(self, changes_path: Path, root_path: Path, version: Version) -> None: @@ -41,6 +44,7 @@ def _create_new_unreleased(self): """ Write a new unreleased changelog file. """ + self.unreleased_md.write_text(UNRELEASED_INITIAL_CONTENT) def _create_versioned_changelog(self, unreleased_content: str) -> None: @@ -50,30 +54,30 @@ def _create_versioned_changelog(self, unreleased_content: str) -> None: Args: unreleased_content: the content of the (not yet versioned) changes """ - header = f"# {self.version} - {datetime.today().strftime('%Y-%m-%d')}" - - dependency_content = "" - if dependency_changes := self._describe_dependency_changes(): - dependency_content = f"## Dependency Updates\n{dependency_changes}" - template = cleandoc(f"{header}\n\n{unreleased_content}\n{dependency_content}") + header = f"# {self.version} - {datetime.today().strftime('%Y-%m-%d')}" + dependency_changes = self._report_dependency_changes() + template = cleandoc(f"{header}\n\n{unreleased_content}\n{dependency_changes}") self.versioned_changelog_md.write_text(template + "\n") def _extract_unreleased_notes(self) -> str: """ Extract (not yet versioned) changes from `unreleased.md`. """ + with self.unreleased_md.open(mode="r", encoding="utf-8") as f: # skip header when reading in file, as contains # Unreleased lines = f.readlines()[1:] unreleased_content = cleandoc("".join(lines)) return unreleased_content + "\n" - def _describe_dependency_changes(self) -> str: + def _dependency_changes(self) -> str: """ - Describe the dependency changes between the latest tag and the current version - for use in the versioned changes file. + Return the dependency changes between the latest tag and the + current version for use in the versioned changes file in markdown + format. If there are no changes, return an empty string. """ + try: previous_dependencies_in_groups = get_dependencies_from_latest_tag( root_path=self.root_path @@ -112,6 +116,7 @@ def _sort_groups(groups: set[str]) -> list[str]: - `main` group should always be first - remaining groups are sorted alphabetically """ + main = "main" if main not in groups: # sorted converts set to list @@ -120,10 +125,10 @@ def _sort_groups(groups: set[str]) -> list[str]: # sorted converts set to list return [main] + sorted(remaining_groups) - def _update_changelog_table_of_contents(self) -> None: + def _update_table_of_contents(self) -> None: """ - Read in existing `changelog.md` and append to appropriate sections - before writing out to again. + Read the existing `changelog.md`, append the latest changes file + to the relevant sections, and write the updated changelog.md again. """ updated_content = [] with self.changelog_md.open(mode="r", encoding="utf-8") as f: @@ -142,7 +147,28 @@ def _update_changelog_table_of_contents(self) -> None: def get_changed_files(self) -> list[Path]: return [self.unreleased_md, self.versioned_changelog_md, self.changelog_md] - def update_changelogs_for_release(self) -> None: + def _report_dependency_changes(self) -> str: + if changes := self._dependency_changes(): + return f"{DEPENDENCY_UPDATES}{changes}" + return "" + + def update_latest(self) -> Changelogs: + """ + Update the updated dependencies in the latest versioned changelog. + """ + + dependency_changes = self._report_dependency_changes() + old_content = self.versioned_changelog_md.read_text() + new_content = re.sub( + r"^{DEPENDENCY_UPDATES}.*", + dependency_changes + "\n", + old_content, + flags=re.DOTALL | re.MULTILINE + ) + self.versioned_changelog_md.write_text(new_content) + return self + + def prepare_release(self) -> Changelogs: """ Rotates the changelogs as is needed for a release. @@ -157,4 +183,5 @@ def update_changelogs_for_release(self) -> None: # update other changelogs now that versioned changelog exists self._create_new_unreleased() - self._update_changelog_table_of_contents() + self._update_table_of_contents() + return self diff --git a/test/unit/util/release/changelog_test.py b/test/unit/util/release/changelog_test.py index 18d26854b..821b94bf3 100644 --- a/test/unit/util/release/changelog_test.py +++ b/test/unit/util/release/changelog_test.py @@ -141,8 +141,8 @@ def test_extract_unreleased_notes(changelogs, unreleased_md): assert actual == expected @staticmethod - def test_describe_dependency_changes(changelogs, mock_dependencies): - result = changelogs._describe_dependency_changes() + def test_dependency_changes(changelogs, mock_dependencies): + result = changelogs._dependency_changes() assert result == ( "\n" "### `main`\n\n" @@ -153,10 +153,10 @@ def test_describe_dependency_changes(changelogs, mock_dependencies): ) @staticmethod - def test_describe_dependency_changes_without_latest_version( + def test_dependency_changes_without_latest_version( changelogs, mock_new_dependencies ): - result = changelogs._describe_dependency_changes() + result = changelogs._dependency_changes() assert result == ( "\n" "### `main`\n\n" @@ -183,16 +183,16 @@ def test_sort_groups(changelogs, groups, expected): assert result == expected @staticmethod - def test_update_changelog_table_of_contents(changelogs, changes_md): - changelogs._update_changelog_table_of_contents() + def test_update_table_of_contents(changelogs, changes_md): + changelogs._update_table_of_contents() assert changelogs.changelog_md.read_text() == SampleContent.altered_changes @staticmethod - def test_update_changelogs_for_release( + def test_prepare_release( changelogs, mock_dependencies, unreleased_md, changes_md ): - changelogs.update_changelogs_for_release() + changelogs.prepare_release() # changes.md assert changelogs.changelog_md.read_text() == SampleContent.altered_changes @@ -229,10 +229,10 @@ def test_update_changelogs_for_release( ) @staticmethod - def test_update_changelogs_for_release_with_no_dependencies( + def test_prepare_release_with_no_dependencies( changelogs, mock_no_dependencies, unreleased_md, changes_md ): - changelogs.update_changelogs_for_release() + changelogs.prepare_release() # changes.md assert changelogs.changelog_md.read_text() == SampleContent.altered_changes From 751a3c711c79dc07e5c4a2e2a48f7e0a934ba411 Mon Sep 17 00:00:00 2001 From: ckunki Date: Thu, 19 Mar 2026 09:39:50 +0100 Subject: [PATCH 2/6] Updated user guide --- .../features/creating_a_release.rst | 34 ++++++++++++++----- doc/user_guide/features/index.rst | 10 +++--- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/doc/user_guide/features/creating_a_release.rst b/doc/user_guide/features/creating_a_release.rst index bae6464f3..7da99d1ea 100644 --- a/doc/user_guide/features/creating_a_release.rst +++ b/doc/user_guide/features/creating_a_release.rst @@ -10,15 +10,18 @@ Preparing a release nox -s release:prepare -- --type {major,minor,patch} - The ``release:prepare`` nox session affects the ``pyproject.toml``, ``version.py``, and files in the ``doc/changes`` directory: + The ``release:prepare`` nox session affects the ``pyproject.toml``, + ``version.py``, and files in the ``doc/changes`` directory: * Creates & switches to a release branch (can be skipped with ``--no-branch``) * Updates the version in the ``pyproject.toml`` and ``version.py`` - * Moves the content of unreleased changes file ``unreleased.md`` to a versioned changes file ``changes_.md`` + * Moves the content of unreleased changes file ``unreleased.md`` to a + versioned changes file ``changes_.md`` * Adds a description of dependency changes to the versioned changes file: * Only direct dependencies are described, no transitive dependencies - * Changes are detected by comparing the current content of file ``poetry.lock`` to the latest Git tag. + * Changes are detected by comparing the current content of file + ``poetry.lock`` to the latest Git tag. * Updates the ``changelog.md`` list with the newly created versioned changes file * Commits the changes (can be skipped with ``--no-add``) * Pushes the changes and creates a PR (can be skipped with ``--no-pr``) @@ -34,17 +37,29 @@ Preparing a release Use the nox session ``release:trigger`` to: * Switch to & pull the changes from the default branch - * Verify that the version to be released does not already have a git tag or GitHub release - * Create a new tag & push it to the default branch, which will trigger the GitHub workflow ``cd.yml`` + * Verify that the version to be released does not already have a git tag + or GitHub release + * Create a new tag & push it to the default branch, which will trigger the + GitHub workflow ``cd.yml`` - Additionally, if enabled in your project config, the task will create an additional tag with pattern ``v``. - This is especially useful if other projects use Github actions of your project, for example: + Additionally, if enabled in your project config, the task will create an + additional tag with pattern ``v``. This is especially + useful if other projects use Github actions of your project, for example: .. code-block:: yaml uses: exasol/your_project/.github/actions/your_action@v1 - Your ``PROJECT_CONFIG`` needs to have the flag ``create_major_version_tags=True``. + Your ``PROJECT_CONFIG`` needs to have the flag + ``create_major_version_tags=True``. + +Updating Depedencies After Having Prepared the Release +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +If you already ran nox session ``release:prepare`` but afterwards still some +dependencies needed to be updated you can update the dependency changes in the +changelog by running nox session ``release:update``. + What to do if the release failed? +++++++++++++++++++++++++++++++++ @@ -75,6 +90,7 @@ One of the release steps failed (Partial Release) .. note:: Example - **Scenario**: Publishing of the release on GitHub was successfully but during the PyPi release, the upload step was interrupted. + **Scenario**: Publishing of the release on GitHub was successfully but + during the PyPi release, the upload step was interrupted. **Solution**: Manually push the package to PyPi diff --git a/doc/user_guide/features/index.rst b/doc/user_guide/features/index.rst index bc0e7555b..bd98ae29e 100644 --- a/doc/user_guide/features/index.rst +++ b/doc/user_guide/features/index.rst @@ -6,13 +6,13 @@ Features .. toctree:: :maxdepth: 2 - metrics/collecting_metrics - creating_a_release - documentation/index - git_hooks/index - github_workflows/index formatting_code/index + github_workflows/index + documentation/index + creating_a_release managing_dependencies + git_hooks/index + metrics/collecting_metrics Uniform Project Layout ---------------------- From 632470cabff3589bebb5a09171af9b4be65ca9e8 Mon Sep 17 00:00:00 2001 From: ckunki Date: Thu, 19 Mar 2026 09:52:31 +0100 Subject: [PATCH 3/6] Fixed typo --- doc/user_guide/features/creating_a_release.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/user_guide/features/creating_a_release.rst b/doc/user_guide/features/creating_a_release.rst index 7da99d1ea..ea935c7a6 100644 --- a/doc/user_guide/features/creating_a_release.rst +++ b/doc/user_guide/features/creating_a_release.rst @@ -1,7 +1,7 @@ -Creating a release +Creating a Release ================== -Preparing a release +Preparing a Release +++++++++++++++++++ #. Prepare the project for a new release @@ -53,18 +53,18 @@ Preparing a release Your ``PROJECT_CONFIG`` needs to have the flag ``create_major_version_tags=True``. -Updating Depedencies After Having Prepared the Release -++++++++++++++++++++++++++++++++++++++++++++++++++++++ +Updating Dependencies After Having Prepared the Release ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ If you already ran nox session ``release:prepare`` but afterwards still some dependencies needed to be updated you can update the dependency changes in the changelog by running nox session ``release:update``. -What to do if the release failed? +What to do if the Release Failed? +++++++++++++++++++++++++++++++++ -The release failed during pre-release checks +The Release Failed During Pre-Release Checks -------------------------------------------- #. Delete the local tag @@ -83,7 +83,7 @@ The release failed during pre-release checks #. Start the release process from the beginning -One of the release steps failed (Partial Release) +One of the Release Steps Failed (Partial Release) ------------------------------------------------- #. Check the GitHub action/workflow to see which steps failed #. Finish or redo the failed release steps manually From 02ebbd1474c7af325d926b670a18fea15fac0fe6 Mon Sep 17 00:00:00 2001 From: ckunki Date: Thu, 19 Mar 2026 10:51:22 +0100 Subject: [PATCH 4/6] Added tests --- exasol/toolbox/nox/_release.py | 5 +- exasol/toolbox/util/release/changelog.py | 12 +- test/unit/util/release/changelog_test.py | 144 +++++++++++------------ 3 files changed, 73 insertions(+), 88 deletions(-) diff --git a/exasol/toolbox/nox/_release.py b/exasol/toolbox/nox/_release.py index db5756ffb..27d25647e 100644 --- a/exasol/toolbox/nox/_release.py +++ b/exasol/toolbox/nox/_release.py @@ -133,9 +133,7 @@ def prepare_release(session: Session) -> None: _ = _update_project_version(session, new_version) changed_files = ( - _get_changelogs(version=new_version) - .prepare_release() - .get_changed_files() + _get_changelogs(version=new_version).prepare_release().get_changed_files() ) pm = NoxTasks.plugin_manager(PROJECT_CONFIG) @@ -169,6 +167,7 @@ def prepare_release(session: Session) -> None: '""', ) + @nox.session(name="release:update", python=False) def release_update(session: Session) -> None: """Update the changelog of the release already prepared.""" diff --git a/exasol/toolbox/util/release/changelog.py b/exasol/toolbox/util/release/changelog.py index 706a83b9e..d82c0d2cc 100644 --- a/exasol/toolbox/util/release/changelog.py +++ b/exasol/toolbox/util/release/changelog.py @@ -157,15 +157,11 @@ def update_latest(self) -> Changelogs: Update the updated dependencies in the latest versioned changelog. """ + content = self.versioned_changelog_md.read_text() + flags = re.DOTALL | re.MULTILINE + stripped = re.sub(r"^{DEPENDENCY_UPDATES}.*", "", content, flags=flags) dependency_changes = self._report_dependency_changes() - old_content = self.versioned_changelog_md.read_text() - new_content = re.sub( - r"^{DEPENDENCY_UPDATES}.*", - dependency_changes + "\n", - old_content, - flags=re.DOTALL | re.MULTILINE - ) - self.versioned_changelog_md.write_text(new_content) + self.versioned_changelog_md.write_text(f"{stripped}\n{dependency_changes}") return self def prepare_release(self) -> Changelogs: diff --git a/test/unit/util/release/changelog_test.py b/test/unit/util/release/changelog_test.py index 821b94bf3..f2c5c5de1 100644 --- a/test/unit/util/release/changelog_test.py +++ b/test/unit/util/release/changelog_test.py @@ -1,9 +1,10 @@ from datetime import datetime from inspect import cleandoc -from unittest import mock +from unittest.mock import Mock import pytest +import exasol.toolbox.util.release.changelog as impl from exasol.toolbox.util.dependencies.shared_models import LatestTagNotFoundError from exasol.toolbox.util.release.changelog import ( UNRELEASED_INITIAL_CONTENT, @@ -57,6 +58,37 @@ class SampleContent: """) +def expected_changes_file_content(with_dependencies: bool = False): + header = cleandoc(f""" + # 1.0.0 - {datetime.today().strftime('%Y-%m-%d')} + + ## Summary + + Summary of changes. + + ## Added + * Added Awesome feature + + ## Changed + * Some behaviour + + ## Fixed + * Fixed nasty bug + """) + dependencies = cleandoc(f""" + ## Dependency Updates + + ### `main` + + * Updated dependency `package1:0.0.1` to `0.1.0` + + ### `dev` + + * Added dependency `package2:0.2.0` + """) + return f"{header}\n\n{dependencies}\n" if with_dependencies else f"{header}\n" + + @pytest.fixture(scope="function") def changes_md(changelogs): changelogs.changelog_md.write_text(SampleContent.changes) @@ -69,36 +101,28 @@ def unreleased_md(changelogs): ) -@pytest.fixture(scope="function") -def mock_dependencies(dependencies, previous_dependencies): - with mock.patch.multiple( - "exasol.toolbox.util.release.changelog", - get_dependencies_from_latest_tag=lambda root_path: previous_dependencies, - get_dependencies=lambda working_directory: dependencies, +def mock_changelog(monkeypatch, old_dependencies, new_dependencies): + for func, value in ( + ("get_dependencies_from_latest_tag", old_dependencies), + ("get_dependencies", new_dependencies), ): - yield + mock = value if isinstance(value, Mock) else Mock(return_value=value) + monkeypatch.setattr(impl, func, mock) @pytest.fixture(scope="function") -def mock_new_dependencies(dependencies): - mock_latest_tag_not_found_error = mock.Mock(side_effect=LatestTagNotFoundError) +def mock_dependencies(monkeypatch, previous_dependencies, dependencies): + mock_changelog(monkeypatch, previous_dependencies, dependencies) - with mock.patch.multiple( - "exasol.toolbox.util.release.changelog", - get_dependencies_from_latest_tag=mock_latest_tag_not_found_error, - get_dependencies=lambda working_directory: dependencies, - ): - yield + +@pytest.fixture(scope="function") +def mock_new_dependencies(monkeypatch, dependencies): + mock_changelog(monkeypatch, Mock(side_effect=LatestTagNotFoundError), dependencies) @pytest.fixture(scope="function") -def mock_no_dependencies(): - with mock.patch.multiple( - "exasol.toolbox.util.release.changelog", - get_dependencies_from_latest_tag=lambda root_path: {}, - get_dependencies=lambda working_directory: {}, - ): - yield +def mock_no_dependencies(monkeypatch): + mock_changelog(monkeypatch, {}, {}) @pytest.fixture(scope="function") @@ -189,44 +213,28 @@ def test_update_table_of_contents(changelogs, changes_md): assert changelogs.changelog_md.read_text() == SampleContent.altered_changes @staticmethod - def test_prepare_release( - changelogs, mock_dependencies, unreleased_md, changes_md - ): + def test_prepare_release(changelogs, mock_dependencies, unreleased_md, changes_md): changelogs.prepare_release() - - # changes.md assert changelogs.changelog_md.read_text() == SampleContent.altered_changes - # unreleased.md assert changelogs.unreleased_md.read_text() == UNRELEASED_INITIAL_CONTENT - # versioned.md - saved_text = changelogs.versioned_changelog_md.read_text() - assert ( - saved_text == cleandoc(f"""# 1.0.0 - {datetime.today().strftime('%Y-%m-%d')} - - ## Summary - - Summary of changes. - - ## Added - * Added Awesome feature - - ## Changed - * Some behaviour - - ## Fixed - * Fixed nasty bug - - ## Dependency Updates - - ### `main` - - * Updated dependency `package1:0.0.1` to `0.1.0` + versioned = changelogs.versioned_changelog_md.read_text() + assert versioned == expected_changes_file_content(with_dependencies=True) - ### `dev` - - * Added dependency `package2:0.2.0` - """) + "\n" - ) + @staticmethod + def test_update_latest( + monkeypatch, + mock_no_dependencies, + previous_dependencies, + dependencies, + changelogs, + unreleased_md, + changes_md, + ): + changelogs.prepare_release() + mock_changelog(monkeypatch, previous_dependencies, dependencies) + changelogs.update_latest() + versioned = changelogs.versioned_changelog_md.read_text() + assert versioned == expected_changes_file_content(with_dependencies=True) @staticmethod def test_prepare_release_with_no_dependencies( @@ -234,25 +242,7 @@ def test_prepare_release_with_no_dependencies( ): changelogs.prepare_release() - # changes.md assert changelogs.changelog_md.read_text() == SampleContent.altered_changes - # unreleased.md assert changelogs.unreleased_md.read_text() == UNRELEASED_INITIAL_CONTENT - # versioned.md - saved_text = changelogs.versioned_changelog_md.read_text() - assert saved_text == cleandoc(f""" - # 1.0.0 - {datetime.today().strftime('%Y-%m-%d')} - - ## Summary - - Summary of changes. - - ## Added - * Added Awesome feature - - ## Changed - * Some behaviour - - ## Fixed - * Fixed nasty bug - """) + "\n" + versioned = changelogs.versioned_changelog_md.read_text() + assert versioned == expected_changes_file_content() From b8bd1da65eb16c6e8802d30f413af0aa7daf5113 Mon Sep 17 00:00:00 2001 From: Christoph Kuhnke Date: Thu, 19 Mar 2026 13:09:43 +0100 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Mikhail Beck --- doc/user_guide/features/creating_a_release.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user_guide/features/creating_a_release.rst b/doc/user_guide/features/creating_a_release.rst index ea935c7a6..6a84ad8c6 100644 --- a/doc/user_guide/features/creating_a_release.rst +++ b/doc/user_guide/features/creating_a_release.rst @@ -90,7 +90,7 @@ One of the Release Steps Failed (Partial Release) .. note:: Example - **Scenario**: Publishing of the release on GitHub was successfully but + **Scenario**: Publishing of the release on GitHub was successful but during the PyPi release, the upload step was interrupted. **Solution**: Manually push the package to PyPi From c5ade14eb27b9d84a7a5fde9a7169652abbeae02 Mon Sep 17 00:00:00 2001 From: ckunki Date: Thu, 19 Mar 2026 13:10:01 +0100 Subject: [PATCH 6/6] Applied review suggestion rephrasing the paragraph in the user guide. --- doc/user_guide/features/creating_a_release.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/user_guide/features/creating_a_release.rst b/doc/user_guide/features/creating_a_release.rst index 6a84ad8c6..a55a2a7a5 100644 --- a/doc/user_guide/features/creating_a_release.rst +++ b/doc/user_guide/features/creating_a_release.rst @@ -56,9 +56,9 @@ Preparing a Release Updating Dependencies After Having Prepared the Release +++++++++++++++++++++++++++++++++++++++++++++++++++++++ -If you already ran nox session ``release:prepare`` but afterwards still some -dependencies needed to be updated you can update the dependency changes in the -changelog by running nox session ``release:update``. +If you need to update some more dependencies after running the nox session +``release:prepare`` you can update them in the changelog by running the nox +session ``release:update``. What to do if the Release Failed?