Repository: Azure/azure-functions-python-worker (language: python)

Issue:
Functions Integration Tests—Onboard Python worker 
Please follow the instructions in the OneNote to onboard your language worker. 


Discussion / hints:
E2E Core Tools successfully generated, next step: integrating core tools into E2E tests 

Fix patch:
diff --git a/.ci/linux_devops_build.sh b/.ci/linux_devops_build.sh
index ec1756b3..fdae3f57 100644
--- a/.ci/linux_devops_build.sh
+++ b/.ci/linux_devops_build.sh
@@ -12,3 +12,6 @@ python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-ur
 
 # Download Azure Functions Host
 python setup.py webhost
+
+# Setup WebJobs Extensions
+python setup.py extension
\ No newline at end of file
diff --git a/.github/workflows/ut_ci_workflow.yml b/.github/workflows/ut_ci_workflow.yml
index d45e6b8c..c45df624 100644
--- a/.github/workflows/ut_ci_workflow.yml
+++ b/.github/workflows/ut_ci_workflow.yml
@@ -38,6 +38,7 @@ jobs:
         python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple -U azure-functions --pre
         python setup.py build
         python setup.py webhost
+        python setup.py extension
     - name: Test with pytest
       run: |
         pytest  --instafail --cov=./azure_functions_worker --cov-report xml --cov-branch tests/unittests
diff --git a/.gitignore b/.gitignore
index b999acb6..4d233c0f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -121,4 +121,8 @@ py3env/
 .idea_modules/
 
 # Profiling info
-prof/
\ No newline at end of file
+prof/
+
+# E2E Integration Test Core Tools
+.ci/e2e_integration_test/Azure.Functions.Cli/
+.ci/e2e_integration_test/Azure.Functions.Cli*
\ No newline at end of file
diff --git a/azure_functions_worker/constants.py b/azure_functions_worker/constants.py
index b5e13f24..6417dbf3 100644
--- a/azure_functions_worker/constants.py
+++ b/azure_functions_worker/constants.py
@@ -14,6 +14,10 @@
 # Debug Flags
 PYAZURE_WEBHOST_DEBUG = "PYAZURE_WEBHOST_DEBUG"
 
+# E2E Integration Flags and Configurations
+PYAZURE_INTEGRATION_TEST = "PYAZURE_INTEGRATION_TEST"
+PYAZURE_WORKER_DIR = "PYAZURE_WORKER_DIR"
+
 # Platform Environment Variables
 AZURE_WEBJOBS_SCRIPT_ROOT = "AzureWebJobsScriptRoot"
 
diff --git a/setup.py b/setup.py
index 0b2dcb49..e76244e6 100644
--- a/setup.py
+++ b/setup.py
@@ -163,6 +163,54 @@ def run(self, *args, **kwargs):
         super().run(*args, **kwargs)
 
 
+class extension(distutils.cmd.Command):
+    description = (
+        'Resolve WebJobs Extensions from AZURE_EXTENSIONS and NUGET_CONFIG.'
+    )
+    user_options = [
+        ('extensions-dir', None,
+         'A path to the directory where extension should be installed')
+    ]
+
+    def initialize_options(self):
+        self.extensions_dir = None
+
+    def finalize_options(self):
+        if self.extensions_dir is None:
+            self.extensions_dir = \
+                pathlib.Path(__file__).parent / 'build' / 'extensions'
+
+    def _install_extensions(self):
+        if not self.extensions_dir.exists():
+            os.makedirs(self.extensions_dir, exist_ok=True)
+
+        if not (self.extensions_dir / 'host.json').exists():
+            with open(self.extensions_dir / 'host.json', 'w') as f:
+                print('{}', file=f)
+
+        if not (self.extensions_dir / 'extensions.csproj').exists():
+            with open(self.extensions_dir / 'extensions.csproj', 'w') as f:
+                print(AZURE_EXTENSIONS, file=f)
+
+        with open(self.extensions_dir / 'NuGet.config', 'w') as f:
+            print(NUGET_CONFIG, file=f)
+
+        env = os.environ.copy()
+        env['TERM'] = 'xterm'  # ncurses 6.1 workaround
+        try:
+            subprocess.run(
+                args=['dotnet', 'build', '-o', '.'], check=True,
+                cwd=str(self.extensions_dir),
+                stdout=sys.stdout, stderr=sys.stderr, env=env)
+        except Exception:
+            print(".NET Core SDK is required to build the extensions. "
+                  "Please visit https://aka.ms/dotnet-download")
+            sys.exit(1)
+
+    def run(self):
+        self._install_extensions()
+
+
 class webhost(distutils.cmd.Command):
     description = 'Download and setup Azure Functions Web Host.'
     user_options = [
@@ -175,7 +223,6 @@ class webhost(distutils.cmd.Command):
     def initialize_options(self):
         self.webhost_version = None
         self.webhost_dir = None
-        self.extensions_dir = None
 
     def finalize_options(self):
         if self.webhost_version is None:
@@ -185,10 +232,6 @@ def finalize_options(self):
             self.webhost_dir = \
                 pathlib.Path(__file__).parent / 'build' / 'webhost'
 
-        if self.extensions_dir is None:
-            self.extensions_dir = \
-                pathlib.Path(__file__).parent / 'build' / 'extensions'
-
     def _get_webhost_version(self) -> str:
         # Return the latest matched version (e.g. 3.0.15278)
         github_api_url = f'{WEBHOST_GITHUB_API}/tags?page=1&per_page=10'
@@ -294,33 +337,6 @@ def _compile_webhost(self, webhost_dir: pathlib.Path):
 
         print('Functions Host is compiled successfully')
 
-    def _install_extensions(self):
-        if not self.extensions_dir.exists():
-            os.makedirs(self.extensions_dir, exist_ok=True)
-
-        if not (self.extensions_dir / 'host.json').exists():
-            with open(self.extensions_dir / 'host.json', 'w') as f:
-                print('{}', file=f)
-
-        if not (self.extensions_dir / 'extensions.csproj').exists():
-            with open(self.extensions_dir / 'extensions.csproj', 'w') as f:
-                print(AZURE_EXTENSIONS, file=f)
-
-        with open(self.extensions_dir / 'NuGet.config', 'w') as f:
-            print(NUGET_CONFIG, file=f)
-
-        env = os.environ.copy()
-        env['TERM'] = 'xterm'  # ncurses 6.1 workaround
-        try:
-            subprocess.run(
-                args=['dotnet', 'build', '-o', '.'], check=True,
-                cwd=str(self.extensions_dir),
-                stdout=sys.stdout, stderr=sys.stderr, env=env)
-        except Exception:
-            print(".NET Core SDK is required to build the extensions. "
-                  "Please visit https://aka.ms/dotnet-download")
-            sys.exit(1)
-
     def run(self):
         # Prepare webhost
         zip_path = self._download_webhost_zip(self.webhost_version)
@@ -331,9 +347,6 @@ def run(self):
         self._chmod_protobuf_generation_script(self.webhost_dir)
         self._compile_webhost(self.webhost_dir)
 
-        # Prepare extensions
-        self._install_extensions()
-
 
 with open("README.md") as readme:
     long_description = readme.read()
@@ -396,9 +409,10 @@ def run(self):
     },
     include_package_data=True,
     cmdclass={
-        'build': build,
         'develop': develop,
+        'build': build,
         'webhost': webhost,
+        'extension': extension
     },
     test_suite='tests'
 )


Test patch:
diff --git a/.ci/e2e/publish_tests/dev_docker_setup/dev.Dockerfile b/.ci/e2e/publish_tests/dev_docker_setup/dev.Dockerfile
deleted file mode 100644
index 0e2e126f..00000000
--- a/.ci/e2e/publish_tests/dev_docker_setup/dev.Dockerfile
+++ /dev/null
@@ -1,9 +0,0 @@
-ARG BASE_IMAGE=mcr.microsoft.com/azure-functions/python:2.0
-ARG PYTHON_WORKER_LOCATION=.
-FROM ${BASE_IMAGE}
-
-COPY ${PYTHON_WORKER_LOCATION} /python-worker-dev/
-
-RUN pip install -e /python-worker-dev/ && \
-    rm -rf /azure-functions-host/workers/python/worker.py && \
-    mv /python-worker-dev/python/worker.py /azure-functions-host/workers/python/
diff --git a/.ci/e2e/publish_tests/dev_docker_setup/setup.sh b/.ci/e2e/publish_tests/dev_docker_setup/setup.sh
deleted file mode 100644
index 248d2cb9..00000000
--- a/.ci/e2e/publish_tests/dev_docker_setup/setup.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-USAGE="usage ./script <ACR_Name> <dev_image_name> <working_dir>"
-
-if [[ -z "$1" ]]
-then
-    echo "Missing name of the ACR"
-    echo ${USAGE}
-    exit 1
-fi
-
-if [[ -z "$2" ]]
-then
-    echo "Missing name of the dev image to use in ACR"
-    echo ${USAGE}
-    exit 1
-fi
-
-if [[ -z "$3" ]]
-then
-    echo "Missing name of the working directory"
-    echo ${USAGE}
-    exit 1
-fi
-
-SCRIPT_DIR=`realpath $(dirname "${BASH_SOURCE[0]}")`
-
-mkdir -p $3
-cd $3
-az acr login --name $1 --output none
-git clone https://github.com/Azure/azure-functions-docker
-docker build -f ./azure-functions-docker/host/2.0/stretch/amd64/python-deps.Dockerfile ./azure-functions-docker/host/2.0/stretch/amd64 -t azure-functions-python-deps-dev
-# The directory to build from needs to be the amd64, because the Dockerfile copies resources
-docker build --build-arg BASE_PYTHON_IMAGE=azure-functions-python-deps-dev -f ./azure-functions-docker/host/2.0/stretch/amd64/python-buildenv.Dockerfile -t azure-functions-python-dev ./azure-functions-docker/host/2.0/stretch/amd64
-docker build --build-arg BASE_IMAGE=azure-functions-python-dev -f ${SCRIPT_DIR}/dev.Dockerfile ${SCRIPT_DIR}/../../../.. -t azure-functions-python-dev-updated
-docker tag azure-functions-python-dev-updated $1.azurecr.io/$2
-docker push $1.azurecr.io/$2
-echo "New image pushed to the ACR."
-echo "Starting cleanup"
-cd ..
-rm -r $3
-echo "Completed cleanup"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/dev_func_setup/setup.sh b/.ci/e2e/publish_tests/dev_func_setup/setup.sh
deleted file mode 100644
index 222b2317..00000000
--- a/.ci/e2e/publish_tests/dev_func_setup/setup.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-if [[ -z "$1" ]]
-then
-    echo "Missing name of the directory to install func CLI"
-    echo "usage ./script <directory_name>"
-    exit 1
-fi
-
-if [[ -z "$2" ]]
-then
-    echo "Missing the URL to download functions"
-fi
-
-wget $2
-echo "Retrieving func CLI version: "
-curl https://functionsclibuilds.blob.core.windows.net/builds/2/latest/version.txt
-echo ""
-unzip *.zip -d "$1"
-rm -rf *.zip
-chmod a+x "$1"/func
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/build_native_deps_test.sh b/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/build_native_deps_test.sh
deleted file mode 100644
index 05b9a2e8..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/build_native_deps_test.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/helper.sh"
-ensure_usage "$@"
-
-mkdir -p "$1"
-cd "$1"
-git clone https://github.com/asavaritayal/customer-churn-prediction
-cd customer-churn-prediction
-FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps
-
-if [[ $? -eq 0 ]]
-then
-    sleep 5s
-    # https://stackoverflow.com/questions/2220301/how-to-evaluate-http-response-codes-from-bash-shell-script
-    STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/predict)
-    verify_status_code $1.result
-else
-    echo -e "${RED}Publishing failed (1/2)${RESET}"
-    # Sometimes due to flakiness with the docker daemon or an azure resource may cause it to fail-
-    # So, we retry, but just once
-    echo "Retrying once....."
-    FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps
-    if [[ $? -eq 0 ]]
-    then
-        sleep 5s
-        STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/predict)
-        verify_status_code $1.result
-    else
-        echo -e "${RED}Publishing failed (2/2)${RESET}"
-        echo -e "${RED}FAILED${RESET}" > $1.result
-    fi
-fi
-
-cd ../..
-rm -rf "$1"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/no_bundler_test.sh b/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/no_bundler_test.sh
deleted file mode 100644
index af5e0f22..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/customer_churn_app/no_bundler_test.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/helper.sh"
-ensure_usage "$@"
-
-mkdir -p "$1"
-cd "$1"
-git clone https://github.com/asavaritayal/customer-churn-prediction
-cd customer-churn-prediction
-FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps --no-bundler
-
-if [[ $? -eq 0 ]]
-then
-    sleep 5s
-    # https://stackoverflow.com/questions/2220301/how-to-evaluate-http-response-codes-from-bash-shell-script
-    STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/predict)
-    verify_status_code $1.result
-else
-    echo -e "${RED}Publishing failed (1/2)${RESET}"
-    # Sometimes due to flakiness with the docker daemon or an azure resource may cause it to fail-
-    # So, we retry, but just once
-    echo "Retrying once....."
-    FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps --no-bundler
-    if [[ $? -eq 0 ]]
-    then
-        sleep 5s
-        STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/predict)
-        verify_status_code $1.result
-    else
-        echo -e "${RED}Publishing failed (2/2)${RESET}"
-        echo -e "${RED}FAILED${RESET}" > $1.result
-    fi
-fi
-
-cd ../..
-rm -rf "$1"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/helpers/helper.sh b/.ci/e2e/publish_tests/func_tests_core/helpers/helper.sh
deleted file mode 100644
index dfbf4866..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/helpers/helper.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/env bash
-
-USAGE="usage ./script <directory_name> <appname> <func_location> <docker_image>"
-# https://stackoverflow.com/questions/5947742/how-to-change-the-output-color-of-echo-in-linux
-RED='\033[0;31m'
-GREEN='\033[0;32m'
-RESET='\033[0m' # No Color
-
-ensure_usage() {
-
-    if [[ -z "$1" ]]
-    then
-        echo "Missing name of the directory"
-        echo ${USAGE}
-        exit 1
-    fi
-
-    if [[ -z "$2" ]]
-    then
-        echo "Missing name of the functions app to publish"
-        echo ${USAGE}
-        exit 1
-    fi
-
-    if [[ -z "$3" ]]
-    then
-        echo "Missing name of the func executable"
-        echo ${USAGE}
-        exit 1
-    fi
-
-    if [[ -z "$4" ]]
-    then
-        echo "Missing name of the docker image to use"
-        echo ${USAGE}
-        exit 1
-    fi
-
-}
-
-# Assuming Status_code is set
-verify_status_code() {
-    if [[ -z "$1" ]]
-    then
-        echo "Missing name of the log file"
-        exit 1
-    fi
-    if [[ "${STATUS_CODE}" -ne 200 ]]
-    then
-        MESSAGE="${RED}TEST FAILED: Expected Status Code 200. Found Status Code ${STATUS_CODE}${RESET}"
-        (>&2 echo -e ${MESSAGE})
-        echo -e "${RED}FAILED${RESET}" > $1
-    else
-        MESSAGE="${GREEN}TEST PASSED: Status Code 200.${RESET}"
-        echo -e ${MESSAGE}
-        echo -e "${GREEN}PASSED${RESET}" > $1
-    fi
-}
-
-fail_after_timeout() {
-    timeout $1 ${@:2}
-}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/build_native_deps_test.sh b/.ci/e2e/publish_tests/func_tests_core/new_functionapp/build_native_deps_test.sh
deleted file mode 100644
index 007d275d..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/build_native_deps_test.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env bash
-
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/helper.sh"
-ensure_usage "$@"
-
-# Setup a new func app from prod func
-mkdir -p "$1"
-cd "$1"
-python -m venv env_new_build_native
-source env_new_build_native/bin/activate
-"$3" init . --worker-runtime python
-"$3" new --template httptrigger --name httptriggerTest
-
-# Change auth level to anonymous
-jq '.bindings[].authLevel="anonymous"' httptriggerTest/function.json  > httptriggerTest/replaced.json
-mv httptriggerTest/replaced.json httptriggerTest/function.json
-
-# Publish and verify
-FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps
-
-if [[ $? -eq 0 ]]
-then
-    sleep 5s
-    # https://stackoverflow.com/questions/2220301/how-to-evaluate-http-response-codes-from-bash-shell-script
-    STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-    verify_status_code $1.result
-else
-    echo -e "${RED}Publishing failed (1/2)${RESET}"
-    # Sometimes due to flakiness with the docker daemon or an azure resource may cause it to fail-
-    # So, we retry, but just once
-    echo "Retrying once....."
-    FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps
-    if [[ $? -eq 0 ]]
-    then
-        sleep 5s
-        STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-        verify_status_code $1.result
-    else
-        echo -e "${RED}Publishing failed (2/2)${RESET}"
-        echo -e "${RED}FAILED${RESET}" > $1.result
-    fi
-fi
-
-deactivate
-cd ..
-rm -rf "$1"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/no_bundler_test.sh b/.ci/e2e/publish_tests/func_tests_core/new_functionapp/no_bundler_test.sh
deleted file mode 100644
index 04c06afa..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/no_bundler_test.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env bash
-
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/helper.sh"
-ensure_usage "$@"
-
-# Setup a new func app from prod func
-mkdir -p "$1"
-cd "$1"
-python -m venv env_new_build_native
-source env_new_build_native/bin/activate
-"$3" init . --worker-runtime python
-"$3" new --template httptrigger --name httptriggerTest
-
-# Change auth level to anonymous
-jq '.bindings[].authLevel="anonymous"' httptriggerTest/function.json  > httptriggerTest/replaced.json
-mv httptriggerTest/replaced.json httptriggerTest/function.json
-
-# Publish and verify
-FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps --no-bundler
-
-if [[ $? -eq 0 ]]
-then
-    sleep 5s
-    # https://stackoverflow.com/questions/2220301/how-to-evaluate-http-response-codes-from-bash-shell-script
-    STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-    verify_status_code $1.result
-else
-    echo -e "${RED}Publishing failed (1/2)${RESET}"
-    # Sometimes due to flakiness with the docker daemon or an azure resource may cause it to fail-
-    # So, we retry, but just once
-    echo "Retrying once....."
-    FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2" --build-native-deps --no-bundler
-    if [[ $? -eq 0 ]]
-    then
-        sleep 5s
-        STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-        verify_status_code $1.result
-    else
-        echo -e "${RED}Publishing failed (2/2)${RESET}"
-        echo -e "${RED}FAILED${RESET}" > $1.result
-    fi
-fi
-
-deactivate
-cd ..
-rm -rf "$1"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/packapp_test.sh b/.ci/e2e/publish_tests/func_tests_core/new_functionapp/packapp_test.sh
deleted file mode 100644
index cb115b8d..00000000
--- a/.ci/e2e/publish_tests/func_tests_core/new_functionapp/packapp_test.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/usr/bin/env bash
-
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/helper.sh"
-ensure_usage "$@"
-
-# Setup a new func app from prod func
-mkdir -p "$1"
-cd "$1"
-python -m venv env_new_build_native
-source env_new_build_native/bin/activate
-"$3" init . --worker-runtime python
-"$3" new --template httptrigger --name httptriggerTest
-
-# Change auth level to anonymous
-jq '.bindings[].authLevel="anonymous"' httptriggerTest/function.json  > httptriggerTest/replaced.json
-mv httptriggerTest/replaced.json httptriggerTest/function.json
-
-# Publish and verify
-FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2"
-
-if [[ $? -eq 0 ]]
-then
-    sleep 5s
-    # https://stackoverflow.com/questions/2220301/how-to-evaluate-http-response-codes-from-bash-shell-script
-    STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-    verify_status_code $1.result
-else
-    echo -e "${RED}Publishing failed (1/2)${RESET}"
-    # Sometimes due to flakiness with the docker daemon or an azure resource may cause it to fail-
-    # So, we retry, but just once
-    echo "Retrying once....."
-    FUNCTIONS_PYTHON_DOCKER_IMAGE=$4 "$3" azure functionapp publish "$2"
-    if [[ $? -eq 0 ]]
-    then
-        sleep 5s
-        STATUS_CODE=$(curl --write-out %{http_code} --silent --output /dev/null https://$2.azurewebsites.net/api/httptriggerTest?name=test)
-        verify_status_code $1.result
-    else
-        echo -e "${RED}Publishing failed (2/2)${RESET}"
-        echo -e "${RED}FAILED${RESET}" > $1.result
-    fi
-fi
-
-deactivate
-cd ..
-rm -rf "$1"
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/publish_config.json b/.ci/e2e/publish_tests/publish_config.json
deleted file mode 100644
index 2c860d0d..00000000
--- a/.ci/e2e/publish_tests/publish_config.json
+++ /dev/null
@@ -1,68 +0,0 @@
-{
-  "azure_service_principal": {
-    "user_id": "${AZURE_SERVICE_PRINCIPAL_USER}",
-    "password": "${AZURE_SERVICE_PRINCIPAL_PASSWORD}",
-    "tenant": "${AZURE_SERVICE_PRINCIPAL_TENANT}"
-  },
-  "docker_setup": {
-    "acr_name": "${ACR_NAME}",
-    "working_dir": "/docker-dir",
-    "dev_image_name": "${ACR_IMAGE_NAME}",
-    "prod_image": "mcr.microsoft.com/azure-functions/python:2.0"
-  },
-  "func_setup": {
-    "func_dev_dir": "/func-dev-dir",
-    "func_dev_url": "${FUNC_DEV_URL}"
-  },
-  "tests": {
-    "working_dir": "/tests-dir",
-    "logs": "/tests-logs",
-    "timeout": "3000s"
-  },
-  "publish_function_app": {
-    "prod_func_prod_docker": {
-      "new_function": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}",
-        "packapp": "${FUNCTION_APP}"
-      },
-      "customer_churn": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}"
-      }
-    },
-    "prod_func_dev_docker": {
-      "new_function": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}",
-        "packapp": "${FUNCTION_APP}"
-      },
-      "customer_churn": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}"
-      }
-    },
-    "dev_func_prod_docker": {
-      "new_function": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}",
-        "packapp": "${FUNCTION_APP}"
-      },
-      "customer_churn": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}"
-      }
-    },
-    "dev_func_dev_docker": {
-      "new_function": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}",
-        "packapp": "${FUNCTION_APP}"
-      },
-      "customer_churn": {
-        "build_native_deps": "${FUNCTION_APP}",
-        "no_bundler": "${FUNCTION_APP}"
-      }
-    }
-  }
-}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_build_native_deps.sh
deleted file mode 100644
index 5bf95730..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_dev_docker.customer_churn.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/build_native_deps_test.sh" ${WORKING_DIR}/dfddcbnd ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_no_bundler.sh
deleted file mode 100644
index 5926c685..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/customer_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_dev_docker.customer_churn.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/no_bundler_test.sh" ${WORKING_DIR}/dfddcnb ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_build_native_deps.sh
deleted file mode 100644
index d1d9b7ad..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_dev_docker.new_function.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/build_native_deps_test.sh" ${WORKING_DIR}/dfddnbnd ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_no_bundler.sh
deleted file mode 100644
index 045f83f3..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_dev_docker.new_function.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/no_bundler_test.sh" ${WORKING_DIR}/dfddnnb ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_packapp.sh b/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_packapp.sh
deleted file mode 100644
index a7a9bc61..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_dev_docker/new_packapp.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_dev_docker.new_function.packapp')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/packapp_test.sh" ${WORKING_DIR}/dfddnpa ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_build_native_deps.sh
deleted file mode 100644
index fab55fc4..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_prod_docker.customer_churn.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/build_native_deps_test.sh" ${WORKING_DIR}/dfpdcbnd ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_no_bundler.sh
deleted file mode 100644
index 3b0df02e..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/customer_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_prod_docker.customer_churn.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/no_bundler_test.sh" ${WORKING_DIR}/dfpdcnb ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_build_native_deps.sh
deleted file mode 100644
index 89f6b81f..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_prod_docker.new_function.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/build_native_deps_test.sh" ${WORKING_DIR}/dfpdnbnd ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_no_bundler.sh
deleted file mode 100644
index 56b609f5..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_prod_docker.new_function.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/no_bundler_test.sh" ${WORKING_DIR}/dfpdnnb ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_packapp.sh b/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_packapp.sh
deleted file mode 100644
index fb5a2b05..00000000
--- a/.ci/e2e/publish_tests/test_runners/dev_func_prod_docker/new_packapp.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.dev_func_prod_docker.new_function.packapp')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/packapp_test.sh" ${WORKING_DIR}/dfpdnpa ${FUNCTION_APP} ${FUNC_DEV_DIR}/func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/helpers/get_config_variables.sh b/.ci/e2e/publish_tests/test_runners/helpers/get_config_variables.sh
deleted file mode 100644
index 534d7790..00000000
--- a/.ci/e2e/publish_tests/test_runners/helpers/get_config_variables.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration file
-GLOBAL_CONFIG="$(dirname "${BASH_SOURCE[0]}")/../../publish_config.json"
-if [[ -n "$1" ]]
-then
-    echo "Using the provided global config"
-    GLOBAL_CONFIG=$1
-fi
-
-# Docker Dev Variables
-DOCKER_CONFIG="$(cat "${GLOBAL_CONFIG}" | jq '.docker_setup')"
-ACR_NAME="$(echo "${DOCKER_CONFIG}" | jq -r '.acr_name')"
-DEV_IMAGE_NAME="$(echo "${DOCKER_CONFIG}" | jq -r '.dev_image_name')"
-DEV_DOCKER_IMAGE=${ACR_NAME}.azurecr.io/${DEV_IMAGE_NAME}
-DOCKER_WORKING_DIR="$(echo "${DOCKER_CONFIG}" | jq -r '.working_dir')"
-
-# Docker Prod Variables
-PROD_DOCKER_IMAGE="$(echo "${DOCKER_CONFIG}" | jq -r '.prod_image')"
-
-# Func Dev Variables
-FUNC_CONFIG="$(cat "${GLOBAL_CONFIG}" | jq '.func_setup')"
-FUNC_DEV_DIR="$(echo "${FUNC_CONFIG}" | jq -r '.func_dev_dir')"
-FUNC_DEV_URL="$(echo "${FUNC_CONFIG}" | jq -r '.func_dev_url')"
-
-# Working dir variables
-TESTS_CONFIG="$(cat "${GLOBAL_CONFIG}" | jq '.tests')"
-WORKING_DIR="$(echo "${TESTS_CONFIG}" | jq -r '.working_dir')"
-TESTS_LOGS="$(echo "${TESTS_CONFIG}" | jq -r '.logs')"
-TESTS_TIMEOUT="$(echo "${TESTS_CONFIG}" | jq -r '.timeout')"
-
-# Service Principal variables
-SP_CONFIG="$(cat "${GLOBAL_CONFIG}" | jq '.azure_service_principal')"
-SP_USER_NAME="$(echo "${SP_CONFIG}" | jq -r '.user_id')"
-SP_PASSWORD="$(echo "${SP_CONFIG}" | jq -r '.password')"
-SP_TENANT="$(echo "${SP_CONFIG}" | jq -r '.tenant')"
diff --git a/.ci/e2e/publish_tests/test_runners/helpers/helper.sh b/.ci/e2e/publish_tests/test_runners/helpers/helper.sh
deleted file mode 100644
index a6407722..00000000
--- a/.ci/e2e/publish_tests/test_runners/helpers/helper.sh
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env bash
-
-RESET='\033[0m' # No Color
-YELLOW='\033[1;33m'
-ORANGE='\033[0;33m'
-RED='\033[0;31m'
-
-
-yellow() {
-    echo -e "${YELLOW}$1${RESET}"
-}
-get_result_of() {
-    if [[ -z "$1" ]]
-    then
-        echo -e "${RED}FAILED${RESET}"
-    elif [[ ! -f "$1" ]]
-    then
-        echo -e "${ORANGE}SKIPPED${RESET}"
-    else
-        cat "$1"
-    fi
-}
-
-print_row_line() {
-    # (32 (-10 for colors) + 4) * 6 args + 1 for beauty
-    row=$(printf "%157s" "-")
-    echo "${row// /-}"
-}
-
-print_row() {
-    printf "%-4s" "|"
-    for arg in "$@"
-    do
-        printf "%-32s %-4s" ${arg} "|"
-    done
-    printf "\n"
-}
-
-# Expects a test_script, test_log, timeout, test_result
-run_test() {
-    exit_code=0
-    set -o pipefail
-    chmod a+x $1
-    if [[ ${TESTS_VERBOSE} = "SILENT" ]]
-    then
-        timeout $3 $1 > $2
-        exit_code=$?
-    else
-        timeout $3 $1 2>&1 | tee $2
-        exit_code=$?
-    fi
-    # This means we had a timeout
-    if [[ ${exit_code} = 124 ]]
-    then
-        echo "Test Timed Out!"
-        echo -e "${ORANGE}TIMEOUT${RESET}" > $4
-    fi
-}
-
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_build_native_deps.sh
deleted file mode 100644
index e47f63db..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_dev_docker.customer_churn.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/build_native_deps_test.sh" ${WORKING_DIR}/pfddcbnd ${FUNCTION_APP} func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_no_bundler.sh
deleted file mode 100644
index e2d82629..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/customer_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_dev_docker.customer_churn.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/no_bundler_test.sh" ${WORKING_DIR}/pfddcnb ${FUNCTION_APP} func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_build_native_deps.sh
deleted file mode 100644
index 7e2a1af9..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_dev_docker.new_function.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/build_native_deps_test.sh" ${WORKING_DIR}/pfddnbnd ${FUNCTION_APP} func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_no_bundler.sh
deleted file mode 100644
index 4599290c..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_dev_docker.new_function.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/no_bundler_test.sh" ${WORKING_DIR}/pfddnnb ${FUNCTION_APP} func ${DEV_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_packapp.sh b/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_packapp.sh
deleted file mode 100644
index a51db52c..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_dev_docker/new_packapp.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_dev_docker.new_function.packapp')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/packapp_test.sh" ${WORKING_DIR}/pfddnpa ${FUNCTION_APP} func ${DEV_DOCKER_IMAGE}
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_build_native_deps.sh
deleted file mode 100644
index 2f05e8af..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_prod_docker.customer_churn.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/build_native_deps_test.sh" ${WORKING_DIR}/pfpdcbnd ${FUNCTION_APP} func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_no_bundler.sh
deleted file mode 100644
index 267ff68b..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/customer_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_prod_docker.customer_churn.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/customer_churn_app/no_bundler_test.sh" ${WORKING_DIR}/pfpdcnb ${FUNCTION_APP} func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_build_native_deps.sh b/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_build_native_deps.sh
deleted file mode 100644
index 5c93ff2c..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_build_native_deps.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_prod_docker.new_function.build_native_deps')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/build_native_deps_test.sh" ${WORKING_DIR}/pfpdnbnd ${FUNCTION_APP} func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_no_bundler.sh b/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_no_bundler.sh
deleted file mode 100644
index da5a3280..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_no_bundler.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_prod_docker.new_function.no_bundler')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/no_bundler_test.sh" ${WORKING_DIR}/pfpdnnb ${FUNCTION_APP} func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_packapp.sh b/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_packapp.sh
deleted file mode 100644
index 90a8435d..00000000
--- a/.ci/e2e/publish_tests/test_runners/prod_func_prod_docker/new_packapp.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/../helpers/get_config_variables.sh"
-
-FUNCTION_APP="$(cat "${GLOBAL_CONFIG}" | jq -r '.publish_function_app.prod_func_prod_docker.new_function.packapp')"
-
-"$(dirname "${BASH_SOURCE[0]}")/../../func_tests_core/new_functionapp/packapp_test.sh" ${WORKING_DIR}/pfpdnpa ${FUNCTION_APP} func ${PROD_DOCKER_IMAGE}
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/run_all_parallel.sh b/.ci/e2e/publish_tests/test_runners/run_all_parallel.sh
deleted file mode 100644
index 5bf59e6a..00000000
--- a/.ci/e2e/publish_tests/test_runners/run_all_parallel.sh
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/bash
-
-# Get the config file
-source "$(dirname "${BASH_SOURCE[0]}")/helpers/get_config_variables.sh"
-source "$(dirname "${BASH_SOURCE[0]}")/helpers/helper.sh"
-
-mkdir -p ${WORKING_DIR}
-mkdir -p ${TESTS_LOGS}
-
-BASE_DIR="$(dirname "${BASH_SOURCE[0]}")"
-RESET='\033[0m' # No Color
-BLUE='\033[1;34m'
-YELLOW='\033[1;33m'
-
-# This may be needed if docker image is restarted
-# Better to simply login again at every invoke
-echo "Ensuring login to Azure ACR"
-az acr login --name ${ACR_NAME} --output none
-
-echo -e "Starting Parallel execution in background"
-
-
-run_test ${BASE_DIR}/dev_func_dev_docker/customer_build_native_deps.sh ${TESTS_LOGS}/dfddcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddcbnd.result &
-run_test ${BASE_DIR}/dev_func_dev_docker/customer_no_bundler.sh ${TESTS_LOGS}/dfddcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddcnb.result &
-run_test ${BASE_DIR}/dev_func_dev_docker/new_build_native_deps.sh ${TESTS_LOGS}/dfddnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnbnd.result &
-run_test ${BASE_DIR}/dev_func_dev_docker/new_no_bundler.sh ${TESTS_LOGS}/dfddnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnnb.result &
-run_test ${BASE_DIR}/dev_func_dev_docker/new_packapp.sh ${TESTS_LOGS}/dfddnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnpa.result &
-
-run_test ${BASE_DIR}/dev_func_prod_docker/customer_build_native_deps.sh ${TESTS_LOGS}/dfpdcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdcbnd.result &
-run_test ${BASE_DIR}/dev_func_prod_docker/customer_no_bundler.sh ${TESTS_LOGS}/dfpdcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdcnb.result &
-run_test ${BASE_DIR}/dev_func_prod_docker/new_build_native_deps.sh ${TESTS_LOGS}/dfpdnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnbnd.result &
-run_test ${BASE_DIR}/dev_func_prod_docker/new_no_bundler.sh ${TESTS_LOGS}/dfpdnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnnb.result &
-run_test ${BASE_DIR}/dev_func_prod_docker/new_packapp.sh ${TESTS_LOGS}/dfpdnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnpa.result &
-
-run_test ${BASE_DIR}/prod_func_prod_docker/customer_build_native_deps.sh ${TESTS_LOGS}/pfpdcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdcbnd.result &
-run_test ${BASE_DIR}/prod_func_prod_docker/customer_no_bundler.sh ${TESTS_LOGS}/pfpdcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdcnb.result &
-run_test ${BASE_DIR}/prod_func_prod_docker/new_build_native_deps.sh ${TESTS_LOGS}/pfpdnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnbnd.result &
-run_test ${BASE_DIR}/prod_func_prod_docker/new_no_bundler.sh ${TESTS_LOGS}/pfpdnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnnb.result &
-run_test ${BASE_DIR}/prod_func_prod_docker/new_packapp.sh ${TESTS_LOGS}/pfpdnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnpa.result &
-
-run_test ${BASE_DIR}/prod_func_dev_docker/customer_build_native_deps.sh ${TESTS_LOGS}/pfddcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddcbnd.result &
-run_test ${BASE_DIR}/prod_func_dev_docker/customer_no_bundler.sh ${TESTS_LOGS}/pfddcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddcnb.result &
-run_test ${BASE_DIR}/prod_func_dev_docker/new_build_native_deps.sh ${TESTS_LOGS}/pfddnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnbnd.result &
-run_test ${BASE_DIR}/prod_func_dev_docker/new_no_bundler.sh ${TESTS_LOGS}/pfddnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnnb.result &
-run_test ${BASE_DIR}/prod_func_dev_docker/new_packapp.sh ${TESTS_LOGS}/pfddnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnpa.result &
-
-echo "Waiting for tests to complete (this may take several minutes)..."
-wait
-
-echo "Test Completed!"
-yellow "Results-"
-printf "\n"
-
-print_row $(yellow "Version") $(yellow "Exist-Build-Native") \
-$(yellow "Exist-No-Bundler") $(yellow "New-Build-Native") $(yellow "New-No-Bundler") $(yellow "New-Packapp")
-
-print_row_line
-
-print_row $(yellow "dev-func-dev-docker") $(get_result_of ${WORKING_DIR}/dfddcbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfddcnb.result) $(get_result_of ${WORKING_DIR}/dfddnbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfddnnb.result) $(get_result_of ${WORKING_DIR}/dfddnpa.result)
-
-print_row $(yellow "dev-func-dev-docker") $(get_result_of ${WORKING_DIR}/dfpdcbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfpdcnb.result) $(get_result_of ${WORKING_DIR}/dfpdnbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfpdnnb.result) $(get_result_of ${WORKING_DIR}/dfpdnpa.result)
-
-print_row $(yellow "dev-func-dev-docker") $(get_result_of ${WORKING_DIR}/pfddcbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfddcnb.result) $(get_result_of ${WORKING_DIR}/pfddnbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfddnnb.result) $(get_result_of ${WORKING_DIR}/pfddnpa.result)
-
-print_row $(yellow "dev-func-dev-docker") $(get_result_of ${WORKING_DIR}/pfpdcbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfpdcnb.result) $(get_result_of ${WORKING_DIR}/pfpdnbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfpdnnb.result) $(get_result_of ${WORKING_DIR}/pfpdnpa.result)
-
-
-# This is useful when running in a container environment
-printf "\n"
-echo "All logs are available at ${TESTS_LOGS}"
-echo "Sleeping for infinity, in case you need to open bash in the container"
-if [[ ${ENVIRONMENT} = "DOCKER" ]]
-then
-    sleep infinity
-fi
-
-if [[ ${EXIT_ON_FAIL} -ne "FALSE" ]]
-then
-    NUMBER_PASSED=$(grep -l "PASSED" ${WORKING_DIR}/*.result | wc -l)
-    if [[ ${NUMBER_PASSED} -ne 20 ]]
-    then
-        echo "Not all (20) tests passed! Dieing.."
-        exit 1
-    else
-        echo "All tests passed (20/20)!"
-    fi
-fi
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/run_all_serial.sh b/.ci/e2e/publish_tests/test_runners/run_all_serial.sh
deleted file mode 100644
index 7cf852e6..00000000
--- a/.ci/e2e/publish_tests/test_runners/run_all_serial.sh
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/bin/bash
-
-# Get the config file
-source "$(dirname "${BASH_SOURCE[0]}")/helpers/get_config_variables.sh"
-source "$(dirname "${BASH_SOURCE[0]}")/helpers/helper.sh"
-
-mkdir -p ${WORKING_DIR}
-mkdir -p ${TESTS_LOGS}
-
-BASE_DIR="$(dirname "${BASH_SOURCE[0]}")"
-RESET='\033[0m' # No Color
-BLUE='\033[1;34m'
-YELLOW='\033[1;33m'
-
-# This may be needed if docker image is restarted
-# Better to simply login again at every invoke
-echo "Ensuring login to Azure ACR"
-az acr login --name ${ACR_NAME} --output none
-
-echo -e "Starting Serial Execution..."
-echo "This will take a while"
-
-
-run_test ${BASE_DIR}/dev_func_dev_docker/customer_build_native_deps.sh ${TESTS_LOGS}/dfddcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddcbnd.result
-run_test ${BASE_DIR}/dev_func_dev_docker/customer_no_bundler.sh ${TESTS_LOGS}/dfddcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddcnb.result
-run_test ${BASE_DIR}/dev_func_dev_docker/new_build_native_deps.sh ${TESTS_LOGS}/dfddnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnbnd.result
-run_test ${BASE_DIR}/dev_func_dev_docker/new_no_bundler.sh ${TESTS_LOGS}/dfddnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnnb.result
-run_test ${BASE_DIR}/dev_func_dev_docker/new_packapp.sh ${TESTS_LOGS}/dfddnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfddnpa.result
-
-run_test ${BASE_DIR}/dev_func_prod_docker/customer_build_native_deps.sh ${TESTS_LOGS}/dfpdcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdcbnd.result
-run_test ${BASE_DIR}/dev_func_prod_docker/customer_no_bundler.sh ${TESTS_LOGS}/dfpdcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdcnb.result
-run_test ${BASE_DIR}/dev_func_prod_docker/new_build_native_deps.sh ${TESTS_LOGS}/dfpdnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnbnd.result
-run_test ${BASE_DIR}/dev_func_prod_docker/new_no_bundler.sh ${TESTS_LOGS}/dfpdnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnnb.result
-run_test ${BASE_DIR}/dev_func_prod_docker/new_packapp.sh ${TESTS_LOGS}/dfpdnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/dfpdnpa.result
-
-run_test ${BASE_DIR}/prod_func_prod_docker/customer_build_native_deps.sh ${TESTS_LOGS}/pfpdcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdcbnd.result
-run_test ${BASE_DIR}/prod_func_prod_docker/customer_no_bundler.sh ${TESTS_LOGS}/pfpdcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdcnb.result
-run_test ${BASE_DIR}/prod_func_prod_docker/new_build_native_deps.sh ${TESTS_LOGS}/pfpdnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnbnd.result
-run_test ${BASE_DIR}/prod_func_prod_docker/new_no_bundler.sh ${TESTS_LOGS}/pfpdnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnnb.result
-run_test ${BASE_DIR}/prod_func_prod_docker/new_packapp.sh ${TESTS_LOGS}/pfpdnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfpdnpa.result
-
-echo "Ensuring login to Azure ACR (again because login has been flaky)"
-az acr login --name ${ACR_NAME} --output none
-run_test ${BASE_DIR}/prod_func_dev_docker/customer_build_native_deps.sh ${TESTS_LOGS}/pfddcbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddcbnd.result
-run_test ${BASE_DIR}/prod_func_dev_docker/customer_no_bundler.sh ${TESTS_LOGS}/pfddcnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddcnb.result
-run_test ${BASE_DIR}/prod_func_dev_docker/new_build_native_deps.sh ${TESTS_LOGS}/pfddnbnd.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnbnd.result
-run_test ${BASE_DIR}/prod_func_dev_docker/new_no_bundler.sh ${TESTS_LOGS}/pfddnnb.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnnb.result
-run_test ${BASE_DIR}/prod_func_dev_docker/new_packapp.sh ${TESTS_LOGS}/pfddnpa.log ${TESTS_TIMEOUT} ${WORKING_DIR}/pfddnpa.result
-
-echo "Test Completed!"
-yellow "Results-"
-printf "\n"
-
-print_row $(yellow "Version") $(yellow "Exist-Build-Native") \
-$(yellow "Exist-No-Bundler") $(yellow "New-Build-Native") $(yellow "New-No-Bundler") $(yellow "New-Packapp")
-
-print_row_line
-
-print_row $(yellow "dev-func-dev-docker") $(get_result_of ${WORKING_DIR}/dfddcbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfddcnb.result) $(get_result_of ${WORKING_DIR}/dfddnbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfddnnb.result) $(get_result_of ${WORKING_DIR}/dfddnpa.result)
-
-print_row $(yellow "dev-func-prod-docker") $(get_result_of ${WORKING_DIR}/dfpdcbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfpdcnb.result) $(get_result_of ${WORKING_DIR}/dfpdnbnd.result) \
-$(get_result_of ${WORKING_DIR}/dfpdnnb.result) $(get_result_of ${WORKING_DIR}/dfpdnpa.result)
-
-print_row $(yellow "prod-func-dev-docker") $(get_result_of ${WORKING_DIR}/pfddcbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfddcnb.result) $(get_result_of ${WORKING_DIR}/pfddnbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfddnnb.result) $(get_result_of ${WORKING_DIR}/pfddnpa.result)
-
-print_row $(yellow "prod-func-prod-docker") $(get_result_of ${WORKING_DIR}/pfpdcbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfpdcnb.result) $(get_result_of ${WORKING_DIR}/pfpdnbnd.result) \
-$(get_result_of ${WORKING_DIR}/pfpdnnb.result) $(get_result_of ${WORKING_DIR}/pfpdnpa.result)
-
-printf "\n"
-echo "All logs are available at ${TESTS_LOGS}"
-
-if [[ ${ENVIRONMENT} = "DOCKER" ]]
-then
-    # This is useful when running in a container environment
-    echo "Sleeping for infinity, in case you need to open bash in the container"
-    sleep infinity
-fi
-
-if [[ -z ${EXIT_ON_FAIL} ]] || [[ ${EXIT_ON_FAIL} -ne "FALSE" ]]
-then
-    NUMBER_PASSED=$(grep -l "PASSED" ${WORKING_DIR}/*.result | wc -l)
-    if [[ ${NUMBER_PASSED} -ne 20 ]]
-    then
-        echo "Not all (20) tests passed! Dieing.."
-        exit 1
-    else
-        echo "All tests passed (20/20)!"
-    fi
-fi
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/setup_container_environment.sh b/.ci/e2e/publish_tests/test_runners/setup_container_environment.sh
deleted file mode 100644
index ed931035..00000000
--- a/.ci/e2e/publish_tests/test_runners/setup_container_environment.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-apt-get update
-apt-get install azure-functions-core-tools jq git unzip gettext -y
-curl -sSL https://get.docker.com/ | sh
-
-# Install azure CLI
-apt-get install apt-transport-https lsb-release software-properties-common dirmngr -y
-AZ_REPO=$(lsb_release -cs)
-echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list
-apt-key --keyring /etc/apt/trusted.gpg.d/Microsoft.gpg adv --keyserver packages.microsoft.com --recv-keys BC528686B50D79E339D3721CEB3E94ADBE1229CF
-apt-get update
-apt-get install azure-cli -y
\ No newline at end of file
diff --git a/.ci/e2e/publish_tests/test_runners/setup_test_environment.sh b/.ci/e2e/publish_tests/test_runners/setup_test_environment.sh
deleted file mode 100644
index d884b0ee..00000000
--- a/.ci/e2e/publish_tests/test_runners/setup_test_environment.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-# Get the configuration variables
-source "$(dirname "${BASH_SOURCE[0]}")/helpers/get_config_variables.sh"
-
-# Login to the Service Principal Azure Account
-az login --service-principal -u ${SP_USER_NAME} -p ${SP_PASSWORD} --tenant ${SP_TENANT} --output none
-
-# Update the ACR Docker Image with the dev branch of Docker image and python worker
-chmod a+x $(dirname "${BASH_SOURCE[0]}")/../dev_docker_setup/setup.sh
-$(dirname "${BASH_SOURCE[0]}")/../dev_docker_setup/setup.sh ${ACR_NAME} ${DEV_IMAGE_NAME} ${DOCKER_WORKING_DIR}
-
-# Setup the dev func executables
-chmod a+x $(dirname "${BASH_SOURCE[0]}")/../dev_func_setup/setup.sh
-$(dirname "${BASH_SOURCE[0]}")/../dev_func_setup/setup.sh ${FUNC_DEV_DIR} ${FUNC_DEV_URL}
\ No newline at end of file
diff --git a/.ci/e2e/running-environments/Docker/start_tests_docker.sh b/.ci/e2e/running-environments/Docker/start_tests_docker.sh
deleted file mode 100644
index b2c7ff21..00000000
--- a/.ci/e2e/running-environments/Docker/start_tests_docker.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-# This needs to happen after the docker container is built. This is because the setup uses Docker deamon
-# And the /var/run/docker.sock needs to be mounted for the setup script to use Docker.
-# This is done when the Docker container is run.
-/azure-functions-python-worker/.ci/e2e/publish_tests/test_runners/setup_test_environment.sh
-
-/azure-functions-python-worker/.ci/e2e/publish_tests/test_runners/run_all_serial.sh
\ No newline at end of file
diff --git a/.ci/e2e/running-environments/Docker/test_runner.Dockerfile b/.ci/e2e/running-environments/Docker/test_runner.Dockerfile
deleted file mode 100644
index d39cb4b5..00000000
--- a/.ci/e2e/running-environments/Docker/test_runner.Dockerfile
+++ /dev/null
@@ -1,28 +0,0 @@
-# When running, make sure to mount Docker sock and use the python-worker directory as the base dir
-# Example-
-# docker build -f .ci\e2e\running-environments\Docker\test_runner.Dockerfile -t my-test-image <path-to-python-worker>
-# docker run -v /var/run/docker.sock:/var/run/docker.sock my-test-image
-
-FROM mcr.microsoft.com/azure-functions/python:2.0
-
-COPY . /azure-functions-python-worker
-
-RUN apt-get update && \
-    apt-get install azure-functions-core-tools jq git unzip dos2unix -y
-
-# Install docker amd azure CLI
-RUN curl -sSL https://get.docker.com/ | sh && \
-    apt-get update && \
-    apt-get install apt-transport-https lsb-release software-properties-common dirmngr -y && \
-    AZ_REPO=$(lsb_release -cs) && \
-    echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | tee /etc/apt/sources.list.d/azure-cli.list && \
-    apt-key --keyring /etc/apt/trusted.gpg.d/Microsoft.gpg adv --keyserver packages.microsoft.com --recv-keys BC528686B50D79E339D3721CEB3E94ADBE1229CF && \
-    apt-get update && \
-    apt-get install azure-cli -y
-
-ENV ENVIRONMENT=DOCKER
-ENV EXIT_ON_FAIL=FALSE
-
-RUN find /azure-functions-python-worker/.ci/e2e -type f -print0 | xargs -0 dos2unix
-
-CMD [ "bash", "/azure-functions-python-worker/.ci/e2e/running-environments/Docker/start_tests_docker.sh" ]
\ No newline at end of file
diff --git a/.ci/e2e/setup-e2e.ps1 b/.ci/e2e/setup-e2e.ps1
deleted file mode 100644
index db7fa01b..00000000
--- a/.ci/e2e/setup-e2e.ps1
+++ /dev/null
@@ -1,25 +0,0 @@
-Write-Host "Downloading Functions Core Tools...."
-Invoke-RestMethod -Uri 'https://functionsclibuilds.blob.core.windows.net/builds/2/latest/version.txt' -OutFile version.txt
-Write-Host "Using Functions Core Tools version: $(Get-Content -Raw version.txt)"
-Remove-Item version.txt
-
-$currDir = Get-Location
-$output = "$currDir\Azure.Functions.Cli"
-
-
-if (-not (Test-Path env:CORE_TOOLS_URL)) 
-{ 
-    $env:CORE_TOOLS_URL = "https://functionsclibuilds.blob.core.windows.net/builds/2/latest/Azure.Functions.Cli.win-x86.zip"
-}
-
-if (Test-Path env:CORE_TOOLS_EXE_PATH)
-{
-    $output = Split-Path $env:CORE_TOOLS_EXE_PATH
-}
-
-Write-Host "CORE_TOOLS_URL: $env:CORE_TOOLS_URL"
-$wc = New-Object System.Net.WebClient
-$wc.DownloadFile($env:CORE_TOOLS_URL, "$output.zip")
-
-Write-Host "Extracting Functions Core Tools...."
-Expand-Archive "$output.zip" -DestinationPath "$output"
\ No newline at end of file
diff --git a/.ci/e2e_integration_test/pipeline.yml b/.ci/e2e_integration_test/pipeline.yml
new file mode 100644
index 00000000..e29e4315
--- /dev/null
+++ b/.ci/e2e_integration_test/pipeline.yml
@@ -0,0 +1,36 @@
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License.
+
+# E2E Integration Test Pipeline
+
+pr: none
+trigger: none
+
+pool:
+    vmImage: 'ubuntu-latest'
+
+variables:
+    DOTNET_VERSION: '3.1.405'
+    PYTHON_VERSION: '3.8'
+
+steps:
+- task: UsePythonVersion@0
+  displayName: 'Install Python'
+  inputs:
+    versionSpec: $(PYTHON_VERSION)
+    addToPath: true
+- task: UseDotNet@2
+  displayName: 'Install DotNet'
+  inputs:
+    packageType: 'sdk'
+    version: $(DOTNET_VERSION)
+- pwsh: '$(Build.SourcesDirectory)/.ci/e2e_integration_test/start-e2e.ps1'
+  env:
+    AzureWebJobsStorage: $(AzureWebJobsStorage)
+    AzureWebJobsCosmosDBConnectionString: $(AzureWebJobsCosmosDBConnectionString)
+    AzureWebJobsEventHubConnectionString: $(AzureWebJobsEventHubConnectionString)
+    AzureWebJobsServiceBusConnectionString: $(AzureWebJobsServiceBusConnectionString)
+    AzureWebJobPythonVersionsEventGridTopicUri: $(AzureWebJobsEventGridTopicUri)
+    AzureWebJobsEventGridConnectionKey: $(AzureWebJobsEventGridConnectionKey)
+    PythonVersion: $(PYTHON_VERSION)
+  displayName: 'Running Python Language Worker E2E Tests'
diff --git a/.ci/e2e_integration_test/start-e2e.ps1 b/.ci/e2e_integration_test/start-e2e.ps1
new file mode 100644
index 00000000..409e42a4
--- /dev/null
+++ b/.ci/e2e_integration_test/start-e2e.ps1
@@ -0,0 +1,98 @@
+#
+# Copyright (c) Microsoft. All rights reserved.
+# Licensed under the MIT license. See LICENSE file in the project root for full license information.
+#
+
+# Python worker E2E integration test
+# The E2E integration test will test the worker against a prerelease version of core tools
+$FUNC_RUNTIME_VERSION = '3'
+$FUNC_RUNTIME_LANGUAGE = 'python'
+$AZURE_FUNCTIONS_ENVIRONMENT = "development"
+$PYAZURE_WEBHOST_DEBUG = "true"
+$PYAZURE_INTEGRATION_TEST = "true"
+
+# Speed up Invoke-RestMethod by turning off progress bar
+$ProgressPreference = 'SilentlyContinue'
+
+function get_architecture() {
+    # Return "x64" or "x86"
+    return [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant();
+}
+
+function get_os() {
+    # Return either "win", "linux", "osx", or "unknown"
+    if ($IsWindows) {
+        return "win"
+    } elseif ($IsLinux) {
+        return "linux"
+    } elseif ($IsMacOS) {
+        return "osx"
+    }
+    return "unknown"
+}
+
+function get_core_tool_download_url() {
+    $os = get_os
+    $arch = get_architecture
+    return "https://functionsintegclibuilds.blob.core.windows.net/builds/$FUNC_RUNTIME_VERSION/latest/Azure.Functions.Cli.$os-$arch.zip"
+}
+
+function get_core_tools_version_url() {
+    return "https://functionsintegclibuilds.blob.core.windows.net/builds/$FUNC_RUNTIME_VERSION/latest/version.txt"
+}
+
+function get_func_execuable_path($path) {
+    $exe_name = "func"
+    if ($IsWindows) {
+        $exe_name = "func.exe"
+    }
+    return Join-Path $path $exe_name
+}
+
+$FUNC_CLI_DIRECTORY = Join-Path $PSScriptRoot 'Azure.Functions.Cli'
+$FUNC_CLI_DIRECTORY_EXIST = Test-Path -Path $FUNC_CLI_DIRECTORY -PathType Container
+if ($FUNC_CLI_DIRECTORY_EXIST) {
+    Write-Host 'Deleting Functions Core Tools...'
+    Remove-Item -Force "$FUNC_CLI_DIRECTORY.zip" -ErrorAction Ignore
+    Remove-Item -Recurse -Force $FUNC_CLI_DIRECTORY -ErrorAction Ignore
+}
+
+$version = Invoke-RestMethod -Uri "$(get_core_tools_version_url)"
+Write-Host "Downloading Functions Core Tools $version..."
+
+$output = "$FUNC_CLI_DIRECTORY.zip"
+Invoke-RestMethod -Uri "$(get_core_tool_download_url)" -OutFile $output
+
+Write-Host 'Extracting Functions Core Tools...'
+Expand-Archive $output -DestinationPath $FUNC_CLI_DIRECTORY
+
+Write-Host "Starting Functions Host..."
+$env:FUNCTIONS_WORKER_RUNTIME = $FUNC_RUNTIME_LANGUAGE
+$env:FUNCTIONS_WORKER_RUNTIME_VERSION = $env:PythonVersion
+$env:AZURE_FUNCTIONS_ENVIRONMENT = $AZURE_FUNCTIONS_ENVIRONMENT
+$env:PYAZURE_WEBHOST_DEBUG = $PYAZURE_WEBHOST_DEBUG
+$env:PYAZURE_INTEGRATION_TEST = $PYAZURE_INTEGRATION_TEST
+
+$env:Path = "$env:Path$([System.IO.Path]::PathSeparator)$FUNC_CLI_DIRECTORY"
+$funcExePath = $(get_func_execuable_path $FUNC_CLI_DIRECTORY)
+
+if ($IsMacOS -or $IsLinux) {
+    chmod -R 755 $FUNC_CLI_DIRECTORY
+}
+Write-Host "Function Exe Path: $funcExePath"
+
+Set-Location $env:BUILD_SOURCESDIRECTORY
+Write-Host "Set-Location: $env:BUILD_SOURCESDIRECTORY"
+
+Write-Host "Preparing E2E integration tests..." -ForegroundColor Green
+Write-Host "-----------------------------------------------------------------------------`n" -ForegroundColor Green
+pip install -e .[dev]
+python setup.py build
+python setup.py extension
+Write-Host "-----------------------------------------------------------------------------`n" -ForegroundColor Green
+
+Write-Host "Running E2E integration tests..." -ForegroundColor Green
+Write-Host "-----------------------------------------------------------------------------`n" -ForegroundColor Green
+$env:CORE_TOOLS_EXE_PATH = "$funcExePath"
+pytest --instafail --cov=./azure_functions_worker --cov-report xml --cov-branch --cov-append tests/endtoend
+Write-Host "-----------------------------------------------------------------------------`n" -ForegroundColor Green
\ No newline at end of file
diff --git a/.github/workflows/ci_e2e_workflow.yml b/.github/workflows/ci_e2e_workflow.yml
index 1f4a5a76..d8af1488 100644
--- a/.github/workflows/ci_e2e_workflow.yml
+++ b/.github/workflows/ci_e2e_workflow.yml
@@ -41,6 +41,7 @@ jobs:
           python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple -U azure-functions --pre
           python setup.py build
           python setup.py webhost
+          python setup.py extension
       - name: Running 3.6 Tests
         if: matrix.python-version == 3.6
         env:
diff --git a/.github/workflows/perf-testing-setup.yml b/.github/workflows/perf-testing-setup.yml
index bcdce299..37250c56 100644
--- a/.github/workflows/perf-testing-setup.yml
+++ b/.github/workflows/perf-testing-setup.yml
@@ -40,6 +40,7 @@ jobs:
         python -m pip install -q --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple -U azure-functions --pre
         python setup.py build
         python setup.py webhost
+        python setup.py extension
     - name: Build and Run the Docker image
       run: |
         docker build --build-arg PYTHON_VERSION=${{ env.PYTHON_VERSION }} --file .ci/perf_tests/dockerfiles/perf_tests.Dockerfile --tag perfimage:latest .
diff --git a/azure_functions_worker/testutils.py b/azure_functions_worker/testutils.py
index 3951bee4..7b762f17 100644
--- a/azure_functions_worker/testutils.py
+++ b/azure_functions_worker/testutils.py
@@ -35,7 +35,11 @@
 from azure_functions_worker._thirdparty import aio_compat
 from . import dispatcher
 from . import protos
-from .constants import PYAZURE_WEBHOST_DEBUG
+from .constants import (
+    PYAZURE_WEBHOST_DEBUG,
+    PYAZURE_WORKER_DIR,
+    PYAZURE_INTEGRATION_TEST
+)
 from .utils.common import is_envvar_true
 
 PROJECT_ROOT = pathlib.Path(__file__).parent.parent
@@ -654,10 +658,13 @@ def popen_webhost(*, stdout, stderr, script_root=FUNCS_PATH, port=None):
             '      dll = /path/Microsoft.Azure.WebJobs.Script.WebHost.dll',
             ' * or download Azure Functions Core Tools binaries and',
             '   then write the full path to func.exe into the ',
-            '   `CORE_TOOLS_PATH` envrionment variable.'
+            '   `CORE_TOOLS_EXE_PATH` envrionment variable.',
+            '',
+            'Setting "export PYAZURE_WEBHOST_DEBUG=true" to get the full',
+            'stdout and stderr from function host.'
         ]))
 
-    worker_path = os.environ.get('PYAZURE_WORKER_DIR')
+    worker_path = os.environ.get(PYAZURE_WORKER_DIR)
     worker_path = WORKER_PATH if not worker_path else pathlib.Path(worker_path)
     if not worker_path.exists():
         raise RuntimeError(f'Worker path {worker_path} does not exist')
@@ -672,6 +679,11 @@ def popen_webhost(*, stdout, stderr, script_root=FUNCS_PATH, port=None):
         'AzureWebJobsSecretStorageType': 'files'
     }
 
+    # In E2E Integration mode, we should use the core tools worker
+    # from the latest artifact instead of the azure_functions_worker module
+    if is_envvar_true(PYAZURE_INTEGRATION_TEST):
+        extra_env.pop('languageWorkers:python:workerDirectory')
+
     if testconfig and 'azure' in testconfig:
         st = testconfig['azure'].get('storage_key')
         if st:
diff --git a/tests/endtoend/test_eventgrid_functions.py b/tests/endtoend/test_eventgrid_functions.py
index de2ed8f4..957185b8 100644
--- a/tests/endtoend/test_eventgrid_functions.py
+++ b/tests/endtoend/test_eventgrid_functions.py
@@ -92,7 +92,7 @@ def test_eventgrid_trigger(self):
             else:
                 break
 
-    @testutils.retryable_test(1, 5)
+    @testutils.retryable_test(3, 5)
     def test_eventgrid_output_binding(self):
         """test event_grid output binding