From 79b6e68bf187d2ac9c485ee7311e75a8159fb6ef Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Thu, 21 May 2026 14:49:15 -0600 Subject: [PATCH 1/5] Fix test install --- eng/templates/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 0b9b393..19265d9 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -65,8 +65,14 @@ jobs: # PRs to main and main itself; this step is defense-in-depth to ensure # the artifacts we're about to ship are at least importable and pass # the pure-Python unit tests. + # + # `requirements.txt` brings in the test-time dependencies (opentelemetry, + # grpcio, etc.) that the test modules import. We install it before the + # built wheels so the wheels (which are what we're actually validating) + # take precedence over any editable/source install of the same package. - script: | set -e + python -m pip install -r requirements.txt python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask/*.whl python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged/*.whl displayName: "Install built wheels" From 9d7d4afc34ec82b486c992c40438857e4160a60d Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Thu, 21 May 2026 15:52:08 -0600 Subject: [PATCH 2/5] Fix durabletask crash, gate pipelines on environment --- eng/ci/release.yml | 2 ++ eng/templates/build.yml | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/eng/ci/release.yml b/eng/ci/release.yml index 0bd8a52..7b58c7f 100644 --- a/eng/ci/release.yml +++ b/eng/ci/release.yml @@ -27,6 +27,7 @@ extends: templateContext: type: releaseJob isProduction: true + environment: durabletask-pypi-prod inputs: - input: pipelineArtifact pipeline: DurableTaskPythonBuildPipeline @@ -63,6 +64,7 @@ extends: templateContext: type: releaseJob isProduction: true + environment: durabletask-pypi-prod inputs: - input: pipelineArtifact pipeline: DurableTaskPythonBuildPipeline diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 19265d9..5c1eb50 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -81,6 +81,11 @@ jobs: displayName: "pytest: durabletask (unit tests, no emulators)" workingDirectory: tests/durabletask - - script: pytest -m "not dts" --verbose + - script: pytest -m "not dts" --ignore=test_dts_activity_sequence.py --verbose displayName: "pytest: durabletask-azuremanaged (unit tests, no emulators)" workingDirectory: tests/durabletask-azuremanaged + # NOTE: `test_dts_activity_sequence.py` is `--ignore`d because it calls + # `exit()` at module load time when TASKHUB isn't set, which crashes + # pytest collection before its `pytest.mark.dts` marker can be applied. + # The other `test_dts_*.py` files handle missing env vars more + # gracefully and are filtered out by `-m "not dts"` as intended. From 8280a2c2f1019741842a04c1870376d2a90780b7 Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Thu, 21 May 2026 16:02:23 -0600 Subject: [PATCH 3/5] Cut back azuremanged tests again --- eng/templates/build.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 5c1eb50..12e9699 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -81,11 +81,15 @@ jobs: displayName: "pytest: durabletask (unit tests, no emulators)" workingDirectory: tests/durabletask - - script: pytest -m "not dts" --ignore=test_dts_activity_sequence.py --verbose - displayName: "pytest: durabletask-azuremanaged (unit tests, no emulators)" - workingDirectory: tests/durabletask-azuremanaged - # NOTE: `test_dts_activity_sequence.py` is `--ignore`d because it calls - # `exit()` at module load time when TASKHUB isn't set, which crashes - # pytest collection before its `pytest.mark.dts` marker can be applied. - # The other `test_dts_*.py` files handle missing env vars more - # gracefully and are filtered out by `-m "not dts"` as intended. + # `tests/durabletask-azuremanaged/` is intentionally NOT exercised here. + # Every test in that directory requires the Durable Task Scheduler + # emulator (a Docker container) which isn't provisioned in the 1ES + # network-isolated pool. The full azuremanaged test suite gates merges + # via `.github/workflows/durabletask-azuremanaged.yml` on every PR to + # `main` and `release/*`, so artifacts that reach this build have + # already passed those tests. Instead, we run a smoke import below to + # confirm the built wheel is loadable. + - script: | + set -e + python -c "import durabletask.azuremanaged; from durabletask.azuremanaged.client import DurableTaskSchedulerClient; from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker; print('durabletask.azuremanaged smoke import OK')" + displayName: "smoke import: durabletask-azuremanaged" From 9729fd659d76831a2c59231d018e99fcb064c920 Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Thu, 21 May 2026 16:12:42 -0600 Subject: [PATCH 4/5] Final azuremanaged test fix --- eng/templates/build.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 12e9699..97358fa 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -81,15 +81,10 @@ jobs: displayName: "pytest: durabletask (unit tests, no emulators)" workingDirectory: tests/durabletask - # `tests/durabletask-azuremanaged/` is intentionally NOT exercised here. - # Every test in that directory requires the Durable Task Scheduler - # emulator (a Docker container) which isn't provisioned in the 1ES - # network-isolated pool. The full azuremanaged test suite gates merges - # via `.github/workflows/durabletask-azuremanaged.yml` on every PR to - # `main` and `release/*`, so artifacts that reach this build have - # already passed those tests. Instead, we run a smoke import below to - # confirm the built wheel is loadable. + # `tests/durabletask-azuremanaged/` is NOT exercised here. + # Those tests require the Durable Task Scheduler emulator which is + # not available in the network-isolated pools. - script: | set -e - python -c "import durabletask.azuremanaged; from durabletask.azuremanaged.client import DurableTaskSchedulerClient; from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker; print('durabletask.azuremanaged smoke import OK')" + python -P -c "import durabletask.azuremanaged; from durabletask.azuremanaged.client import DurableTaskSchedulerClient; from durabletask.azuremanaged.worker import DurableTaskSchedulerWorker; print('durabletask.azuremanaged smoke import OK')" displayName: "smoke import: durabletask-azuremanaged" From 8e311b04f8d4d489bd671ba1b6b32e4a860f575e Mon Sep 17 00:00:00 2001 From: Andy Staples Date: Thu, 21 May 2026 16:34:06 -0600 Subject: [PATCH 5/5] Install with optionals to validate wheel --- eng/templates/build.yml | 50 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/eng/templates/build.yml b/eng/templates/build.yml index 97358fa..498ba94 100644 --- a/eng/templates/build.yml +++ b/eng/templates/build.yml @@ -25,10 +25,14 @@ jobs: inputs: artifactFeeds: "internal/PythonSDK_Internal_PublicPackages" - # Install build + lint + test tooling + # Install build + lint + test tooling. Note: we deliberately do NOT + # install the SDK's runtime dependencies (grpcio, protobuf, etc.) here. + # Those are pulled in later via the built wheels' declared metadata so + # that a wheel which accidentally drops a declared dependency surfaces + # the missing dep instead of being silently masked. - script: | python -m pip install --upgrade pip - python -m pip install build flake8 pytest pytest-asyncio aiohttp + python -m pip install build flake8 pytest pytest-asyncio displayName: "Install build tooling" # Lint core SDK @@ -57,24 +61,36 @@ jobs: ls -la $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged displayName: "List build outputs" - # Install the built wheels and run unit tests against them. We exclude - # tests marked `dts` (require the Durable Task Scheduler emulator) and - # `azurite` (require the Azurite blob emulator) since those external - # services aren't provisioned in this network-isolated pool. The full - # matrix (including emulator-backed tests) runs in GitHub Actions on - # PRs to main and main itself; this step is defense-in-depth to ensure - # the artifacts we're about to ship are at least importable and pass - # the pure-Python unit tests. + # Install the built wheels with all declared optional extras and let + # pip resolve their runtime dependencies (grpcio, protobuf, packaging, + # azure-identity, azure-storage-blob, opentelemetry-*, etc.). This is + # intentional: if a wheel ever accidentally drops a declared + # dependency, this step will surface the missing dependency at install + # or test time instead of being masked by a preinstalled + # requirements.txt. Test-only tools (pytest, pytest-asyncio) are + # already installed in the "Install build tooling" step above. # - # `requirements.txt` brings in the test-time dependencies (opentelemetry, - # grpcio, etc.) that the test modules import. We install it before the - # built wheels so the wheels (which are what we're actually validating) - # take precedence over any editable/source install of the same package. + # >>> MAINTENANCE NOTE <<< + # When a new optional extra is added to either package's + # `pyproject.toml` under `[project.optional-dependencies]`, append it + # to the extras list below (e.g., add `,my-new-extra` inside the + # brackets). This keeps the smoke tests and dependency-resolution + # check exercising every shipping configuration. + # + # We exclude tests marked `dts` (require the Durable Task Scheduler + # emulator) and `azurite` (require the Azurite blob emulator) since + # those external services aren't provisioned in this network-isolated + # pool. The full matrix (including emulator-backed tests) runs in + # GitHub Actions on PRs to main and main itself. - script: | set -e - python -m pip install -r requirements.txt - python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask/*.whl - python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged/*.whl + # Resolve the wheel filename explicitly because bash treats + # `*.whl[extra]` as a glob with a character class and would not + # append the extras correctly. + DT_WHEEL=$(ls $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask/*.whl) + DT_AM_WHEEL=$(ls $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged/*.whl) + python -m pip install "${DT_WHEEL}[opentelemetry,azure-blob-payloads]" + python -m pip install "${DT_AM_WHEEL}[azure-blob-payloads]" displayName: "Install built wheels" - script: pytest -m "not dts and not azurite" --verbose