Deployment Guide
This guide covers deploying the SWMM Feature Publisher Function to Azure.
Prerequisites
- Azure subscription
- Azure CLI installed and configured
- Function App deployment permissions
- ArcGIS Online account with API key
Deployment Options
Option 1: Azure Portal (Recommended for First Time)
Step 1: Create Storage Account
Go to Azure Portal
Create new Storage Account:
- Resource Group: Create new or use existing
- Storage Account Name: e.g.,
swmmpublisherstorage - Location: Choose region close to users
- Performance: Standard
- Redundancy: LRS (or GRS for production)
After creation, create these resources:
- Container:
swmm-input(for INP file uploads - triggers blob function) - Tables:
Projects,ProjectFeatureMetaData
- Container:
Important: Ensure the container
swmm-inputhas appropriate permissions for blob trigger:- The function app's managed identity or connection string must have read access
- Blob creation events will trigger the
swmmBlobTriggerPublisherfunction
Step 2: Get Connection String/SAS Token
Option A: Connection String (Simpler)
- Go to Storage Account → Access keys
- Copy "Connection string" from key1 or key2
Option B: SAS Token (More Secure)
- Go to Storage Account → Shared access signature
- Configure:
- Allowed services: Blob, Table
- Allowed resource types: Service, Container, Object
- Allowed permissions: Read, Write, Delete, List, Add, Create, Update
- Start and expiry date: Set appropriate dates
- Click "Generate SAS and connection string"
- Copy the SAS token
Step 3: Create Application Insights
- Create new Application Insights resource
- Note the Connection String
Step 4: Create Function App
Create new Function App:
- Runtime: Python
- Version: 3.11
- Operating System: Linux
- Plan: Consumption (Y1) or Premium
- Storage Account: Use existing or create new
Configure Application Settings (Environment Variables):
Go to Function App → Configuration → Application settings:
AzureWebJobsStorage = <storage-connection-string>
0b61f1_STORAGE = <storage-connection-string>
APPLICATIONINSIGHTS_CONNECTION_STRING = <app-insights-connection-string>
AZURE_STORAGE_ACCOUNT_NAME = <account-name>
AZURE_STORAGE_SAS_TOKEN = <sas-token-with-question-mark>
SWMM_INP_CONTAINER = swmm-input
PROJECT_TABLE_NAME = Projects
FEATURES_TABLE_NAME = ProjectFeatureMetaData
ARCGIS_URL = https://www.arcgis.com
ARCGIS_API_KEY = <your-arcgis-api-key>
MAX_ATTEMPTS = 3
FUNCTIONS_WORKER_RUNTIME = python
# Optional: fail publish if Projects row has no valid EPSG (Int32) and HTTP body omits "epsg"
# REQUIRE_PROJECT_EPSG = true
Project CRS (EPSG): Layer publishing uses the project's EPSG authority code for hybrid reprojection and INP-only GeoJSON CRS metadata. Resolution order: optional epsg in the publish-project-layers JSON body → EPSG column on the Projects table row (Int32, e.g. 26917) → default 3089 (see publisher/constants.py) with a log warning. Set REQUIRE_PROJECT_EPSG=true to return an error instead of using the default when EPSG is missing.
Subcatchment outputs: Hybrid publishing writes two subcatchment layers and two metadata rows in ProjectFeatureMetaData:
Subcatchment(Polygon geometry from INP[Polygons]section; no centroid fallback)Subcatchment_Centroid(Point geometry)
Step 5: Deploy Code
From VS Code:
- Install Azure Functions extension
- Right-click on function folder
- Select "Deploy to Function App"
- Choose your function app
From Command Line:
cd c:\Git\gqc\hydrotrek-ssc-suite\swmm-feature-publisher-function
func azure functionapp publish <your-function-app-name>
Step 6: Verify Deployment
Check Function App logs:
- Go to Function App → Log stream in Azure Portal
- Or use Azure CLI:
az webapp log tail --name <function-app-name> --resource-group <resource-group>
Test health endpoint:
curl https://<function-app-name>.azurewebsites.net/api/healthExpected response:
{"status": "healthy", "service": "swmm-feature-publisher"}Test blob trigger:
# Upload test INP file to trigger automatic publishing
python scripts/test_blob_upload.py \
--project-id test-deployment \
--inp-file scripts/rivershore.inpThis tests the automatic publishing workflow:
- ✅ Blob trigger activates on upload
- ✅ Status updates: "Uploaded input file" → "Processing" → "Complete"
- ✅ Layers published to ArcGIS with prefix
SD1_test-deployment
Monitor first upload:
- Check Function App Logs for blob trigger activation
- Verify Projects Table status transitions
- Check ArcGIS Online for published layers
- View Application Insights telemetry
Option 2: Azure CLI (Automated)
#!/bin/bash
# Configuration
RESOURCE_GROUP="rg-swmm-publisher"
LOCATION="eastus"
STORAGE_ACCOUNT="swmmpublisherstorage"
FUNCTION_APP="swmm-feature-publisher"
APP_INSIGHTS="swmm-publisher-insights"
# Create resource group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# Create storage account
az storage account create \
--name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku Standard_LRS
# Get storage connection string
STORAGE_CONN=$(az storage account show-connection-string \
--name $STORAGE_ACCOUNT \
--resource-group $RESOURCE_GROUP \
--query connectionString \
--output tsv)
# Create container
az storage container create \
--name swmm-input \
--connection-string "$STORAGE_CONN"
# Create tables
az storage table create \
--name Projects \
--connection-string "$STORAGE_CONN"
az storage table create \
--name ProjectFeatureMetaData \
--connection-string "$STORAGE_CONN"
# Create Application Insights
az monitor app-insights component create \
--app $APP_INSIGHTS \
--location $LOCATION \
--resource-group $RESOURCE_GROUP
# Get App Insights connection string
APP_INSIGHTS_CONN=$(az monitor app-insights component show \
--app $APP_INSIGHTS \
--resource-group $RESOURCE_GROUP \
--query connectionString \
--output tsv)
# Create Function App
az functionapp create \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP \
--storage-account $STORAGE_ACCOUNT \
--runtime python \
--runtime-version 3.11 \
--os-type Linux \
--functions-version 4 \
--consumption-plan-location $LOCATION
# Configure app settings
az functionapp config appsettings set \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP \
--settings \
"0b61f1_STORAGE=$STORAGE_CONN" \
"APPLICATIONINSIGHTS_CONNECTION_STRING=$APP_INSIGHTS_CONN" \
"AZURE_STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT" \
"SWMM_INP_CONTAINER=swmm-input" \
"PROJECT_TABLE_NAME=Projects" \
"FEATURES_TABLE_NAME=ProjectFeatureMetaData" \
"ARCGIS_URL=https://www.arcgis.com" \
"ARCGIS_API_KEY=<YOUR_API_KEY>" \
"MAX_ATTEMPTS=3"
# Deploy function code
func azure functionapp publish $FUNCTION_APP
echo "Deployment complete!"
echo "Function App: https://$FUNCTION_APP.azurewebsites.net"
echo "Health Check: https://$FUNCTION_APP.azurewebsites.net/api/health"
Option 3: Using Managed Identity (Production Best Practice)
For production, use Managed Identity instead of connection strings:
Step 1: Enable Managed Identity
az functionapp identity assign \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP
Step 2: Grant Permissions
# Get Function App's principal ID
PRINCIPAL_ID=$(az functionapp identity show \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP \
--query principalId \
--output tsv)
# Grant Storage Blob Data Contributor
az role assignment create \
--assignee $PRINCIPAL_ID \
--role "Storage Blob Data Contributor" \
--scope "/subscriptions/<subscription-id>/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT"
# Grant Storage Table Data Contributor
az role assignment create \
--assignee $PRINCIPAL_ID \
--role "Storage Table Data Contributor" \
--scope "/subscriptions/<subscription-id>/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Storage/storageAccounts/$STORAGE_ACCOUNT"
Step 3: Update App Settings
Remove keys, use identity-based connection:
az functionapp config appsettings set \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP \
--settings \
"AzureWebJobsStorage__accountName=$STORAGE_ACCOUNT" \
"0b61f1_STORAGE__accountName=$STORAGE_ACCOUNT" \
"AZURE_STORAGE_ACCOUNT_NAME=$STORAGE_ACCOUNT"
Post-Deployment Configuration
1. Configure Monitoring Alerts
# Alert on function failures
az monitor metrics alert create \
--name "swmm-function-failures" \
--resource-group $RESOURCE_GROUP \
--scopes "/subscriptions/<subscription-id>/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Web/sites/$FUNCTION_APP" \
--condition "count FunctionExecutionCount < 1" \
--window-size 5m \
--evaluation-frequency 1m
2. Configure Auto-scaling (Premium Plan)
az functionapp plan update \
--name <plan-name> \
--resource-group $RESOURCE_GROUP \
--max-burst 20 \
--min-instances 1
3. Enable Diagnostic Logs
az monitor diagnostic-settings create \
--name function-diagnostics \
--resource "/subscriptions/<subscription-id>/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Web/sites/$FUNCTION_APP" \
--logs '[{"category": "FunctionAppLogs","enabled": true}]' \
--workspace <log-analytics-workspace-id>
Continuous Deployment
Deployment is manual for now (GitHub Actions deploy to Flex Consumption can fail; use one of the methods in Step 5 above: VS Code "Deploy to Function App" or func azure functionapp publish <your-function-app-name> from the command line).
Rollback Procedure
If deployment fails:
Option 1: Azure Portal
- Go to Function App → Deployment Center
- Click on previous deployment
- Click "Redeploy"
Option 2: Azure CLI
# List deployment IDs
az functionapp deployment list \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP
# Redeploy specific version
az functionapp deployment source sync \
--name $FUNCTION_APP \
--resource-group $RESOURCE_GROUP
Deployment Verification Checklist
After deployment, verify:
- Health endpoint returns 200 OK
- Application Insights shows telemetry
- Blob container
swmm-inputexists - Tables
ProjectsandProjectFeatureMetaDataexist - Test blob upload processes successfully
- Project status updates correctly
- ArcGIS layers publish successfully
- Error logging works
Troubleshooting Deployment
Function won't start
- Check Application Insights logs
- Verify all required app settings configured
- Ensure Python runtime version matches (3.11)
- Check storage account connection
Permission errors
- Verify SAS token permissions (rwdxftlacup)
- Check Managed Identity role assignments
- Ensure ArcGIS API key is valid
Performance issues
- Increase Function App plan tier
- Adjust
batchSizein host.json - Enable Application Insights profiling
Security Checklist
- Use Managed Identity in production
- Store secrets in Azure Key Vault
- Enable HTTPS only
- Configure IP restrictions if needed
- Rotate SAS tokens regularly
- Use least-privilege permissions
- Enable Azure Defender for Storage
- Configure alert rules