diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d1c2f5..bca5a28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +## v1.5.0 + ADDED - Added `ReplaySafeLogger` and `OrchestrationContext.create_replay_safe_logger()` diff --git a/durabletask-azuremanaged/CHANGELOG.md b/durabletask-azuremanaged/CHANGELOG.md index 2a416c3..8a74350 100644 --- a/durabletask-azuremanaged/CHANGELOG.md +++ b/durabletask-azuremanaged/CHANGELOG.md @@ -7,6 +7,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +## v1.5.0 + +- Updates base dependency to durabletask v1.5.0 - Added optional `interceptors`, `channel`, and `channel_options` parameters to `DurableTaskSchedulerClient`, `AsyncDurableTaskSchedulerClient`, and `DurableTaskSchedulerWorker` to allow combining custom gRPC interceptors with diff --git a/durabletask-azuremanaged/pyproject.toml b/durabletask-azuremanaged/pyproject.toml index ee23588..e5e2b0b 100644 --- a/durabletask-azuremanaged/pyproject.toml +++ b/durabletask-azuremanaged/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "durabletask.azuremanaged" -version = "1.4.0" +version = "1.5.0" description = "Durable Task Python SDK provider implementation for the Azure Durable Task Scheduler" keywords = [ "durable", @@ -26,13 +26,13 @@ requires-python = ">=3.10" license = {file = "LICENSE"} readme = "README.md" dependencies = [ - "durabletask>=1.4.0", + "durabletask>=1.5.0", "azure-identity>=1.19.0" ] [project.optional-dependencies] azure-blob-payloads = [ - "durabletask[azure-blob-payloads]>=1.4.0" + "durabletask[azure-blob-payloads]>=1.5.0" ] [project.urls] diff --git a/eng/ci/official-build.yml b/eng/ci/official-build.yml new file mode 100644 index 0000000..429e251 --- /dev/null +++ b/eng/ci/official-build.yml @@ -0,0 +1,55 @@ +variables: + - template: ci/variables/cfs.yml@eng + +trigger: + batch: true + branches: + include: + - main + +# CI only, does not trigger on PRs. +pr: none + +schedules: + # Build nightly to catch any new CVEs and report SDL often. + # We are also required to generate CodeQL reports weekly, so this + # helps us meet that. + - cron: "0 5 * * *" + displayName: Nightly Build + branches: + include: + - main + always: true + +resources: + repositories: + - repository: 1es + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: eng + type: git + name: engineering + ref: refs/tags/release + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1es + parameters: + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + ${{ if eq( variables['Build.Reason'], 'Schedule' ) }}: + demands: + - Priority -equals Low + sdl: + sourceAnalysisPool: + name: 1es-pool-azfunc + image: 1es-windows-2022 + os: windows + + stages: + - stage: BuildAndSign + dependsOn: [] + jobs: + - template: /eng/templates/build.yml@self diff --git a/eng/ci/release.yml b/eng/ci/release.yml new file mode 100644 index 0000000..0bd8a52 --- /dev/null +++ b/eng/ci/release.yml @@ -0,0 +1,90 @@ +pr: none +trigger: none + +resources: + repositories: + - repository: 1ESPipelineTemplates + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + pipelines: + - pipeline: DurableTaskPythonBuildPipeline + source: durabletask-python.official + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1ESPipelineTemplates + parameters: + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + stages: + - stage: release + jobs: + - job: durabletask + displayName: "Release durabletask" + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: DurableTaskPythonBuildPipeline + artifactName: drop + targetPath: $(System.DefaultWorkingDirectory)/drop + + steps: + - task: SFP.release-tasks.custom-build-release-task.EsrpRelease@9 + displayName: "ESRP Release durabletask" + inputs: + connectedservicename: "dtfx-internal-esrp-prod" + usemanagedidentity: true + keyvaultname: "durable-esrp-akv" + signcertname: "dts-esrp-cert" + clientid: "0b3ed1a4-0727-4a50-b82a-02c2bd9dec89" + intent: "PackageDistribution" + contenttype: "PyPi" + contentsource: "Folder" + folderlocation: "$(System.DefaultWorkingDirectory)/drop/buildoutputs/durabletask" + waitforreleasecompletion: true + # Auto-populate from the build queuer's identity so we don't + # hardcode personal emails in source. ESRP will send the + # release notification / approval link to whoever clicked + # "Run pipeline". This matches the pattern used by + # Azure/azure-sdk-for-python and microsoft/mcp pipelines. + owners: $(Build.RequestedForEmail) + approvers: $(Build.RequestedForEmail) + serviceendpointurl: "https://api.esrp.microsoft.com" + mainpublisher: "durabletask-java" + domaintenantid: "33e01921-4d64-4f8c-a055-5bdaffd5e33d" + + - job: durabletask_azuremanaged + displayName: "Release durabletask-azuremanaged" + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + pipeline: DurableTaskPythonBuildPipeline + artifactName: drop + targetPath: $(System.DefaultWorkingDirectory)/drop + + steps: + - task: SFP.release-tasks.custom-build-release-task.EsrpRelease@9 + displayName: "ESRP Release durabletask-azuremanaged" + inputs: + connectedservicename: "dtfx-internal-esrp-prod" + usemanagedidentity: true + keyvaultname: "durable-esrp-akv" + signcertname: "dts-esrp-cert" + clientid: "0b3ed1a4-0727-4a50-b82a-02c2bd9dec89" + intent: "PackageDistribution" + contenttype: "PyPi" + contentsource: "Folder" + folderlocation: "$(System.DefaultWorkingDirectory)/drop/buildoutputs/durabletask-azuremanaged" + waitforreleasecompletion: true + owners: $(Build.RequestedForEmail) + approvers: $(Build.RequestedForEmail) + serviceendpointurl: "https://api.esrp.microsoft.com" + mainpublisher: "durabletask-java" + domaintenantid: "33e01921-4d64-4f8c-a055-5bdaffd5e33d" diff --git a/eng/templates/build.yml b/eng/templates/build.yml new file mode 100644 index 0000000..0b9b393 --- /dev/null +++ b/eng/templates/build.yml @@ -0,0 +1,80 @@ +jobs: + - job: BuildAndSign + displayName: "Build and sign" + templateContext: + outputs: + - output: pipelineArtifact + path: $(Build.ArtifactStagingDirectory) + artifact: drop + sbomBuildDropPath: "$(System.DefaultWorkingDirectory)" + sbomPackageName: "Durable Task Python SBOM" + + steps: + - checkout: self + + - task: UsePythonVersion@0 + displayName: "Use Python 3.12" + inputs: + versionSpec: "3.12" + addToPath: true + + # The 1ES pool is network-isolated, so direct pypi.org access is blocked. + # Authenticate pip to an ADO Artifacts feed that proxies PyPI as upstream. + - task: PipAuthenticate@1 + displayName: "Pip Authenticate" + inputs: + artifactFeeds: "internal/PythonSDK_Internal_PublicPackages" + + # Install build + lint + test tooling + - script: | + python -m pip install --upgrade pip + python -m pip install build flake8 pytest pytest-asyncio aiohttp + displayName: "Install build tooling" + + # Lint core SDK + - script: flake8 . + displayName: "flake8: durabletask" + workingDirectory: durabletask + + # Lint azuremanaged provider + - script: flake8 . + displayName: "flake8: durabletask-azuremanaged" + workingDirectory: durabletask-azuremanaged + + # Build sdist + wheel for durabletask (core SDK) + - script: | + python -m build --sdist --wheel --outdir $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask . + displayName: "Build durabletask (sdist + wheel)" + + # Build sdist + wheel for durabletask-azuremanaged + - script: | + python -m build --sdist --wheel --outdir $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged ./durabletask-azuremanaged + displayName: "Build durabletask-azuremanaged (sdist + wheel)" + + # List staged outputs for visibility in logs + - script: | + ls -la $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask + 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. + - script: | + set -e + python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask/*.whl + python -m pip install $(Build.ArtifactStagingDirectory)/buildoutputs/durabletask-azuremanaged/*.whl + displayName: "Install built wheels" + + - script: pytest -m "not dts and not azurite" --verbose + displayName: "pytest: durabletask (unit tests, no emulators)" + workingDirectory: tests/durabletask + + - script: pytest -m "not dts" --verbose + displayName: "pytest: durabletask-azuremanaged (unit tests, no emulators)" + workingDirectory: tests/durabletask-azuremanaged diff --git a/pyproject.toml b/pyproject.toml index 145b930..731b988 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ build-backend = "setuptools.build_meta" [project] name = "durabletask" -version = "1.4.0" +version = "1.5.0" description = "A Durable Task Client SDK for Python" keywords = [ "durable",