-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add Application Insights for OTEL tracing and uat->staging rename #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8eef6e1
901509d
3945195
8f6c24a
4f315b2
eb07474
9d5b99b
cab0205
ef8619a
c7d997a
4c5e506
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,232 @@ | ||
| name: Deploy Environment | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| env_name: | ||
| required: true | ||
| type: string | ||
| description: Environment name (dev/staging/prod) | ||
| tf_state_key: | ||
| required: true | ||
| type: string | ||
| description: Terraform state key (e.g., dev.terraform.tfstate) | ||
| codex_model: | ||
| required: true | ||
| type: string | ||
| description: Codex model deployment name | ||
| codex_api_version: | ||
| required: true | ||
| type: string | ||
| description: Codex API version | ||
| terraform_working_directory: | ||
| required: true | ||
| type: string | ||
| description: Terraform working directory (e.g., infra/env/dev) | ||
| smoke_retry_sleep: | ||
| required: false | ||
| type: string | ||
| default: "10" | ||
| description: Retry sleep for smoke tests | ||
| smoke_models_wait_sleep: | ||
| required: false | ||
| type: string | ||
| default: "15" | ||
| description: Wait sleep for model registration | ||
| include_aoai_host_check: | ||
| required: false | ||
| type: boolean | ||
| default: false | ||
| description: Include AOAI endpoint host validation | ||
| secrets: | ||
| AZURE_OPENAI_ENDPOINT: | ||
| required: true | ||
| AZURE_OPENAI_API_KEY: | ||
| required: true | ||
| AZURE_OPENAI_EMBEDDING_ENDPOINT: | ||
| required: true | ||
| AZURE_OPENAI_EMBEDDING_API_KEY: | ||
| required: true | ||
| AIGATEWAY_KEY: | ||
| required: true | ||
|
|
||
| env: | ||
| TF_VAR_env: ${{ inputs.env_name }} | ||
| TF_VAR_projname: "aigateway" | ||
| TF_VAR_location: "southafricanorth" | ||
| TF_VAR_location_short: "san" | ||
| TF_VAR_azure_openai_endpoint: ${{ secrets.AZURE_OPENAI_ENDPOINT }} | ||
| TF_VAR_azure_openai_api_key: ${{ secrets.AZURE_OPENAI_API_KEY }} | ||
| TF_VAR_azure_openai_embedding_endpoint: ${{ secrets.AZURE_OPENAI_EMBEDDING_ENDPOINT }} | ||
| TF_VAR_azure_openai_embedding_api_key: ${{ secrets.AZURE_OPENAI_EMBEDDING_API_KEY }} | ||
| TF_VAR_gateway_key: ${{ secrets.AIGATEWAY_KEY }} | ||
| TF_VAR_codex_model: ${{ inputs.codex_model }} | ||
| TF_VAR_codex_api_version: ${{ inputs.codex_api_version }} | ||
| TF_VAR_embedding_deployment: "text-embedding-3-large" | ||
| TF_VAR_embeddings_api_version: "2024-02-01" | ||
|
|
||
| jobs: | ||
| deploy: | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: ${{ inputs.terraform_working_directory }} | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Quickcheck required secrets and config | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| missing=0 | ||
| required=( | ||
| AZURE_CLIENT_ID | ||
| AZURE_TENANT_ID | ||
| AZURE_SUBSCRIPTION_ID | ||
| TF_BACKEND_RG | ||
| TF_BACKEND_SA | ||
| TF_BACKEND_CONTAINER | ||
| TF_VAR_azure_openai_endpoint | ||
| TF_VAR_azure_openai_api_key | ||
| TF_VAR_gateway_key | ||
| ) | ||
| for v in "${required[@]}"; do | ||
| if [ -z "${!v:-}" ]; then | ||
| echo "::error::Missing required value: ${v}" | ||
| missing=1 | ||
| else | ||
| echo "${v}=SET" | ||
| fi | ||
| done | ||
| echo "TF_VAR_env=${TF_VAR_env:-unset}" | ||
| echo "TF_VAR_embedding_deployment=${TF_VAR_embedding_deployment:-unset}" | ||
| echo "TF_VAR_codex_model=${TF_VAR_codex_model:-unset}" | ||
| if [ -n "${TF_VAR_azure_openai_endpoint:-}" ]; then | ||
| echo "Azure OpenAI endpoint=${TF_VAR_azure_openai_endpoint}" | ||
| endpoint_host=$(echo "${TF_VAR_azure_openai_endpoint}" | sed -E 's#^https?://([^/]+)/?.*$#\1#') | ||
| echo "Azure OpenAI endpoint host=${endpoint_host}" | ||
| if [ "${{ inputs.include_aoai_host_check }}" = "true" ] && [ -n "${EXPECTED_AOAI_ENDPOINT_HOST:-}" ] && [ "${endpoint_host}" != "${EXPECTED_AOAI_ENDPOINT_HOST}" ]; then | ||
| echo "::error::Prod AOAI endpoint host mismatch. Expected '${EXPECTED_AOAI_ENDPOINT_HOST}', got '${endpoint_host}'. Check environment secret AZURE_OPENAI_ENDPOINT." | ||
| missing=1 | ||
| fi | ||
| fi | ||
| if [ "${missing}" -ne 0 ]; then | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Azure Login | ||
| uses: azure/login@v2 | ||
| with: | ||
| client-id: ${{ env.AZURE_CLIENT_ID }} | ||
| tenant-id: ${{ env.AZURE_TENANT_ID }} | ||
| subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }} | ||
|
|
||
| - name: Setup Terraform | ||
| uses: hashicorp/setup-terraform@v3 | ||
| with: | ||
| terraform_version: 1.14.6 | ||
|
|
||
| - name: Terraform Init | ||
| run: | | ||
| terraform init \ | ||
| -backend-config="resource_group_name=${TF_BACKEND_RG}" \ | ||
| -backend-config="storage_account_name=${TF_BACKEND_SA}" \ | ||
| -backend-config="container_name=${TF_BACKEND_CONTAINER}" \ | ||
| -backend-config="key=${{ inputs.tf_state_key }}" | ||
|
|
||
| - name: Import existing Container App into Terraform state | ||
| uses: ./.github/actions/import-container-app | ||
| with: | ||
| projname: ${{ env.TF_VAR_projname }} | ||
| env: ${{ env.TF_VAR_env }} | ||
| location_short: ${{ env.TF_VAR_location_short }} | ||
| subscription_id: ${{ env.AZURE_SUBSCRIPTION_ID }} | ||
| terraform_working_directory: ${{ inputs.terraform_working_directory }} | ||
|
|
||
| - name: Terraform Plan | ||
| run: | | ||
| terraform plan -out=tfplan | ||
|
|
||
| - name: Terraform Apply | ||
| run: | | ||
| terraform apply -auto-approve tfplan | ||
|
|
||
| - name: Get gateway URL | ||
| id: gw | ||
| run: echo "url=$(terraform output -raw gateway_url)" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Get dashboard URL | ||
| id: db | ||
| run: echo "url=$(terraform output -raw dashboard_url 2>/dev/null || true)" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Runtime diagnostics (Container App config) | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| RG_NAME="pvc-${TF_VAR_env}-${TF_VAR_projname}-rg-${TF_VAR_location_short}" | ||
| CA_NAME="pvc-${TF_VAR_env}-${TF_VAR_projname}-ca-${TF_VAR_location_short}" | ||
| echo "Resource Group: ${RG_NAME}" | ||
| echo "Container App: ${CA_NAME}" | ||
| echo "Gateway URL (terraform output): ${{ steps.gw.outputs.url }}" | ||
| echo "Latest revision:" | ||
| az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.latestRevisionName" -o tsv | ||
| echo "Active revisions (name, active, created):" | ||
| az containerapp revision list -g "${RG_NAME}" -n "${CA_NAME}" --query "[].{name:name,active:properties.active,created:properties.createdTime}" -o table | ||
| echo "Configured env vars for LiteLLM secret refs:" | ||
| az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.template.containers[0].env[?name=='LITELLM_AZURE_OPENAI_API_KEY' || name=='LITELLM_GATEWAY_KEY']" -o json | ||
| echo "Configured secret sources (names + key vault URLs):" | ||
| az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.configuration.secrets[].{name:name,keyVaultUrl:keyVaultUrl}" -o table | ||
| echo "LITELLM_CONFIG_CONTENT excerpt (first 2000 chars):" | ||
| az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.template.containers[0].env[?name=='LITELLM_CONFIG_CONTENT'].value | [0]" -o tsv | head -c 2000 || true | ||
| echo | ||
|
|
||
| - name: Integration test (Azure OpenAI backend) | ||
| shell: bash | ||
| env: | ||
| AZURE_OPENAI_ENDPOINT: ${{ env.TF_VAR_azure_openai_endpoint }} | ||
| AZURE_OPENAI_API_KEY: ${{ env.TF_VAR_azure_openai_api_key }} | ||
| AZURE_OPENAI_EMBEDDING_ENDPOINT: ${{ env.TF_VAR_azure_openai_embedding_endpoint }} | ||
| AZURE_OPENAI_EMBEDDING_API_KEY: ${{ env.TF_VAR_azure_openai_embedding_api_key }} | ||
| AZURE_OPENAI_EMBEDDING_DEPLOYMENT: ${{ env.TF_VAR_embedding_deployment }} | ||
| AZURE_OPENAI_API_VERSION: ${{ env.TF_VAR_embeddings_api_version }} | ||
| AZURE_OPENAI_CHAT_DEPLOYMENT: "gpt-4.1" | ||
| AZURE_OPENAI_CHAT_API_VERSION: ${{ env.TF_VAR_codex_api_version }} | ||
| AZURE_OPENAI_CODEX_MODEL: ${{ env.TF_VAR_codex_model }} | ||
| working-directory: ${{ github.workspace }} | ||
| run: python3 scripts/integration_test.py | ||
|
|
||
| - name: Smoke test gateway (embeddings + responses) | ||
| uses: ./.github/actions/smoke-test-gateway | ||
| with: | ||
| gateway_url: ${{ steps.gw.outputs.url }} | ||
| gateway_key: ${{ secrets.AIGATEWAY_KEY }} | ||
| embedding_model: ${{ env.TF_VAR_embedding_deployment }} | ||
| codex_model: ${{ env.TF_VAR_codex_model }} | ||
| aoai_endpoint: ${{ env.TF_VAR_azure_openai_endpoint }} | ||
| aoai_api_key: ${{ env.TF_VAR_azure_openai_api_key }} | ||
| max_attempts: "3" | ||
| retry_sleep: ${{ inputs.smoke_retry_sleep }} | ||
| models_wait_attempts: ${{ if(inputs.env_name == 'prod', '3', '1') }} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: GitHub Actions expressions do not provide an So for “ternary-like” value selection you have two options:
Sources: Replace the unsupported GitHub Actions expressions do not support Suggested fix- models_wait_attempts: ${{ if(inputs.env_name == 'prod', '3', '1') }}
+ models_wait_attempts: ${{ case(inputs.env_name == 'prod', '3', '1') }}Alternatively, the 🧰 Tools🪛 actionlint (1.7.11)[error] 211-211: undefined function "if". available functions are "always", "cancelled", "case", "contains", "endswith", "failure", "format", "fromjson", "hashfiles", "join", "startswith", "success", "tojson" (expression) 🤖 Prompt for AI Agents |
||
| models_wait_sleep: ${{ inputs.smoke_models_wait_sleep }} | ||
|
|
||
| - name: Smoke test shared state API (dashboard proxy) | ||
| if: env.TF_VAR_state_service_container_image != '' | ||
| shell: bash | ||
| run: | | ||
| set -euo pipefail | ||
| DASHBOARD_URL="${{ steps.db.outputs.url }}" | ||
| TEST_USER="ci-smoke-${TF_VAR_env}" | ||
|
|
||
| curl -fsS --connect-timeout 5 --max-time 15 "${DASHBOARD_URL}/api/state/catalog" > /tmp/catalog.json | ||
|
|
||
| curl -fsS --connect-timeout 5 --max-time 15 -X PUT "${DASHBOARD_URL}/api/state/selection" \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "X-User-Id: ${TEST_USER}" \ | ||
| -d '{"enabled":true,"selected_model":"'"${TF_VAR_codex_model}"'"}' > /tmp/selection-put.json | ||
|
|
||
| curl -fsS --connect-timeout 5 --max-time 15 "${DASHBOARD_URL}/api/state/selection" \ | ||
| -H "X-User-Id: ${TEST_USER}" > /tmp/selection-get.json | ||
|
|
||
| jq -e '.enabled == true' /tmp/selection-get.json > /dev/null | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Do reusable GitHub Actions workflows inherit the caller workflow's top-levelenv:values, or must those values be passed explicitly and rebound inside the called workflow?💡 Result:
No—reusable (called) workflows do not inherit the caller workflow’s top-level
env:values. GitHub explicitly states that “Any environment variables set in anenvcontext defined at the workflow level in the caller workflow are not propagated to the called workflow.” [1]So if the called workflow needs those values, you must pass them explicitly (typically via
on: workflow_call: inputs:/jobs.<job_id>.with:) and then rebind/use them inside the called workflow. [1]🏁 Script executed:
sed -n '211p' .github/workflows/deploy-environment.yamlRepository: phoenixvc/ai-gateway
Length of output: 142
Rebuild the full deploy env inside the reusable workflow and fix Line 211 syntax.
Reusable workflows do not inherit the caller's top-level
env:values—they must be passed explicitly. This workflow only recreates the AOAI/gateway subset, leavingAZURE_CLIENT_ID,AZURE_TENANT_ID,AZURE_SUBSCRIPTION_ID,TF_BACKEND_*, and other Terraform variables empty for Lines 79-137. The result is thatapplyexecutes with a different input set than the reviewedplan,TF_VAR_state_service_container_imagestays empty so the Line 215 smoke gate never runs, and the prod AOAI guard at Lines 106-113 is inert becauseEXPECTED_AOAI_ENDPOINT_HOSTis never exported. Additionally, Line 211 uses invalid syntaxif(inputs.env_name == 'prod', '3', '1')— GitHub Actions has noif()function; use a ternary pattern instead:inputs.env_name == 'prod' && '3' || '1'.🤖 Prompt for AI Agents