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
7 changes: 3 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

The Python SDK advances to prerelease `2.0.0-rc.44`. PyPI displays the normalized
PEP 440 identity `2.0.0rc44`. This Avro-only SDK release is qualified with Server
`2.0.0-rc.68`; JSON remains HTTP transport and is no longer a workflow payload
codec.
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.
Earlier SDK versions remain historical releases and are not alternate supported
2.0 baselines; no prerelease compatibility shim is provided.

Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

A Python SDK for the [Durable Workflow server](https://github.com/durable-workflow/server). Speaks the server's language-neutral HTTP/JSON worker protocol — no PHP runtime required.

Status: **Release candidate** — this is the Python SDK release candidate in the
Durable Workflow 2.0 train. Core features include workflows, activities,
Status: **Stable 2.0**. Core features include workflows, activities,
schedules, signals, timers, child workflows, continue-as-new, side effects,
version markers, worker-applied accepted updates, replay verification, the
in-process `WorkflowEnvironment` test harness, and invocable activity carriers.
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ hide:

<div class="dw-hero__copy" markdown="1">

<p class="dw-eyebrow">First-party Python SDK · 2.0 prerelease</p>
<p class="dw-eyebrow">First-party Python SDK · 2.0 stable</p>

# Durable workflows in Python.

Expand Down Expand Up @@ -100,7 +100,7 @@ file containing an activity, workflow, worker, and client.
### 1. Start Server

Docker keeps this first run local. Resolve the Server image without copying a
prerelease sequence number into the page:
release version into the page:

```bash
{{ durable_workflow_server_image_resolver }}
Expand Down
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"

[project]
name = "durable-workflow"
version = "2.0.0-rc.44"
description = "Release candidate Python SDK for the Durable Workflow 2.0 train"
version = "2.0.0"
description = "Python SDK for the Durable Workflow 2.0 platform"
readme = "README.md"
requires-python = ">=3.10"
license = "MIT"
Expand Down Expand Up @@ -68,9 +68,9 @@ 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-rc.44"
registry-version = "2.0.0rc44"
supported-server-versions = "2.0.0-rc.68"
product-train = "2.0.0"
registry-version = "2.0.0"
supported-server-versions = "2.0.0"
worker-protocol-version = "1.19"
control-plane-version = "2"
durable-selection = true
Expand Down
18 changes: 8 additions & 10 deletions scripts/api_reference_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
RELEASE_EVIDENCE_SCHEMA = "durable-workflow.python-api-reference.release"
QUICKSTART_CONTRACT_SCHEMA = "durable-workflow.docs.v2.quickstart-execution-contract"
QUICKSTART_CONTRACT_URL = "https://durable-workflow.com/quickstart-execution-contract.json"
RELEASE_VERSION_PATTERN = r"[0-9]+\.[0-9]+\.[0-9]+(?:-(?:alpha|beta|rc)\.[0-9]+)?"
SUPPORTED_PRERELEASE_INSTALL_COMMAND = "curl -fsSL https://durable-workflow.com/install-sdk.sh | sh -s -- python"
SUPPORTED_SERVER_IMAGE_RESOLVER_COMMAND = rf'''export DW_SERVER_IMAGE="$(
curl -fsSL "${{DURABLE_WORKFLOW_QUICKSTART_CONTRACT_URL:-{QUICKSTART_CONTRACT_URL}}}" |
Expand All @@ -50,8 +51,8 @@
version = server.get("version")
image = server.get("image")
reference = server.get("reference")
if not isinstance(version, str) or re.fullmatch(r"[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)\.[0-9]+", version) is None:
raise SystemExit("The public quickstart contract has an invalid Server prerelease.")
if not isinstance(version, str) or re.fullmatch(r"{RELEASE_VERSION_PATTERN}", version) is None:
raise SystemExit("The public quickstart contract has an invalid Server release.")
if not isinstance(image, str) or reference != f"{{image}}:{{version}}":
raise SystemExit("The public quickstart contract has an invalid Server reference.")
print(reference)'
Expand Down Expand Up @@ -116,9 +117,6 @@ def load_release_identity(repo_root: Path) -> ReleaseIdentity:
raise ValueError("project.version and tool.durable-workflow.product-train must match")
if normalize_registry_version(identity.version) != identity.registry_version:
raise ValueError("registry-version must be the PEP 440 form of project.version")
if "-" not in identity.version:
raise ValueError("API-reference release identity must remain a prerelease before the 2.0 stable cutover")

runtime_protocol = declared_runtime_protocol_version(
(repo_root / "src" / "durable_workflow" / "client.py").read_text(encoding="utf-8")
)
Expand Down Expand Up @@ -160,11 +158,11 @@ def load_qualified_onboarding(payload: object) -> QualifiedOnboarding:
server_version = server.get("version")
server_image = server.get("image")
server_reference = server.get("reference")
prerelease = re.compile(r"[0-9]+\.[0-9]+\.[0-9]+-(?:alpha|beta|rc)\.[0-9]+")
if not isinstance(sdk_version, str) or prerelease.fullmatch(sdk_version) is None:
raise ValueError("Public quickstart contract has an invalid Python SDK prerelease")
if not isinstance(server_version, str) or prerelease.fullmatch(server_version) is None:
raise ValueError("Public quickstart contract has an invalid Server prerelease")
release = re.compile(RELEASE_VERSION_PATTERN)
if not isinstance(sdk_version, str) or release.fullmatch(sdk_version) is None:
raise ValueError("Public quickstart contract has an invalid Python SDK release")
if not isinstance(server_version, str) or release.fullmatch(server_version) is None:
raise ValueError("Public quickstart contract has an invalid Server release")
if not isinstance(server_image, str) or not server_image:
raise ValueError("Public quickstart contract has an invalid Server image")
if server_reference != f"{server_image}:{server_version}":
Expand Down
11 changes: 11 additions & 0 deletions tests/test_api_reference_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ def test_contract_change_alone_changes_the_qualified_sdk_server_pair() -> None:
assert changed.server_reference != current.server_reference


def test_stable_contract_selects_the_stable_sdk_server_pair() -> None:
stable = load_qualified_onboarding(quickstart_contract("2.0.0", "2.0.0"))

assert stable == QualifiedOnboarding(
sdk_version="2.0.0",
sdk_registry_version="2.0.0",
server_version="2.0.0",
server_reference="durableworkflow/server:2.0.0",
)


def test_contract_rejects_a_mismatched_server_reference() -> None:
contract = quickstart_contract("2.0.0-rc.101", "2.0.0-rc.201")
artifacts = contract["artifacts"]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_release_docs_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

REPO_ROOT = Path(__file__).resolve().parents[1]
VALIDATOR = REPO_ROOT / "scripts" / "ci" / "validate-release-docs-source.py"
VERSION = "2.0.0-rc.44"
VERSION = "2.0.0"


def git(repo: Path, *arguments: str) -> str:
Expand Down
14 changes: 7 additions & 7 deletions tests/test_release_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ def source_metadata() -> SourceMetadata:
return SourceMetadata(
commit="a" * 40,
name="durable-workflow",
version="2.0.0-rc.44",
registry_version="2.0.0rc44",
server_version="2.0.0-rc.68",
version="2.0.0",
registry_version="2.0.0",
server_version="2.0.0",
worker_protocol_version="1.19",
summary="Release candidate Python SDK for the Durable Workflow 2.0 train",
summary="Python SDK for the Durable Workflow 2.0 platform",
classifiers=("Programming Language :: Python :: 3",),
readme=(
"# Durable Workflow\n\n"
Expand All @@ -45,10 +45,10 @@ 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-rc.44"
assert project["version"] == "2.0.0"
assert release["product-train"] == project["version"]
assert release["registry-version"] == "2.0.0rc44"
assert release["supported-server-versions"] == "2.0.0-rc.68"
assert release["registry-version"] == "2.0.0"
assert release["supported-server-versions"] == "2.0.0"
assert release["worker-protocol-version"] == PROTOCOL_VERSION == "1.19"
assert release["durable-selection"] is True
assert release["durable-selection-minimum-worker-protocol-version"] == "1.19"
Expand Down
Loading