Skip to content

fix: Add Azure OpenAI API key secret reference for deployment #48

fix: Add Azure OpenAI API key secret reference for deployment

fix: Add Azure OpenAI API key secret reference for deployment #48

name: Build and Deploy to Azure
on:
push:
branches:
- master
jobs:
deploy-container-apps:
name: Build and Deploy Python and Blazor Apps
runs-on: ubuntu-latest
permissions:
id-token: write
env:
RESOURCE_GROUP: ${{ secrets.RESOURCE_GROUP }}
PYTHON_APP_NAME: ${{ secrets.CONTAINER_APP_NAME }}
BLAZOR_APP_NAME: ${{ secrets.BLAZOR_CONTAINER_APP_NAME }}
GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }}
GHCR_PAT: ${{ secrets.GHCR_PAT }}
PYTHON_IMAGE: ghcr.io/${{ secrets.GHCR_USERNAME }}/weather-py:latest
BLAZOR_IMAGE: ghcr.io/${{ secrets.GHCR_USERNAME }}/weather-blazor:latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Validate deployment configuration
run: |
set -euo pipefail
required_vars=(
RESOURCE_GROUP
PYTHON_APP_NAME
BLAZOR_APP_NAME
GHCR_USERNAME
GHCR_PAT
)
for var_name in "${required_vars[@]}"; do
if [ -z "${!var_name}" ]; then
echo "ERROR: Required workflow value '$var_name' is not configured."
exit 1
fi
done
# Warn (but don't fail) if the WeatherAPI key is absent — the app will
# start but weather data will be unavailable.
if [ -z "${{ secrets.WEATHER_API_KEY }}" ]; then
echo "WARNING: WEATHER_API_KEY secret is not set. Weather data will not be available."
fi
- name: Log in to Azure
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUB_ID }}
- name: Log in to GitHub Container Registry
run: echo "$GHCR_PAT" | docker login ghcr.io -u "$GHCR_USERNAME" --password-stdin
- name: Build Python Docker image
run: docker build -t "$PYTHON_IMAGE" .
- name: Push Python Docker image
run: docker push "$PYTHON_IMAGE"
- name: Deploy Python app to Azure Container Apps
run: |
set -euo pipefail
az containerapp update \
--name "$PYTHON_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--image "$PYTHON_IMAGE" \
--set-env-vars \
"WEATHER_API_KEY=secretref:weatherapikey" \
"AZURE_OPENAI_API_KEY=secretref:azure-open-ai-key" \
"AZURE_OPENAI_ENDPOINT=${{ secrets.AZURE_OPENAI_ENDPOINT }}" \
"AZURE_OPENAI_DEPLOYMENT=${{ secrets.AZURE_OPENAI_DEPLOYMENT }}" \
"AZURE_OPENAI_API_VERSION=2024-10-21"
- name: Build Blazor Docker image
run: docker build -f Dockerfile.blazor -t "$BLAZOR_IMAGE" .
- name: Push Blazor Docker image
run: docker push "$BLAZOR_IMAGE"
- name: Resolve existing Container Apps environment
id: container-env
run: |
set -euo pipefail
MANAGED_ENVIRONMENT_ID=$(az containerapp show \
--name "$PYTHON_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--query "properties.managedEnvironmentId" \
--output tsv)
if [ -z "$MANAGED_ENVIRONMENT_ID" ]; then
echo "ERROR: Unable to resolve the managed environment from $PYTHON_APP_NAME."
exit 1
fi
echo "managed_environment_id=$MANAGED_ENVIRONMENT_ID" >> "$GITHUB_OUTPUT"
- name: Deploy Blazor app to Azure Container Apps
env:
MANAGED_ENVIRONMENT_ID: ${{ steps.container-env.outputs.managed_environment_id }}
run: |
set -euo pipefail
APP_EXISTS=$(az containerapp show \
--name "$BLAZOR_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--query "name" \
--output tsv 2>/dev/null || true)
if [ -n "$APP_EXISTS" ]; then
echo "Updating existing Blazor Container App: $BLAZOR_APP_NAME"
az containerapp update \
--name "$BLAZOR_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--image "$BLAZOR_IMAGE" \
--set-env-vars \
"WEATHER_API_KEY=secretref:weatherapikey" \
"AZURE_OPENAI_API_KEY=secretref:azure-open-ai-key" \
"AZURE_OPENAI_ENDPOINT=${{ secrets.AZURE_OPENAI_ENDPOINT }}" \
"AZURE_OPENAI_DEPLOYMENT=${{ secrets.AZURE_OPENAI_DEPLOYMENT }}" \
"AZURE_OPENAI_API_VERSION=2024-10-21"
else
echo "Creating new Blazor Container App: $BLAZOR_APP_NAME"
if [ -z "${{ secrets.API_KEY_WEATHER }}" ]; then
echo "ERROR: Required repository secret 'API_KEY_WEATHER' is not configured."
exit 1
fi
az containerapp create \
--name "$BLAZOR_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--environment "$MANAGED_ENVIRONMENT_ID" \
--image "$BLAZOR_IMAGE" \
--target-port 80 \
--ingress external \
--registry-server ghcr.io \
--registry-username "$GHCR_USERNAME" \
--registry-password "$GHCR_PAT" \
--secrets \
"weatherapikey=${{ secrets.API_KEY_WEATHER }}" \
"azure-open-ai-key=${{ secrets.AZURE_OPENAI_API_KEY }}" \
--env-vars \
"WEATHER_API_KEY=secretref:weatherapikey" \
"AZURE_OPENAI_API_KEY=secretref:azure-open-ai-key" \
"AZURE_OPENAI_ENDPOINT=${{ secrets.AZURE_OPENAI_ENDPOINT }}" \
"AZURE_OPENAI_DEPLOYMENT=${{ secrets.AZURE_OPENAI_DEPLOYMENT }}" \
"AZURE_OPENAI_API_VERSION=2024-10-21"
fi
# Blazor Server uses a persistent SignalR circuit that must stay on the
# same replica for the lifetime of the browser session. Without sticky
# sessions, requests can be routed to a different replica that has no
# record of the circuit, silently preventing interactive components
# (search box, theme toggle, etc.) from connecting.
- name: Enable sticky sessions for Blazor Container App
run: |
az containerapp ingress sticky-sessions set \
--name "$BLAZOR_APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--affinity sticky