From 04abfbe1c02b6de1ece49a3e2635215e243d327d Mon Sep 17 00:00:00 2001 From: Durable Workflow Date: Wed, 2 Sep 2026 22:56:05 +0000 Subject: [PATCH] Prepare Python SDK 2.0.1 --- CHANGELOG.md | 14 ++++++++++---- pyproject.toml | 6 +++--- scripts/check_pypi_project_surface.py | 2 +- scripts/check_release_metadata.py | 10 ++++++++-- tests/test_pypi_project_surface.py | 6 +++--- tests/test_release_metadata.py | 20 ++++++++++---------- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eae35c..9b91c67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.0.1] - 2026-09-02 + +### Fixed +- Cold replay now treats an intervening durable step as the authoritative + boundary for later signals and updates, even when they retain an older + condition sequence. Post-condition activities can therefore complete before + those receivers advance the workflow without rebinding them to a closed wait. + +## [2.0.0] - 2026-09-01 + The Python SDK `2.0.0` promotes the qualified release candidate to the stable 2.0 line. This Avro-only SDK release is supported with Server `2.0.0`; JSON remains HTTP transport and is not a workflow payload codec. @@ -91,10 +101,6 @@ Earlier SDK versions remain historical releases and are not alternate supported `NamespaceDescription.deleted`. ### Fixed -- Cold replay now treats an intervening durable step as the authoritative - boundary for later signals and updates, even when they retain an older - condition sequence. Post-condition activities can therefore complete before - those receivers advance the workflow without rebinding them to a closed wait. - The README and PyPI project description now require Server worker protocol `>=1.19,<2.0`. Package and API-reference release validation derive that interval from the shipped SDK protocol and reject semantic guidance drift. diff --git a/pyproject.toml b/pyproject.toml index 5b5eb83..2d85e64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "durable-workflow" -version = "2.0.0" +version = "2.0.1" description = "Python client and worker SDK for Durable Workflow Cloud and self-hosted Server" readme = "README.md" requires-python = ">=3.10" @@ -71,8 +71,8 @@ durable-workflow-replay-conformance = "durable_workflow.replay_conformance:main" durable-workflow-workflow-updates-conformance = "durable_workflow.workflow_updates_conformance:main" [tool.durable-workflow] -product-train = "2.0.0" -registry-version = "2.0.0" +product-train = "2.0.1" +registry-version = "2.0.1" supported-server-versions = "2.0.0" worker-protocol-version = "1.19" control-plane-version = "2" diff --git a/scripts/check_pypi_project_surface.py b/scripts/check_pypi_project_surface.py index b424fc8..22cc138 100644 --- a/scripts/check_pypi_project_surface.py +++ b/scripts/check_pypi_project_surface.py @@ -77,7 +77,7 @@ def release_channel(source: SourceMetadata) -> str: if re.fullmatch(r"2\.0\.0rc[1-9][0-9]*", source.registry_version): return "prerelease" - if source.registry_version == "2.0.0": + if re.fullmatch(r"2\.0\.(?:0|[1-9][0-9]*)", source.registry_version): return "stable" raise ProjectSurfaceError(f"unsupported PyPI release identity: {source.registry_version}") diff --git a/scripts/check_release_metadata.py b/scripts/check_release_metadata.py index 8a2735f..507874d 100644 --- a/scripts/check_release_metadata.py +++ b/scripts/check_release_metadata.py @@ -116,13 +116,19 @@ def load_source_metadata(source_ref: str) -> SourceMetadata: server_version = tool.get("supported-server-versions") worker_protocol_version = tool.get("worker-protocol-version") classifiers = project.get("classifiers") - if not isinstance(version, str) or not re.fullmatch(r"2\.0\.0(?:-rc\.[1-9][0-9]*)?", version): + if not isinstance(version, str) or not re.fullmatch( + r"2\.0\.(?:0-rc\.[1-9][0-9]*|0|[1-9][0-9]*)", + version, + ): raise ReleaseMetadataError("source version is not an exact supported Durable Workflow 2.0 release") if product_train != version: raise ReleaseMetadataError("product-train does not match project.version") if registry_version != version.replace("-rc.", "rc"): raise ReleaseMetadataError("registry-version is not the PEP 440 form of project.version") - if not isinstance(server_version, str) or not re.fullmatch(r"2\.0\.0(?:-rc\.[1-9][0-9]*)?", server_version): + if not isinstance(server_version, str) or not re.fullmatch( + r"2\.0\.(?:0-rc\.[1-9][0-9]*|0|[1-9][0-9]*)", + server_version, + ): raise ReleaseMetadataError("supported-server-versions must identify one exact qualified Server release") if not isinstance(worker_protocol_version, str): raise ReleaseMetadataError("worker-protocol-version must be a string") diff --git a/tests/test_pypi_project_surface.py b/tests/test_pypi_project_surface.py index 26afdbf..2b98fe9 100644 --- a/tests/test_pypi_project_surface.py +++ b/tests/test_pypi_project_surface.py @@ -20,8 +20,8 @@ def source_metadata(*, stable: bool = False) -> SourceMetadata: - version = "2.0.0" if stable else "2.0.0-rc.44" - registry_version = "2.0.0" if stable else "2.0.0rc44" + version = "2.0.1" if stable else "2.0.0-rc.44" + registry_version = "2.0.1" if stable else "2.0.0rc44" return SourceMetadata( commit="a" * 40, name="durable-workflow", @@ -305,7 +305,7 @@ def test_stable_project_root_mismatch_remains_release_blocking( "scripts.check_pypi_project_surface._request_json", lambda url: exact_version_payload(source) if url.endswith(f"/{source.registry_version}/json") else root, ) - monkeypatch.setattr("scripts.check_pypi_project_surface._pip_report", lambda *_args, **_kwargs: pip_report("2.0.0")) + monkeypatch.setattr("scripts.check_pypi_project_surface._pip_report", lambda *_args, **_kwargs: pip_report("2.0.1")) with pytest.raises(ProjectSurfaceError, match="stable project-root metadata did not converge.*field version"): main(["--source-ref", "release-source"]) diff --git a/tests/test_release_metadata.py b/tests/test_release_metadata.py index b5b0565..082b109 100644 --- a/tests/test_release_metadata.py +++ b/tests/test_release_metadata.py @@ -21,8 +21,8 @@ def source_metadata() -> SourceMetadata: return SourceMetadata( commit="a" * 40, name="durable-workflow", - version="2.0.0", - registry_version="2.0.0", + version="2.0.1", + registry_version="2.0.1", server_version="2.0.0", worker_protocol_version="1.19", summary="Python SDK for the Durable Workflow 2.0 platform", @@ -41,9 +41,9 @@ def test_worker_release_identity_matches_supported_server_and_protocol() -> None project = manifest["project"] release = manifest["tool"]["durable-workflow"] - assert project["version"] == "2.0.0" + assert project["version"] == "2.0.1" assert release["product-train"] == project["version"] - assert release["registry-version"] == "2.0.0" + assert release["registry-version"] == "2.0.1" assert release["supported-server-versions"] == "2.0.0" assert release["worker-protocol-version"] == PROTOCOL_VERSION == "1.19" assert release["durable-selection"] is True @@ -93,14 +93,14 @@ def test_release_metadata_loader_accepts_the_authorized_stable_identity( pyproject = b""" [project] name = "durable-workflow" -version = "2.0.0" +version = "2.0.1" description = "Python SDK for Durable Workflow 2.0" readme = "README.md" classifiers = ["Programming Language :: Python :: 3"] [tool.durable-workflow] -product-train = "2.0.0" -registry-version = "2.0.0" +product-train = "2.0.1" +registry-version = "2.0.1" supported-server-versions = "2.0.0" worker-protocol-version = "1.19" """ @@ -120,9 +120,9 @@ def git(*arguments: str) -> bytes: monkeypatch.setattr(check_release_metadata, "_git", git) - source = check_release_metadata.load_source_metadata("2.0.0") - assert source.version == "2.0.0" - assert source.registry_version == "2.0.0" + source = check_release_metadata.load_source_metadata("2.0.1") + assert source.version == "2.0.1" + assert source.registry_version == "2.0.1" def test_normal_project_page_is_retained_as_rendered_evidence(monkeypatch: pytest.MonkeyPatch) -> None: