Skip to content

Commit f46838f

Browse files
committed
Fixed TASK - 3461, 3561, 3562 and 3563
## Dev Board Ticket - https://dev.azure.com/TDEI-UW/TDEI/_workitems/edit/3461/ - https://dev.azure.com/TDEI-UW/TDEI/_workitems/edit/3561/ - https://dev.azure.com/TDEI-UW/TDEI/_workitems/edit/3562/ - https://dev.azure.com/TDEI-UW/TDEI/_workitems/edit/3563/ ## Changes - Fixed large GeoJSON output packaging to prevent empty zip creation by using robust zip creation/validation (Zip64-enabled, file-entry checks, and empty-archive guards). - Fixed queue processing reliability by aligning subscription/shutdown lifecycle with osw-validation and stabilizing callback execution in this runtime to avoid callback worker exits. - Improved service success/failure handling and status publishing so failures in processing/upload are correctly reported, with safer upload validation and clearer operational logging. - Updated README with actual production use cases, current request/response contract, and lifecycle behavior. - Expanded and aligned unit tests (service/helper/main) and CI test workflow updates, raising coverage to the target range. ## Testing - Unit test suite (`python -m unittest discover -s tests`) - Coverage (`python -m coverage run --source=src -m unittest discover -s tests`, `coverage report`) - Runtime validation with real queue messages and storage upload flow in local environment
1 parent d1de630 commit f46838f

15 files changed

