Skip to content

Commit 2bc7860

Browse files
authored
Merge pull request #68 from phoenixvc/feat/infra-alignment
feat: add Application Insights for OTEL tracing and uat->staging rename
2 parents 7fb9fe9 + 4c5e506 commit 2bc7860

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+6027
-629
lines changed

.github/actions/import-container-app/action.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ inputs:
1010
description: Project name component of the Container App name (TF_VAR_projname)
1111
env:
1212
required: true
13-
description: Environment name (dev|uat|prod)
13+
description: Environment name (dev|staging|prod)
1414
location_short:
1515
required: true
1616
description: Short location code (TF_VAR_location_short)

.github/pull_request_template.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
- [ ] No environment/config changes required
1616
- [ ] Environment/config changes required (describe below)
1717

18-
## UAT Toggle (PRs to `main`)
18+
## Staging Toggle (PRs to `main`)
1919

20-
- Add label `run-uat` to this PR to enable UAT deployment (`deploy-uat`).
21-
- Remove label `run-uat` to skip UAT deployment.
20+
- Add label `run-staging` to this PR to enable staging deployment (`deploy-staging`).
21+
- Remove label `run-staging` to skip staging deployment.
2222

2323
## Risk / Rollback
2424

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
name: Deploy Environment
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
env_name:
7+
required: true
8+
type: string
9+
description: Environment name (dev/staging/prod)
10+
tf_state_key:
11+
required: true
12+
type: string
13+
description: Terraform state key (e.g., dev.terraform.tfstate)
14+
codex_model:
15+
required: true
16+
type: string
17+
description: Codex model deployment name
18+
codex_api_version:
19+
required: true
20+
type: string
21+
description: Codex API version
22+
terraform_working_directory:
23+
required: true
24+
type: string
25+
description: Terraform working directory (e.g., infra/env/dev)
26+
smoke_retry_sleep:
27+
required: false
28+
type: string
29+
default: "10"
30+
description: Retry sleep for smoke tests
31+
smoke_models_wait_sleep:
32+
required: false
33+
type: string
34+
default: "15"
35+
description: Wait sleep for model registration
36+
include_aoai_host_check:
37+
required: false
38+
type: boolean
39+
default: false
40+
description: Include AOAI endpoint host validation
41+
secrets:
42+
AZURE_OPENAI_ENDPOINT:
43+
required: true
44+
AZURE_OPENAI_API_KEY:
45+
required: true
46+
AZURE_OPENAI_EMBEDDING_ENDPOINT:
47+
required: true
48+
AZURE_OPENAI_EMBEDDING_API_KEY:
49+
required: true
50+
AIGATEWAY_KEY:
51+
required: true
52+
53+
env:
54+
TF_VAR_env: ${{ inputs.env_name }}
55+
TF_VAR_projname: "aigateway"
56+
TF_VAR_location: "southafricanorth"
57+
TF_VAR_location_short: "san"
58+
TF_VAR_azure_openai_endpoint: ${{ secrets.AZURE_OPENAI_ENDPOINT }}
59+
TF_VAR_azure_openai_api_key: ${{ secrets.AZURE_OPENAI_API_KEY }}
60+
TF_VAR_azure_openai_embedding_endpoint: ${{ secrets.AZURE_OPENAI_EMBEDDING_ENDPOINT }}
61+
TF_VAR_azure_openai_embedding_api_key: ${{ secrets.AZURE_OPENAI_EMBEDDING_API_KEY }}
62+
TF_VAR_gateway_key: ${{ secrets.AIGATEWAY_KEY }}
63+
TF_VAR_codex_model: ${{ inputs.codex_model }}
64+
TF_VAR_codex_api_version: ${{ inputs.codex_api_version }}
65+
TF_VAR_embedding_deployment: "text-embedding-3-large"
66+
TF_VAR_embeddings_api_version: "2024-02-01"
67+
68+
jobs:
69+
deploy:
70+
runs-on: ubuntu-latest
71+
defaults:
72+
run:
73+
working-directory: ${{ inputs.terraform_working_directory }}
74+
75+
steps:
76+
- name: Checkout code
77+
uses: actions/checkout@v4
78+
79+
- name: Quickcheck required secrets and config
80+
shell: bash
81+
run: |
82+
set -euo pipefail
83+
missing=0
84+
required=(
85+
AZURE_CLIENT_ID
86+
AZURE_TENANT_ID
87+
AZURE_SUBSCRIPTION_ID
88+
TF_BACKEND_RG
89+
TF_BACKEND_SA
90+
TF_BACKEND_CONTAINER
91+
TF_VAR_azure_openai_endpoint
92+
TF_VAR_azure_openai_api_key
93+
TF_VAR_gateway_key
94+
)
95+
for v in "${required[@]}"; do
96+
if [ -z "${!v:-}" ]; then
97+
echo "::error::Missing required value: ${v}"
98+
missing=1
99+
else
100+
echo "${v}=SET"
101+
fi
102+
done
103+
echo "TF_VAR_env=${TF_VAR_env:-unset}"
104+
echo "TF_VAR_embedding_deployment=${TF_VAR_embedding_deployment:-unset}"
105+
echo "TF_VAR_codex_model=${TF_VAR_codex_model:-unset}"
106+
if [ -n "${TF_VAR_azure_openai_endpoint:-}" ]; then
107+
echo "Azure OpenAI endpoint=${TF_VAR_azure_openai_endpoint}"
108+
endpoint_host=$(echo "${TF_VAR_azure_openai_endpoint}" | sed -E 's#^https?://([^/]+)/?.*$#\1#')
109+
echo "Azure OpenAI endpoint host=${endpoint_host}"
110+
if [ "${{ inputs.include_aoai_host_check }}" = "true" ] && [ -n "${EXPECTED_AOAI_ENDPOINT_HOST:-}" ] && [ "${endpoint_host}" != "${EXPECTED_AOAI_ENDPOINT_HOST}" ]; then
111+
echo "::error::Prod AOAI endpoint host mismatch. Expected '${EXPECTED_AOAI_ENDPOINT_HOST}', got '${endpoint_host}'. Check environment secret AZURE_OPENAI_ENDPOINT."
112+
missing=1
113+
fi
114+
fi
115+
if [ "${missing}" -ne 0 ]; then
116+
exit 1
117+
fi
118+
119+
- name: Azure Login
120+
uses: azure/login@v2
121+
with:
122+
client-id: ${{ env.AZURE_CLIENT_ID }}
123+
tenant-id: ${{ env.AZURE_TENANT_ID }}
124+
subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}
125+
126+
- name: Setup Terraform
127+
uses: hashicorp/setup-terraform@v3
128+
with:
129+
terraform_version: 1.14.6
130+
131+
- name: Terraform Init
132+
run: |
133+
terraform init \
134+
-backend-config="resource_group_name=${TF_BACKEND_RG}" \
135+
-backend-config="storage_account_name=${TF_BACKEND_SA}" \
136+
-backend-config="container_name=${TF_BACKEND_CONTAINER}" \
137+
-backend-config="key=${{ inputs.tf_state_key }}"
138+
139+
- name: Import existing Container App into Terraform state
140+
uses: ./.github/actions/import-container-app
141+
with:
142+
projname: ${{ env.TF_VAR_projname }}
143+
env: ${{ env.TF_VAR_env }}
144+
location_short: ${{ env.TF_VAR_location_short }}
145+
subscription_id: ${{ env.AZURE_SUBSCRIPTION_ID }}
146+
terraform_working_directory: ${{ inputs.terraform_working_directory }}
147+
148+
- name: Terraform Plan
149+
run: |
150+
terraform plan -out=tfplan
151+
152+
- name: Terraform Apply
153+
run: |
154+
terraform apply -auto-approve tfplan
155+
156+
- name: Get gateway URL
157+
id: gw
158+
run: echo "url=$(terraform output -raw gateway_url)" >> $GITHUB_OUTPUT
159+
160+
- name: Get dashboard URL
161+
id: db
162+
run: echo "url=$(terraform output -raw dashboard_url 2>/dev/null || true)" >> $GITHUB_OUTPUT
163+
164+
- name: Runtime diagnostics (Container App config)
165+
shell: bash
166+
run: |
167+
set -euo pipefail
168+
RG_NAME="pvc-${TF_VAR_env}-${TF_VAR_projname}-rg-${TF_VAR_location_short}"
169+
CA_NAME="pvc-${TF_VAR_env}-${TF_VAR_projname}-ca-${TF_VAR_location_short}"
170+
echo "Resource Group: ${RG_NAME}"
171+
echo "Container App: ${CA_NAME}"
172+
echo "Gateway URL (terraform output): ${{ steps.gw.outputs.url }}"
173+
echo "Latest revision:"
174+
az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.latestRevisionName" -o tsv
175+
echo "Active revisions (name, active, created):"
176+
az containerapp revision list -g "${RG_NAME}" -n "${CA_NAME}" --query "[].{name:name,active:properties.active,created:properties.createdTime}" -o table
177+
echo "Configured env vars for LiteLLM secret refs:"
178+
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
179+
echo "Configured secret sources (names + key vault URLs):"
180+
az containerapp show -g "${RG_NAME}" -n "${CA_NAME}" --query "properties.configuration.secrets[].{name:name,keyVaultUrl:keyVaultUrl}" -o table
181+
echo "LITELLM_CONFIG_CONTENT excerpt (first 2000 chars):"
182+
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
183+
echo
184+
185+
- name: Integration test (Azure OpenAI backend)
186+
shell: bash
187+
env:
188+
AZURE_OPENAI_ENDPOINT: ${{ env.TF_VAR_azure_openai_endpoint }}
189+
AZURE_OPENAI_API_KEY: ${{ env.TF_VAR_azure_openai_api_key }}
190+
AZURE_OPENAI_EMBEDDING_ENDPOINT: ${{ env.TF_VAR_azure_openai_embedding_endpoint }}
191+
AZURE_OPENAI_EMBEDDING_API_KEY: ${{ env.TF_VAR_azure_openai_embedding_api_key }}
192+
AZURE_OPENAI_EMBEDDING_DEPLOYMENT: ${{ env.TF_VAR_embedding_deployment }}
193+
AZURE_OPENAI_API_VERSION: ${{ env.TF_VAR_embeddings_api_version }}
194+
AZURE_OPENAI_CHAT_DEPLOYMENT: "gpt-4.1"
195+
AZURE_OPENAI_CHAT_API_VERSION: ${{ env.TF_VAR_codex_api_version }}
196+
AZURE_OPENAI_CODEX_MODEL: ${{ env.TF_VAR_codex_model }}
197+
working-directory: ${{ github.workspace }}
198+
run: python3 scripts/integration_test.py
199+
200+
- name: Smoke test gateway (embeddings + responses)
201+
uses: ./.github/actions/smoke-test-gateway
202+
with:
203+
gateway_url: ${{ steps.gw.outputs.url }}
204+
gateway_key: ${{ secrets.AIGATEWAY_KEY }}
205+
embedding_model: ${{ env.TF_VAR_embedding_deployment }}
206+
codex_model: ${{ env.TF_VAR_codex_model }}
207+
aoai_endpoint: ${{ env.TF_VAR_azure_openai_endpoint }}
208+
aoai_api_key: ${{ env.TF_VAR_azure_openai_api_key }}
209+
max_attempts: "3"
210+
retry_sleep: ${{ inputs.smoke_retry_sleep }}
211+
models_wait_attempts: ${{ if(inputs.env_name == 'prod', '3', '1') }}
212+
models_wait_sleep: ${{ inputs.smoke_models_wait_sleep }}
213+
214+
- name: Smoke test shared state API (dashboard proxy)
215+
if: env.TF_VAR_state_service_container_image != ''
216+
shell: bash
217+
run: |
218+
set -euo pipefail
219+
DASHBOARD_URL="${{ steps.db.outputs.url }}"
220+
TEST_USER="ci-smoke-${TF_VAR_env}"
221+
222+
curl -fsS --connect-timeout 5 --max-time 15 "${DASHBOARD_URL}/api/state/catalog" > /tmp/catalog.json
223+
224+
curl -fsS --connect-timeout 5 --max-time 15 -X PUT "${DASHBOARD_URL}/api/state/selection" \
225+
-H "Content-Type: application/json" \
226+
-H "X-User-Id: ${TEST_USER}" \
227+
-d '{"enabled":true,"selected_model":"'"${TF_VAR_codex_model}"'"}' > /tmp/selection-put.json
228+
229+
curl -fsS --connect-timeout 5 --max-time 15 "${DASHBOARD_URL}/api/state/selection" \
230+
-H "X-User-Id: ${TEST_USER}" > /tmp/selection-get.json
231+
232+
jq -e '.enabled == true' /tmp/selection-get.json > /dev/null

0 commit comments

Comments
 (0)