From 5c41c8d699f6f52ee647dbfaa14d4eea2dd24cbb Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Wed, 10 Dec 2025 13:12:12 -0600 Subject: [PATCH 1/9] Release fixes from 4.41.1 --- eng/ci/integration-tests.yml | 4 + .../official/jobs/ci-simple-e2e-tests.yml | 42 +++++++ .../official/jobs/publish-release.yml | 2 +- .../endtoend/test_basic_http_functions.py | 110 ++++++++++++++++++ 4 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 eng/templates/official/jobs/ci-simple-e2e-tests.yml create mode 100644 workers/tests/endtoend/test_basic_http_functions.py diff --git a/eng/ci/integration-tests.yml b/eng/ci/integration-tests.yml index 5dfb6c7d8..9015bbc84 100644 --- a/eng/ci/integration-tests.yml +++ b/eng/ci/integration-tests.yml @@ -51,3 +51,7 @@ extends: dependsOn: [] jobs: - template: /eng/templates/official/jobs/ci-lc-tests.yml@self + - stage: RunSimpleE2ETests + dependsOn: [] + jobs: + - template: /eng/templates/official/jobs/ci-simple-e2e-tests.yml@self diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml new file mode 100644 index 000000000..32785ff7e --- /dev/null +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -0,0 +1,42 @@ +parameters: + PROJECT_DIRECTORY: 'workers' + +jobs: + - job: "TestPython" + displayName: "Run HTTP Trigger Integration Test" + + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + strategy: + matrix: + Python39: + PYTHON_VERSION: '3.9' + STORAGE_CONNECTION: $(LinuxStorageConnectionString39) + Python313: + PYTHON_VERSION: '3.13' + STORAGE_CONNECTION: $(LinuxStorageConnectionString312) + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + - task: UseDotNet@2 + displayName: 'Install .NET 8' + inputs: + version: 8.0.x + - bash: | + python -m pip install --upgrade pip + python -m pip install . pytest~=7.4.4 + + chmod +x eng/scripts/test-setup.sh + eng/scripts/test-setup.sh + displayName: 'Install only worker dependencies and build the host' + - bash: | + python -m pytest tests/endtoend/test_basic_http_functions.py + env: + AzureWebJobsStorage: $(STORAGE_CONNECTION) + PYAZURE_WEBHOST_DEBUG: true + displayName: "Running $(PYTHON_VERSION) Python Simple E2E Tests" + workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }} diff --git a/eng/templates/official/jobs/publish-release.yml b/eng/templates/official/jobs/publish-release.yml index 54d87313e..2cba69900 100644 --- a/eng/templates/official/jobs/publish-release.yml +++ b/eng/templates/official/jobs/publish-release.yml @@ -123,7 +123,7 @@ jobs: # Modify release_notes.md Write-Host "Adding a new entry in release_notes.md" - Add-Content -Path release_notes.md -Value "`n- Update Python Worker Version to [$newWorkerVersion](https://github.com/Azure/azure-functions-python-worker/releases/tag/$newWorkerVersion)" + Add-Content -Path release_notes.md -Value "- Update Python Worker Version to [$newWorkerVersion](https://github.com/Azure/azure-functions-python-worker/releases/tag/$newWorkerVersion)" # Commit Python Version diff --git a/workers/tests/endtoend/test_basic_http_functions.py b/workers/tests/endtoend/test_basic_http_functions.py new file mode 100644 index 000000000..f4b04ff15 --- /dev/null +++ b/workers/tests/endtoend/test_basic_http_functions.py @@ -0,0 +1,110 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +from tests.utils import testutils + +REQUEST_TIMEOUT_SEC = 5 + + +class TestHttpFunctions(testutils.WebHostTestCase): + """Test the native Http Trigger in the local webhost. + + This test class will spawn a webhost from your /build/webhost + folder and replace the built-in Python with azure_functions_worker from + your code base. Since the Http Trigger is a native suport from host, we + don't need to setup any external resources. + + Compared to the unittests/test_http_functions.py, this file is more focus + on testing the E2E flow scenarios. + """ + + def setUp(self): + super().setUp() + + def tearDown(self): + super().tearDown() + + @classmethod + def get_script_dir(cls): + return testutils.E2E_TESTS_FOLDER / 'http_functions' + + def test_function_index_page_should_return_ok(self): + """The index page of Azure Functions should return OK in any + circumstances + """ + r = self.webhost.request('GET', '', no_prefix=True, + timeout=REQUEST_TIMEOUT_SEC) + self.assertTrue(r.ok) + + def test_default_http_template_should_return_ok(self): + """Test if the default template of Http trigger in Python Function app + will return OK + """ + r = self.webhost.request('GET', 'default_template', + timeout=REQUEST_TIMEOUT_SEC) + self.assertTrue(r.ok) + + def test_default_http_template_should_accept_query_param(self): + """Test if the azure.functions SDK is able to deserialize query + parameter from the default template + """ + r = self.webhost.request('GET', 'default_template', + params={'name': 'query'}, + timeout=REQUEST_TIMEOUT_SEC) + self.assertTrue(r.ok) + self.assertEqual( + r.content, + b'Hello, query. This HTTP triggered function executed successfully.' + ) + + def test_default_http_template_should_accept_body(self): + """Test if the azure.functions SDK is able to deserialize http body + and pass it to default template + """ + r = self.webhost.request('POST', 'default_template', + data='{ "name": "body" }'.encode('utf-8'), + timeout=REQUEST_TIMEOUT_SEC) + self.assertTrue(r.ok) + self.assertEqual( + r.content, + b'Hello, body. This HTTP triggered function executed successfully.' + ) + + +class TestHttpFunctionsStein(TestHttpFunctions): + + @classmethod + def get_script_dir(cls): + return testutils.E2E_TESTS_FOLDER / 'http_functions' / \ + 'http_functions_stein' + + def test_return_custom_class(self): + """Test if returning a custom class returns OK + """ + r = self.webhost.request('GET', 'custom_response', + timeout=REQUEST_TIMEOUT_SEC) + self.assertEqual( + r.content, + b'{"status": "healthy"}' + ) + self.assertTrue(r.ok) + + def test_return_custom_class_with_query_param(self): + """Test if query is accepted + """ + r = self.webhost.request('GET', 'custom_response', + params={'name': 'query'}, + timeout=REQUEST_TIMEOUT_SEC) + self.assertTrue(r.ok) + self.assertEqual( + r.content, + b'{"name": "query"}' + ) + + +class TestHttpFunctionsSteinGeneric(TestHttpFunctionsStein): + + @classmethod + def get_script_dir(cls): + return testutils.E2E_TESTS_FOLDER / 'http_functions' / \ + 'http_functions_stein' / \ + 'generic' From ee810ab881b9f38b2a6fafae6c3d978ca42ff84c Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Wed, 10 Dec 2025 13:27:20 -0600 Subject: [PATCH 2/9] fix dir --- eng/templates/official/jobs/ci-simple-e2e-tests.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml index 32785ff7e..419ac71af 100644 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -27,11 +27,12 @@ jobs: inputs: version: 8.0.x - bash: | - python -m pip install --upgrade pip - python -m pip install . pytest~=7.4.4 - chmod +x eng/scripts/test-setup.sh eng/scripts/test-setup.sh + + cd ${{ parameters.PROJECT_DIRECTORY }} + python -m pip install --upgrade pip + python -m pip install . pytest~=7.4.4 displayName: 'Install only worker dependencies and build the host' - bash: | python -m pytest tests/endtoend/test_basic_http_functions.py From ce194518f6aad575769e1e1030c1e4c2d87391fe Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Thu, 11 Dec 2025 13:37:43 -0600 Subject: [PATCH 3/9] run for all versions, isntall invoke --- .../official/jobs/ci-simple-e2e-tests.yml | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml index 419ac71af..fe35ea727 100644 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -14,10 +14,16 @@ jobs: matrix: Python39: PYTHON_VERSION: '3.9' - STORAGE_CONNECTION: $(LinuxStorageConnectionString39) + Python310: + PYTHON_VERSION: '3.10' + Python311: + PYTHON_VERSION: '3.11' + Python312: + PYTHON_VERSION: '3.12' Python313: PYTHON_VERSION: '3.13' - STORAGE_CONNECTION: $(LinuxStorageConnectionString312) + Python314: + PYTHON_VERSION: '3.14' steps: - task: UsePythonVersion@0 inputs: @@ -27,17 +33,19 @@ jobs: inputs: version: 8.0.x - bash: | + cd workers + python -m pip install --upgrade pip + python -m pip install . pytest~=7.4.4 invoke + + cd .. chmod +x eng/scripts/test-setup.sh eng/scripts/test-setup.sh - cd ${{ parameters.PROJECT_DIRECTORY }} - python -m pip install --upgrade pip - python -m pip install . pytest~=7.4.4 displayName: 'Install only worker dependencies and build the host' - bash: | python -m pytest tests/endtoend/test_basic_http_functions.py env: - AzureWebJobsStorage: $(STORAGE_CONNECTION) + AzureWebJobsStorage: $(LinuxStorageConnectionString312) PYAZURE_WEBHOST_DEBUG: true displayName: "Running $(PYTHON_VERSION) Python Simple E2E Tests" workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }} From e267875c52517042cea80e0e068dc62407912fa3 Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Thu, 11 Dec 2025 14:25:03 -0600 Subject: [PATCH 4/9] add requests --- eng/templates/official/jobs/ci-simple-e2e-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml index fe35ea727..3ee06b164 100644 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -35,7 +35,7 @@ jobs: - bash: | cd workers python -m pip install --upgrade pip - python -m pip install . pytest~=7.4.4 invoke + python -m pip install . pytest~=7.4.4 invoke requests cd .. chmod +x eng/scripts/test-setup.sh From 00c1005c5850ec00d76555995ffcdc6063e7dbd7 Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Thu, 11 Dec 2025 15:40:34 -0600 Subject: [PATCH 5/9] fix worker installation --- eng/templates/official/jobs/ci-simple-e2e-tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml index 3ee06b164..ce8a8d0ea 100644 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -37,10 +37,13 @@ jobs: python -m pip install --upgrade pip python -m pip install . pytest~=7.4.4 invoke requests + # Remove from virtual environment + pip uninstall -y azure-functions-worker + pip uninstall -y proxy-worker + cd .. chmod +x eng/scripts/test-setup.sh eng/scripts/test-setup.sh - displayName: 'Install only worker dependencies and build the host' - bash: | python -m pytest tests/endtoend/test_basic_http_functions.py From 53764c66b29ad1c5ab7b8f3f5ee66a9aa6cfc54a Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Fri, 12 Dec 2025 10:06:10 -0600 Subject: [PATCH 6/9] debug --- eng/templates/official/jobs/ci-simple-e2e-tests.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml index ce8a8d0ea..aaf2ab096 100644 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ b/eng/templates/official/jobs/ci-simple-e2e-tests.yml @@ -35,16 +35,18 @@ jobs: - bash: | cd workers python -m pip install --upgrade pip - python -m pip install . pytest~=7.4.4 invoke requests - - # Remove from virtual environment - pip uninstall -y azure-functions-worker - pip uninstall -y proxy-worker + python -m pip install . pytest~=7.4.4 invoke requests==2.* cd .. chmod +x eng/scripts/test-setup.sh eng/scripts/test-setup.sh displayName: 'Install only worker dependencies and build the host' + - bash: | + echo "Current directory: $(pwd)" + echo "Build.SourcesDirectory: $(Build.SourcesDirectory)" + echo "Contents of Build.SourcesDirectory:" + ls -la $(Build.SourcesDirectory) + displayName: 'Debug directory information' - bash: | python -m pytest tests/endtoend/test_basic_http_functions.py env: From 59303f4bc95352027285f7a8868708bf15d3937c Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Fri, 12 Dec 2025 10:29:52 -0600 Subject: [PATCH 7/9] change in approach --- eng/ci/integration-tests.yml | 4 - eng/ci/public-build.yml | 4 + eng/templates/jobs/ci-dependency-check.yml | 83 +++++++++++++++++++ .../official/jobs/ci-simple-e2e-tests.yml | 56 ------------- 4 files changed, 87 insertions(+), 60 deletions(-) create mode 100644 eng/templates/jobs/ci-dependency-check.yml delete mode 100644 eng/templates/official/jobs/ci-simple-e2e-tests.yml diff --git a/eng/ci/integration-tests.yml b/eng/ci/integration-tests.yml index 9015bbc84..5dfb6c7d8 100644 --- a/eng/ci/integration-tests.yml +++ b/eng/ci/integration-tests.yml @@ -51,7 +51,3 @@ extends: dependsOn: [] jobs: - template: /eng/templates/official/jobs/ci-lc-tests.yml@self - - stage: RunSimpleE2ETests - dependsOn: [] - jobs: - - template: /eng/templates/official/jobs/ci-simple-e2e-tests.yml@self diff --git a/eng/ci/public-build.yml b/eng/ci/public-build.yml index 69ae8576f..19c350e10 100644 --- a/eng/ci/public-build.yml +++ b/eng/ci/public-build.yml @@ -60,6 +60,10 @@ extends: PROJECT_DIRECTORY: 'workers' # Skip the build stage for SDK and Extensions release branches. This stage will fail because pyproject.toml contains the updated (and unreleased) library version condition: and(eq(variables.isSdkRelease, false), eq(variables.isExtensionsRelease, false), eq(variables['USETESTPYTHONSDK'], false), eq(variables['USETESTPYTHONEXTENSIONS'], false)) + - stage: CheckPythonWorkerDependencies + dependsOn: BuildPythonWorker + jobs: + - template: /eng/templates/jobs/ci-dependency-check.yml@self - stage: RunWorkerUnitTests dependsOn: BuildPythonWorker jobs: diff --git a/eng/templates/jobs/ci-dependency-check.yml b/eng/templates/jobs/ci-dependency-check.yml new file mode 100644 index 000000000..d86378e6d --- /dev/null +++ b/eng/templates/jobs/ci-dependency-check.yml @@ -0,0 +1,83 @@ +parameters: + PROJECT_DIRECTORY: 'workers' + +jobs: + - job: "TestPython" + displayName: "Run HTTP Trigger Integration Test" + + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + strategy: + matrix: + Python39: + PYTHON_VERSION: '3.9' + Python310: + PYTHON_VERSION: '3.10' + Python311: + PYTHON_VERSION: '3.11' + Python312: + PYTHON_VERSION: '3.12' + Python313: + PYTHON_VERSION: '3.13' + Python314: + PYTHON_VERSION: '3.14' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + - bash: | + cd workers + pip install --no-deps . + + PY_VER="$(PYTHON_VERSION)" + echo "Python version: $PY_VER" + + # Extract minor version + PY_MINOR="${PY_VER#*.}" + + python -c "import pkgutil, sys; + + if [ "$PY_MINOR" -ge 13 ]; then + import proxy_worker; + else + import azure_functions_worker; + fi + print('OK: imports resolved')" + displayName: 'Python Worker: check for missing dependencies' + - bash: | + cd runtimes/v1 + pip install --no-deps . + + PY_VER="$(PYTHON_VERSION)" + echo "Python version: $PY_VER" + + # Extract minor version + PY_MINOR="${PY_VER#*.}" + + python -c "import pkgutil, sys; + + if [ "$PY_MINOR" -ge 13 ]; then + import azure_functions_runtime_v1; + fi + print('OK: imports resolved')" + displayName: 'Python Library V1: check for missing dependencies' + - bash: | + cd runtimes/v2 + pip install --no-deps . + + PY_VER="$(PYTHON_VERSION)" + echo "Python version: $PY_VER" + + # Extract minor version + PY_MINOR="${PY_VER#*.}" + + python -c "import pkgutil, sys; + + if [ "$PY_MINOR" -ge 13 ]; then + import azure_functions_runtime; + fi + print('OK: imports resolved')" + displayName: 'Python Library V2: check for missing dependencies' diff --git a/eng/templates/official/jobs/ci-simple-e2e-tests.yml b/eng/templates/official/jobs/ci-simple-e2e-tests.yml deleted file mode 100644 index aaf2ab096..000000000 --- a/eng/templates/official/jobs/ci-simple-e2e-tests.yml +++ /dev/null @@ -1,56 +0,0 @@ -parameters: - PROJECT_DIRECTORY: 'workers' - -jobs: - - job: "TestPython" - displayName: "Run HTTP Trigger Integration Test" - - pool: - name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux - - strategy: - matrix: - Python39: - PYTHON_VERSION: '3.9' - Python310: - PYTHON_VERSION: '3.10' - Python311: - PYTHON_VERSION: '3.11' - Python312: - PYTHON_VERSION: '3.12' - Python313: - PYTHON_VERSION: '3.13' - Python314: - PYTHON_VERSION: '3.14' - steps: - - task: UsePythonVersion@0 - inputs: - versionSpec: $(PYTHON_VERSION) - - task: UseDotNet@2 - displayName: 'Install .NET 8' - inputs: - version: 8.0.x - - bash: | - cd workers - python -m pip install --upgrade pip - python -m pip install . pytest~=7.4.4 invoke requests==2.* - - cd .. - chmod +x eng/scripts/test-setup.sh - eng/scripts/test-setup.sh - displayName: 'Install only worker dependencies and build the host' - - bash: | - echo "Current directory: $(pwd)" - echo "Build.SourcesDirectory: $(Build.SourcesDirectory)" - echo "Contents of Build.SourcesDirectory:" - ls -la $(Build.SourcesDirectory) - displayName: 'Debug directory information' - - bash: | - python -m pytest tests/endtoend/test_basic_http_functions.py - env: - AzureWebJobsStorage: $(LinuxStorageConnectionString312) - PYAZURE_WEBHOST_DEBUG: true - displayName: "Running $(PYTHON_VERSION) Python Simple E2E Tests" - workingDirectory: $(Build.SourcesDirectory)/${{ parameters.PROJECT_DIRECTORY }} From fa90875213ceef87b511701edf2ff00f8e0d2c17 Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Fri, 12 Dec 2025 10:57:50 -0600 Subject: [PATCH 8/9] fix pool --- eng/ci/public-build.yml | 2 ++ eng/templates/jobs/ci-dependency-check.yml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/eng/ci/public-build.yml b/eng/ci/public-build.yml index 19c350e10..17d8000c3 100644 --- a/eng/ci/public-build.yml +++ b/eng/ci/public-build.yml @@ -64,6 +64,8 @@ extends: dependsOn: BuildPythonWorker jobs: - template: /eng/templates/jobs/ci-dependency-check.yml@self + parameters: + PoolName: 1es-pool-azfunc-public - stage: RunWorkerUnitTests dependsOn: BuildPythonWorker jobs: diff --git a/eng/templates/jobs/ci-dependency-check.yml b/eng/templates/jobs/ci-dependency-check.yml index d86378e6d..15ad87997 100644 --- a/eng/templates/jobs/ci-dependency-check.yml +++ b/eng/templates/jobs/ci-dependency-check.yml @@ -3,10 +3,10 @@ parameters: jobs: - job: "TestPython" - displayName: "Run HTTP Trigger Integration Test" + displayName: "Run Dependency Checks" pool: - name: 1es-pool-azfunc + name: ${{ parameters.PoolName }} image: 1es-ubuntu-22.04 os: linux From 77e066fb12237954233e5619993552d28d9d94df Mon Sep 17 00:00:00 2001 From: Victoria Hall Date: Fri, 12 Dec 2025 14:42:16 -0600 Subject: [PATCH 9/9] fix? --- eng/templates/jobs/ci-dependency-check.yml | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/eng/templates/jobs/ci-dependency-check.yml b/eng/templates/jobs/ci-dependency-check.yml index 15ad87997..13dfc89ec 100644 --- a/eng/templates/jobs/ci-dependency-check.yml +++ b/eng/templates/jobs/ci-dependency-check.yml @@ -36,16 +36,17 @@ jobs: echo "Python version: $PY_VER" # Extract minor version - PY_MINOR="${PY_VER#*.}" - - python -c "import pkgutil, sys; + PY_MINOR="${PY_VER#*.}" if [ "$PY_MINOR" -ge 13 ]; then + python -c "import pkgutil, sys; import proxy_worker; + print('OK: imports resolved')" else + python -c "import pkgutil, sys; import azure_functions_worker; + print('OK: imports resolved')" fi - print('OK: imports resolved')" displayName: 'Python Worker: check for missing dependencies' - bash: | cd runtimes/v1 @@ -57,12 +58,11 @@ jobs: # Extract minor version PY_MINOR="${PY_VER#*.}" - python -c "import pkgutil, sys; - if [ "$PY_MINOR" -ge 13 ]; then + python -c "import pkgutil, sys; import azure_functions_runtime_v1; + print('OK: imports resolved')" fi - print('OK: imports resolved')" displayName: 'Python Library V1: check for missing dependencies' - bash: | cd runtimes/v2 @@ -72,12 +72,11 @@ jobs: echo "Python version: $PY_VER" # Extract minor version - PY_MINOR="${PY_VER#*.}" - - python -c "import pkgutil, sys; + PY_MINOR="${PY_VER#*.}" if [ "$PY_MINOR" -ge 13 ]; then + python -c "import pkgutil, sys; import azure_functions_runtime; + print('OK: imports resolved')" fi - print('OK: imports resolved')" displayName: 'Python Library V2: check for missing dependencies'