Lines changed: 779 additions & 135 deletions
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
# Dev Workflow – build image and deploy to Azure Function App (Development environment).
3+
#
4+
# Required secrets (Settings → Environments → Development → Environment secrets):
5+
# - REGISTRY_DOMAIN – Azure Container Registry login server (e.g. myregistry.azurecr.io)
6+
# - REGISTRY_USERNAME – ACR username
7+
# - REGISTRY_PASSWORD – ACR password
8+
# - REGISTRY_REPO – Repository name in ACR for this app
9+
# - TDEI_CORE_AZURE_CREDS – Azure service principal JSON (for az login)
10+
#
11+
# Required variables (Settings → Environments → Development → Environment variables):
12+
# - FUNCTION_APP_NAME – Azure Function App name to deploy to
13+
# - RESOURCE_GROUP – Azure resource group containing the Function App
14+
#
15+
# Optional variables (defaults used if not set):
16+
# - RESTART_APP – Set to 'true' or 'false'; default 'true'
17+
# - APP_SETTINGS_JSON – JSON object of extra app settings to apply; default '{}'
18+
#
19+
######### Dev Workflow ########
20+
on:
21+
pull_request:
22+
branches: [dev]
23+
types:
24+
- closed
25+
workflow_dispatch:
26+
27+
permissions:
28+
id-token: write
29+
contents: read
30+
31+
jobs:
32+
Build:
33+
environment: Development
34+
runs-on: ubuntu-latest
35+
if: github.event.pull_request.merged == true
36+
steps:
37+
- uses: actions/checkout@v2
38+
- uses: azure/docker-login@v1
39+
with:
40+
login-server: ${{ secrets.REGISTRY_DOMAIN }}
41+
username: ${{ secrets.REGISTRY_USERNAME }}
42+
password: ${{ secrets.REGISTRY_PASSWORD }}
43+
- name: Publish image to Azure Registry
44+
run: |
45+
docker build -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }} -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.ref_name == 'main' && 'prod' || github.ref_name }}${{ github.ref_name != 'main' && '-latest' || 'latest' }} .
46+
docker push ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }} --all-tags
47+
deploy:
48+
environment: Development
49+
runs-on: ubuntu-latest
50+
needs: [Build]
51+
permissions:
52+
contents: read
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Login to Azure
57+
uses: azure/login@v2.0.0
58+
with:
59+
creds: ${{ secrets.TDEI_CORE_AZURE_CREDS }}
60+
61+
- name: Resolve deploy config from environment
62+
id: deploy_config
63+
run: |
64+
echo "function_app_name=${{ vars.FUNCTION_APP_NAME }}" >> "$GITHUB_OUTPUT"
65+
echo "resource_group=${{ vars.RESOURCE_GROUP }}" >> "$GITHUB_OUTPUT"
66+
echo "aci_image=${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }}" >> "$GITHUB_OUTPUT"
67+
echo "restart_app=${{ vars.RESTART_APP || 'true' }}" >> "$GITHUB_OUTPUT"
68+
69+
- name: Log target environment
70+
shell: bash
71+
run: |
72+
echo "Deploying to:"
73+
echo " Function App: ${{ steps.deploy_config.outputs.function_app_name }}"
74+
echo " Resource Group: ${{ steps.deploy_config.outputs.resource_group }}"
75+
echo " ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}"
76+
77+
- name: Update app settings (ACI_IMAGE + extras)
78+
shell: bash
79+
run: |
80+
python - <<'PY'
81+
import json
82+
import os
83+
app_settings = os.environ.get("APP_SETTINGS_JSON", "{}")
84+
data = json.loads(app_settings) if app_settings else {}
85+
data["ACI_IMAGE"] = os.environ["ACI_IMAGE"]
86+
with open("/tmp/appsettings.txt", "w", encoding="utf-8") as handle:
87+
for key, value in data.items():
88+
handle.write(f"{key}={value}\n")
89+
PY
90+
echo "Updating only provided settings (no clearing of others)."
91+
az functionapp config appsettings set \
92+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
93+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}" \
94+
--settings $(cat /tmp/appsettings.txt | tr '\n' ' ')
95+
env:
96+
ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}
97+
APP_SETTINGS_JSON: ${{ vars.APP_SETTINGS_JSON || '{}' }}
98+
99+
- name: Restart function app
100+
if: ${{ steps.deploy_config.outputs.restart_app == 'true' }}
101+
shell: bash
102+
run: |
103+
az functionapp restart \
104+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
105+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}"
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
# Prod Workflow – build image and deploy to Azure Function App (Production environment).
3+
#
4+
# Required secrets (Settings → Environments → Production → Environment secrets):
5+
# - REGISTRY_DOMAIN – Azure Container Registry login server (e.g. myregistry.azurecr.io)
6+
# - REGISTRY_USERNAME – ACR username
7+
# - REGISTRY_PASSWORD – ACR password
8+
# - REGISTRY_REPO – Repository name in ACR for this app
9+
# - TDEI_CORE_AZURE_CREDS – Azure service principal JSON (for az login)
10+
#
11+
# Required variables (Settings → Environments → Production → Environment variables):
12+
# - FUNCTION_APP_NAME – Azure Function App name to deploy to
13+
# - RESOURCE_GROUP – Azure resource group containing the Function App
14+
#
15+
# Optional variables (defaults used if not set):
16+
# - RESTART_APP – Set to 'true' or 'false'; default 'true'
17+
# - APP_SETTINGS_JSON – JSON object of extra app settings to apply; default '{}'
18+
#
19+
######### Prod Workflow ########
20+
on:
21+
pull_request:
22+
branches: [main]
23+
types:
24+
- closed
25+
workflow_dispatch:
26+
27+
permissions:
28+
id-token: write
29+
contents: read
30+
31+
jobs:
32+
Build:
33+
environment: Production
34+
runs-on: ubuntu-latest
35+
if: github.event.pull_request.merged == true
36+
steps:
37+
- uses: actions/checkout@v2
38+
- uses: azure/docker-login@v1
39+
with:
40+
login-server: ${{ secrets.REGISTRY_DOMAIN }}
41+
username: ${{ secrets.REGISTRY_USERNAME }}
42+
password: ${{ secrets.REGISTRY_PASSWORD }}
43+
- name: Publish image to Azure Registry
44+
run: |
45+
docker build -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }} -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.ref_name == 'main' && 'prod' || github.ref_name }}${{ github.ref_name != 'main' && '-latest' || 'latest' }} .
46+
docker push ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }} --all-tags
47+
deploy:
48+
environment: Production
49+
runs-on: ubuntu-latest
50+
needs: [Build]
51+
permissions:
52+
contents: read
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Login to Azure
57+
uses: azure/login@v2.0.0
58+
with:
59+
creds: ${{ secrets.TDEI_CORE_AZURE_CREDS }}
60+
61+
- name: Resolve deploy config from environment
62+
id: deploy_config
63+
run: |
64+
echo "function_app_name=${{ vars.FUNCTION_APP_NAME }}" >> "$GITHUB_OUTPUT"
65+
echo "resource_group=${{ vars.RESOURCE_GROUP }}" >> "$GITHUB_OUTPUT"
66+
echo "aci_image=${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }}" >> "$GITHUB_OUTPUT"
67+
echo "restart_app=${{ vars.RESTART_APP || 'true' }}" >> "$GITHUB_OUTPUT"
68+
69+
- name: Log target environment
70+
shell: bash
71+
run: |
72+
echo "Deploying to:"
73+
echo " Function App: ${{ steps.deploy_config.outputs.function_app_name }}"
74+
echo " Resource Group: ${{ steps.deploy_config.outputs.resource_group }}"
75+
echo " ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}"
76+
77+
- name: Update app settings (ACI_IMAGE + extras)
78+
shell: bash
79+
run: |
80+
python - <<'PY'
81+
import json
82+
import os
83+
app_settings = os.environ.get("APP_SETTINGS_JSON", "{}")
84+
data = json.loads(app_settings) if app_settings else {}
85+
data["ACI_IMAGE"] = os.environ["ACI_IMAGE"]
86+
with open("/tmp/appsettings.txt", "w", encoding="utf-8") as handle:
87+
for key, value in data.items():
88+
handle.write(f"{key}={value}\n")
89+
PY
90+
echo "Updating only provided settings (no clearing of others)."
91+
az functionapp config appsettings set \
92+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
93+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}" \
94+
--settings $(cat /tmp/appsettings.txt | tr '\n' ' ')
95+
env:
96+
ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}
97+
APP_SETTINGS_JSON: ${{ vars.APP_SETTINGS_JSON || '{}' }}
98+
99+
- name: Restart function app
100+
if: ${{ steps.deploy_config.outputs.restart_app == 'true' }}
101+
shell: bash
102+
run: |
103+
az functionapp restart \
104+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
105+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}"
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
# Stage Workflow – build image and deploy to Azure Function App (Stage environment).
3+
#
4+
# Required secrets (Settings → Environments → Stage → Environment secrets):
5+
# - REGISTRY_DOMAIN – Azure Container Registry login server (e.g. myregistry.azurecr.io)
6+
# - REGISTRY_USERNAME – ACR username
7+
# - REGISTRY_PASSWORD – ACR password
8+
# - REGISTRY_REPO – Repository name in ACR for this app
9+
# - TDEI_CORE_AZURE_CREDS – Azure service principal JSON (for az login)
10+
#
11+
# Required variables (Settings → Environments → Stage → Environment variables):
12+
# - FUNCTION_APP_NAME – Azure Function App name to deploy to
13+
# - RESOURCE_GROUP – Azure resource group containing the Function App
14+
#
15+
# Optional variables (defaults used if not set):
16+
# - RESTART_APP – Set to 'true' or 'false'; default 'true'
17+
# - APP_SETTINGS_JSON – JSON object of extra app settings to apply; default '{}'
18+
#
19+
######### Stage Workflow ########
20+
on:
21+
pull_request:
22+
branches: [stage]
23+
types:
24+
- closed
25+
workflow_dispatch:
26+
27+
permissions:
28+
id-token: write
29+
contents: read
30+
31+
jobs:
32+
Build:
33+
environment: Stage
34+
runs-on: ubuntu-latest
35+
if: github.event.pull_request.merged == true
36+
steps:
37+
- uses: actions/checkout@v2
38+
- uses: azure/docker-login@v1
39+
with:
40+
login-server: ${{ secrets.REGISTRY_DOMAIN }}
41+
username: ${{ secrets.REGISTRY_USERNAME }}
42+
password: ${{ secrets.REGISTRY_PASSWORD }}
43+
- name: Publish image to Azure Registry
44+
run: |
45+
docker build -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }} -t ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.ref_name == 'main' && 'prod' || github.ref_name }}${{ github.ref_name != 'main' && '-latest' || 'latest' }} .
46+
docker push ${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }} --all-tags
47+
deploy:
48+
environment: Stage
49+
runs-on: ubuntu-latest
50+
needs: [Build]
51+
permissions:
52+
contents: read
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Login to Azure
57+
uses: azure/login@v2.0.0
58+
with:
59+
creds: ${{ secrets.TDEI_CORE_AZURE_CREDS }}
60+
61+
- name: Resolve deploy config from environment
62+
id: deploy_config
63+
run: |
64+
echo "function_app_name=${{ vars.FUNCTION_APP_NAME }}" >> "$GITHUB_OUTPUT"
65+
echo "resource_group=${{ vars.RESOURCE_GROUP }}" >> "$GITHUB_OUTPUT"
66+
echo "aci_image=${{ secrets.REGISTRY_DOMAIN }}/${{ secrets.REGISTRY_REPO }}:${{ github.sha }}" >> "$GITHUB_OUTPUT"
67+
echo "restart_app=${{ vars.RESTART_APP || 'true' }}" >> "$GITHUB_OUTPUT"
68+
69+
- name: Log target environment
70+
shell: bash
71+
run: |
72+
echo "Deploying to:"
73+
echo " Function App: ${{ steps.deploy_config.outputs.function_app_name }}"
74+
echo " Resource Group: ${{ steps.deploy_config.outputs.resource_group }}"
75+
echo " ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}"
76+
77+
- name: Update app settings (ACI_IMAGE + extras)
78+
shell: bash
79+
run: |
80+
python - <<'PY'
81+
import json
82+
import os
83+
app_settings = os.environ.get("APP_SETTINGS_JSON", "{}")
84+
data = json.loads(app_settings) if app_settings else {}
85+
data["ACI_IMAGE"] = os.environ["ACI_IMAGE"]
86+
with open("/tmp/appsettings.txt", "w", encoding="utf-8") as handle:
87+
for key, value in data.items():
88+
handle.write(f"{key}={value}\n")
89+
PY
90+
echo "Updating only provided settings (no clearing of others)."
91+
az functionapp config appsettings set \
92+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
93+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}" \
94+
--settings $(cat /tmp/appsettings.txt | tr '\n' ' ')
95+
env:
96+
ACI_IMAGE: ${{ steps.deploy_config.outputs.aci_image }}
97+
APP_SETTINGS_JSON: ${{ vars.APP_SETTINGS_JSON || '{}' }}
98+
99+
- name: Restart function app
100+
if: ${{ steps.deploy_config.outputs.restart_app == 'true' }}
101+
shell: bash
102+
run: |
103+
az functionapp restart \
104+
--name "${{ steps.deploy_config.outputs.function_app_name }}" \
105+
--resource-group "${{ steps.deploy_config.outputs.resource_group }}"

.github/workflows/unit_tests.yml

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,28 @@ jobs:
4747
exit 1
4848
fi
4949
50-
- name: Run tests with coverage
50+
- name: Run tests with coverage (show failures in logs)
51+
shell: bash
5152
run: |
52-
timestamp=$(date '+%Y-%m-%d_%H-%M-%S')
53+
set -o pipefail
54+
timestamp="$(date '+%Y-%m-%d_%H-%M-%S')"
5355
mkdir -p test_results
5456
log_file="test_results/${timestamp}_report.log"
55-
echo -e "\nTest Cases Report Report\n" >> $log_file
56-
# Run the tests and append output to the log file
57-
python -m coverage run --source=src -m unittest discover -s tests >> $log_file 2>&1
58-
echo -e "\nCoverage Report\n" >> $log_file
59-
coverage report >> $log_file
57+
58+
{
59+
echo
60+
echo "Test Cases Report"
61+
echo
62+
} | tee -a "$log_file"
63+
64+
# Run unittest in verbose mode; mirror output to console and file
65+
python -m coverage run --source=src -m unittest discover -s tests/unit_tests -v 2>&1 | tee -a "$log_file"
66+
test_status=${PIPESTATUS[0]}
67+
68+
echo -e "\nCoverage Report\n" | tee -a "$log_file"
69+
coverage report 2>&1 | tee -a "$log_file"
70+
71+
exit $test_status
6072
6173
- name: Check coverage
6274
run: |

0 commit comments

Comments
 (0)