fix: Add Azure OpenAI API key secret reference for deployment #48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |