Prompt file imported from samdop/convertonode (
.github/prompts/Phase5-DeployToAzure.prompt.md). Fill in{{PWD}}before use. Copyright stays with the author.
Phase 5: Deploy to Azure
Objective
Deploy the migrated ASP.NET MVC application as a full-stack Node.js + React solution on Azure. This phase deploys:
apps/api— Node.js backend APIapps/web— Vite React web client- Database migration or schema evolution for the target data platform Use the platform selected in Phase 1 and the infrastructure created in Phase 4. Reference skills by folder name:
azure-fullstack-deploymentsqlserver-to-postgres-migrationSuccess means both apps are live over HTTPS, database migrations are complete, telemetry is flowing, security checks pass, and smoke tests are documented.
Prerequisites
- Phase 1 selected the Azure hosting platform.
- Phase 2 defined the target full-stack architecture.
- Phase 3 completed the code migration.
- Phase 3
pnpm buildworks locally. - Phase 4 created infrastructure files in
infra/. - Phase 4 what-if / plan validation passed.
- Entra app registrations from Phase 4 are complete.
- Runtime environment values are known for the target environment.
- Database migration strategy is known.
- Rollback expectations are understood for the selected platform.
Step 0: Load session memory (always run first)
Read reports/Report-Status.md before any other action.
- If Phase 4 is not ✅ Complete: prerequisite unmet — instruct user to complete Phase 4 first. Do not proceed.
- If Session State shows Phase 5 is ✅ Complete for the environment being deployed (dev/staging/prod): ask whether to redeploy or advance to
/phase6-setupcicd. Note: Phase 5 can be run multiple times, once per environment. - If Phase 5 is ⏳ In Progress: scan Activity Log for last successful step (e.g., "api image pushed", "web deployed", "DB migration applied"). Resume from the next unfinished step. Do NOT re-deploy already-successful resources.
- If Phase 5 is ⬜ Not Started: proceed.
- If
Blocked byis set: surface and pause. Append a starting entry at the TOP of the Activity Log: | YYYY-MM-DD HH:MM UTC | Phase 5 | — | Phase 5 started for env= (or resumed at ) | ⏳ | Loaded prior context | UpdateSession State.Current PhasetoPhase 5 — Azure Deployment (<env>)andActive Skills Loadedtoazure-fullstack-deploymentplus DB skill if migrations run.
Step 1: Pre-deployment checklist
Complete every item before deploying.
- Latest
azinstalled:az --versionis ≥ 2.60. - Latest
azdinstalled:azd versionis ≥ 1.9. - Docker Desktop installed and running if using containerized paths.
- Azure CLI login completed.
az login - Target subscription selected.
az account set --subscription <sub-id> - Azure Developer CLI login completed.
azd auth login - Infrastructure files exist in
infra/. -
azure.yamlexists at project root. -
pnpm buildsucceeds locally. - Entra app registrations from Phase 4 are done.
- ACR / Container Registry is provisioned if using container path.
- Env vars are ready:
- API URL
- web URL
- App Insights connection string
- Entra tenant ID
- Entra client IDs
- Entra API audience / app ID URI
- database host and database name
- production feature flags
- No secrets are stored in tracked files.
- Phase 4 what-if validation passed in the target subscription.
Step 2: Choose your deployment path
Use the platform selected in Phase 1 and implemented by Phase 4. Choose exactly one path.
Path A: All Container Apps (recommended default)
Use when both apps run as containers:
apps/apiruns as a Node.js container in Azure Container Apps.apps/webruns as a Vite static build served by nginx in Azure Container Apps.- Images are pushed to ACR and deployed by commit SHA tag.
- Container Apps revisions provide rollback. Phase 4 should have created Container Apps Environment, API app, web app, ACR, Log Analytics, App Insights, and managed identities.
Path B: SWA (web) + Container Apps (api)
Use when the web app should use Azure Static Web Apps and the API should remain containerized.
apps/webdeploys to SWA.apps/apideploys to Container Apps.- SWA handles static hosting and SPA fallback.
- Container Apps handles API revisions and scale.
Path C: SWA (web) + App Service Linux Node (api)
Use when the web app is static and the API is a non-container Linux Node.js App Service.
apps/webdeploys to SWA.apps/apideploys to App Service.- App Service provides slots, logs, and conventional web app operations.
Path D: AKS
Use AKS only if Phase 1 intentionally selected Kubernetes. Brief outline:
- Build API and web images.
- Push both images to ACR.
- Confirm AKS can pull from ACR.
- Update Helm chart values with the commit SHA tags.
- Deploy with Helm.
- Run migrations as a Helm hook, Kubernetes Job, or release task.
- Validate ingress, TLS, probes, telemetry, and smoke tests. Example:
helm upgrade --install $appName ./infra/helm/$appName `
--namespace $envName `
--create-namespace `
--values ./infra/helm/values.$envName.yaml `
--set image.api.tag=$TAG `
--set image.web.tag=$TAG
Step 3 — Path A: All Container Apps
Use this path when both apps/api and apps/web deploy as Azure Container Apps.
3A.1 Build & push images
Set variables.
$appName = "<app-name>"
$envName = "<env>"
$ACR = "<acr-name>"
$TAG = (git rev-parse --short HEAD)
Fail if the SHA tag is missing.
if ([string]::IsNullOrWhiteSpace($TAG)) { throw "Commit SHA tag was not resolved" }
Log in to ACR.
az acr login --name $ACR
Build and push the API image.
# api
docker build -t "$ACR.azurecr.io/$appName-api:$TAG" ./apps/api
docker push "$ACR.azurecr.io/$appName-api:$TAG"
Build and push the web image.
# web (containerized nginx)
docker build --build-arg VITE_API_URL=https://<api-fqdn> -t "$ACR.azurecr.io/$appName-web:$TAG" ./apps/web
docker push "$ACR.azurecr.io/$appName-web:$TAG"
Log after successful image build + push:
| <ts> | Phase 5 | — | Built + pushed api image :<sha> to <ACR> for env=<env> | ✅ | <image-name> |Never deploy:latestalone.
3A.2 Deploy via azd
Use Azure Developer CLI when azure.yaml is wired for this path.
azd up
azd up provisions and deploys in one command.
The first run prompts for environment name, region, and subscription.
Confirm the subscription before continuing.
Capture outputs without exposing secrets.
azd env get-values
3A.3 Alternative direct az cli
Use direct CLI when azd up is not wired for image deployment.
az deployment group create `
--resource-group rg-<app>-<env> `
--template-file infra/main.bicep `
--parameters "@infra/parameters.<env>.json" `
--parameters containerImageApi="$ACR.azurecr.io/$appName-api:$TAG" `
containerImageWeb="$ACR.azurecr.io/$appName-web:$TAG"
az containerapp update --name ca-$appName-api-<env> --resource-group rg-<app>-<env> --image "$ACR.azurecr.io/$appName-api:$TAG"
az containerapp update --name ca-$appName-web-<env> --resource-group rg-<app>-<env> --image "$ACR.azurecr.io/$appName-web:$TAG"
Log after successful Container App update:
| <ts> | Phase 5 | — | Updated Container App <name> to image :<sha> for env=<env> | ✅ | FQDN https://<fqdn> |Log after successful web deployment:| <ts> | Phase 5 | — | Deployed web to <target> for env=<env> | ✅ | https://<web-fqdn> |Verify revisions and image tags.
az containerapp revision list `
--name ca-$appName-api-<env> `
--resource-group rg-<app>-<env> `
--query "[].{name:name,active:properties.active,traffic:properties.trafficWeight,image:properties.template.containers[0].image}" `
-o table
Repeat for the web Container App and verify both images use $TAG.
Step 4 — Path B: SWA (web) + Container Apps (api)
Use this path when apps/web deploys to SWA and apps/api deploys to Container Apps.
4.1 Deploy api same as 3A.1 + 3A.2 minus the web
Build and push only the API image.
$appName = "<app-name>"
$envName = "<env>"
$ACR = "<acr-name>"
$TAG = (git rev-parse --short HEAD)
az acr login --name $ACR
docker build -t "$ACR.azurecr.io/$appName-api:$TAG" ./apps/api
docker push "$ACR.azurecr.io/$appName-api:$TAG"
Log after successful image build + push:
| <ts> | Phase 5 | — | Built + pushed api image :<sha> to <ACR> for env=<env> | ✅ | <image-name> |Deploy throughazd upif configured.
azd up
Or update the API container app directly.
az containerapp update `
--name ca-$appName-api-<env> `
--resource-group rg-<app>-<env> `
--image "$ACR.azurecr.io/$appName-api:$TAG"
Log after successful Container App update:
| <ts> | Phase 5 | — | Updated Container App <name> to image :<sha> for env=<env> | ✅ | FQDN https://<fqdn> |Capture the API FQDN.
$apiFqdn = az containerapp show `
--name ca-$appName-api-<env> `
--resource-group rg-<app>-<env> `
--query "properties.configuration.ingress.fqdn" `
-o tsv
4.2 Web deployment via SWA CLI
Install the SWA CLI.
npm install -g @azure/static-web-apps-cli
Get the deployment token.
az staticwebapp secrets list --name <swa-name> --query "properties.apiKey" -o tsv
Build and deploy the web app.
cd apps/web
pnpm build
swa deploy ./dist --deployment-token $env:SWA_DEPLOYMENT_TOKEN --env production
Log after successful web deployment:
| <ts> | Phase 5 | — | Deployed web to <target> for env=<env> | ✅ | https://<web-fqdn> |If the API URL is injected at build time, setVITE_API_URL=https://<api-fqdn>beforepnpm build. Verify SWA default hostname and SPA fallback.
Step 5 — Path C: SWA + App Service
Use this path when apps/web deploys to SWA and apps/api deploys to Linux App Service.
5.1 Web same as Path B
Use Step 4.2 for web deployment. Build with the App Service API URL.
cd apps/web
$env:VITE_API_URL = "https://app-$appName-api-<env>.azurewebsites.net"
pnpm build
swa deploy ./dist --deployment-token $env:SWA_DEPLOYMENT_TOKEN --env production
Log after successful web deployment:
| <ts> | Phase 5 | — | Deployed web to <target> for env=<env> | ✅ | https://<web-fqdn> |
5.2 Api via az webapp deploy OR azd up
Build and deploy the API.
cd apps/api
pnpm build
az webapp up --name app-$appName-api-<env> --resource-group rg-<app>-<env> --runtime "NODE:20-lts"
az webapp config set --name app-$appName-api-<env> --resource-group rg-<app>-<env> --startup-file "node dist/index.js"
az webapp config appsettings set --name app-$appName-api-<env> --resource-group rg-<app>-<env> --settings NODE_ENV=production ...
Use zip deploy when a package is prepared.
az webapp deploy `
--name app-$appName-api-<env> `
--resource-group rg-<app>-<env> `
--src-path .\api-package.zip `
--type zip
Or use azd up if the App Service path is configured.
azd up
Log after successful API deployment:
| <ts> | Phase 5 | — | Updated app service <name> for env=<env> | ✅ | FQDN https://<fqdn> |Do not proceed until/healthreturns 200.
Step 6: Database migration
Use the sqlserver-to-postgres-migration skill folder as the reference.
Choose the branch matching the Phase 2 and Phase 4 database strategy.
6.1 If PostgreSQL is the target
Use this when the target database is Azure Database for PostgreSQL Flexible Server. First-time data migration from on-prem SQL Server can use pgloader or Azure Database Migration Service.
# pgloader (one-shot, best for smaller DBs)
docker run --rm -v {{PWD}}:/data dimitri/pgloader pgloader /data/sqlserver-to-postgres.load
Use Azure Database Migration Service for larger databases, low-downtime moves, or production cutovers.
Run repeatable ORM migrations using the tool in apps/api.
Prisma:
pnpm --filter api prisma migrate deploy
Drizzle:
pnpm --filter api drizzle-kit push
For production Drizzle, prefer committed migration files or an approved app migration runner. TypeORM:
pnpm --filter api typeorm migration:run
node-pg-migrate:
pnpm --filter api migrate up
Grant DB access to the API managed identity. Connect as Entra admin and run:
SELECT * FROM pgaadauth_create_principal('<api-app-name>', false, false);
Then grant least-privilege schema rights.
GRANT CONNECT ON DATABASE <database_name> TO "<api-app-name>";
GRANT USAGE ON SCHEMA public TO "<api-app-name>";
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO "<api-app-name>";
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO "<api-app-name>";
Seed reference data if needed.
pnpm --filter api seed
Log after successful DB migration:
| <ts> | Phase 5 | — | Ran DB migrations against <env> DB | ✅ | <N> migrations applied |
6.2 If keeping SQL Server
Use this when retaining Azure SQL, SQL Managed Instance, or on-prem SQL Server through ExpressRoute / VPN. Run TypeORM migrations against Azure SQL.
pnpm --filter api typeorm migration:run
For other migration tools, run the equivalent production migration command. Grant the API managed identity database access. Entra admin executes:
CREATE USER [<api-app>] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [<api-app>];
ALTER ROLE db_datawriter ADD MEMBER [<api-app>];
Grant execute if stored procedures are used.
GRANT EXECUTE TO [<api-app>];
If SQL Server remains on-prem, verify networking, DNS, firewall rules, TLS, auth strategy, and connection pool limits.
Log after successful DB migration:
| <ts> | Phase 5 | — | Ran DB migrations against <env> DB | ✅ | <N> migrations applied |
Step 7: Post-deploy configuration
Complete platform configuration after compute and database deployment.
7.1 Verify DNS + custom domain
If using a custom domain, validate DNS records and certificates.
az network dns record-set cname show `
--resource-group <dns-rg> `
--zone-name <domain> `
--name <record-name>
Check endpoints.
curl -I https://<web-fqdn>
curl -I https://<api-fqdn>/health
7.2 Configure APIM subscription keys for the api
If APIM is part of Phase 4, verify:
- API backend URL points to the deployed API host.
- Subscription keys are required only where intended.
- Named values use Key Vault for secrets.
- Managed identity is enabled for APIM where needed.
- CORS and auth policies match the web origin.
- Rate limiting and quota policies match the environment. List subscriptions without printing keys.
az apim subscription list `
--resource-group rg-<app>-<env> `
--service-name apim-<app>-<env> `
--query "[].{name:name,scope:scope,state:state}" `
-o table
7.3 Import OpenAPI spec into APIM
Import a fresh OpenAPI spec or update the existing API.
az apim api import `
--resource-group rg-<app>-<env> `
--service-name apim-<app>-<env> `
--api-id <api-id> `
--path api `
--specification-format OpenApiJson `
--specification-path .\apps\api\openapi.json
Verify operations, backend URL, auth policy, subscription policy, and test console calls.
Step 8: Smoke tests
Run smoke tests against deployed Azure URLs. Do not declare success until all required tests pass or an exception is documented with an owner.
8.1 Backend health
curl https://<api-fqdn>/health
Expected:
- HTTP 200.
- Healthy or intentionally degraded response body.
- No startup errors in logs.
8.2 Frontend deep link
curl -I https://<web-fqdn>/some/route/123
Expected:
- HTTP 200.
- HTML response.
- Browser refresh loads the SPA shell.
8.3 Auth flow
Browser flow:
- Open deployed web URL.
- Sign in with MSAL.
- Get token.
- Call protected
/api/...endpoint. - Confirm authorized data returns. Expected:
- Redirect URI matches deployed host.
- Token audience matches API.
- Missing or invalid tokens are rejected.
- Valid tokens are accepted.
8.4 Real-time
Test:
- Connect WebSocket.
- Subscribe channel.
- Trigger a
NOTIFYvia test mutation. - Observe event on client. Expected:
- WSS connection succeeds.
- Protected sockets authenticate.
- Event arrives without page refresh.
- No reconnect loop appears in logs.
8.5 Data
Test create/edit/delete. Expected:
- Entity create persists.
- Entity edit persists after refresh.
- Entity delete or soft-delete follows business rules.
- List refreshes with current database state.
- Validation messages match migrated rules.
8.6 App Insights
Open Live Metrics and check Log Analytics.
requests
| where timestamp > ago(30m)
| summarize count(), failures=countif(success == false) by cloud_RoleName
dependencies
| where timestamp > ago(30m)
| summarize count(), failures=countif(success == false) by cloud_RoleName, target
exceptions
| where timestamp > ago(30m)
| project timestamp, cloud_RoleName, type, outerMessage
| order by timestamp desc
Expected:
- Live Metrics visible.
- Requests appear.
- Dependencies appear.
- Exceptions show no new unhandled deployment failures.
Log after smoke tests:
| <ts> | Phase 5 | — | Smoke test <env> | ✅ or ❌ | <passing>/<total> checks |
Step 9: Validate observability & security
Perform final platform checks.
9.1 HTTPS enforced
curl -I http://<web-fqdn>
curl -I http://<api-fqdn>/health
9.2 CSP headers present on web
curl -I https://<web-fqdn>
Expected headers:
content-security-policyx-content-type-optionsreferrer-policystrict-transport-securitywhere supported Tune CSP intentionally; do not disable it to hide violations.
9.3 Managed identity in use
Container Apps:
az containerapp identity show --name ca-$appName-api-<env> --resource-group rg-<app>-<env>
App Service:
az webapp identity show --name app-$appName-api-<env> --resource-group rg-<app>-<env>
List app setting names without printing values.
az webapp config appsettings list `
--name app-$appName-api-<env> `
--resource-group rg-<app>-<env> `
--query "[].name" `
-o table
9.4 Log Analytics receiving logs from both apps
Container Apps:
ContainerAppConsoleLogs_CL
| where TimeGenerated > ago(30m)
| summarize count() by ContainerAppName_s
Application Insights:
requests
| where timestamp > ago(30m)
| summarize count() by cloud_RoleName
Step 10: Generate Deployment Report
Create reports/Deployment-Report.md with this template.
# Deployment Report
**Application**: [Name]
**Deployment Date**: [Date/Time]
**Environment**: [dev / staging / prod]
**Prepared By**: [Name]
**Source Commit**: [commit SHA]
## Deployment Details
| Property | Value |
|----------|-------|
| Platform | [Container Apps / SWA + Container Apps / SWA + App Service / AKS] |
| Region | [e.g., eastus] |
| Azure Subscription | [subscription name or redacted ID] |
| Resource Group | rg-<app>-<env> |
| API Host | https://<api-fqdn> |
| Web Host | https://<web-fqdn> |
| Database | [Azure PostgreSQL Flexible Server / Azure SQL / SQL Server] |
| Container Registry | [ACR name, if applicable] |
| App Insights | [name] |
| Log Analytics Workspace | [name] |
## Endpoints
| Service | URL | Auth Required | Notes |
|---------|-----|---------------|-------|
| Web | https://<web-fqdn> | Yes/No | Vite React app |
| API health | https://<api-fqdn>/health | No | Must return 200 |
| API base | https://<api-fqdn>/api | Yes | Protected API |
| APIM gateway | https://<apim-name>.azure-api.net/api | Yes/Key | If applicable |
| App Insights | https://portal.azure.com/#resource/... | Azure RBAC | Operations view |
## Configuration Verified Checklist
- [ ] Correct Azure subscription confirmed before deploy
- [ ] `pnpm build` passed before deploy
- [ ] Phase 4 what-if / plan validation passed
- [ ] API deployment completed
- [ ] Web deployment completed
- [ ] Database migrations completed
- [ ] Managed identity enabled for API
- [ ] No client secrets stored in app settings
- [ ] App Insights connection configured
- [ ] Log Analytics receiving logs
- [ ] HTTPS enforced
- [ ] Certificate valid
- [ ] CSP headers present on web
- [ ] APIM configured, if applicable
- [ ] Custom domain configured, if applicable
## Smoke Test Results
| Test | Evidence | Expected | Actual | Result |
|------|----------|----------|--------|--------|
| Backend health | `curl https://<api-fqdn>/health` | 200 | [value] | ✅/❌ |
| Frontend deep link | `curl -I https://<web-fqdn>/some/route/123` | 200 | [value] | ✅/❌ |
| Auth sign-in | Browser MSAL flow | Token acquired | [value] | ✅/❌ |
| Protected API | Browser/API call | Authorized data | [value] | ✅/❌ |
| Real-time | WebSocket + NOTIFY | Event received | [value] | ✅/❌ |
| Create entity | UI/API | Entity persisted | [value] | ✅/❌ |
| Edit entity | UI/API | Changes persisted | [value] | ✅/❌ |
| Delete entity | UI/API | Entity removed/marked | [value] | ✅/❌ |
| App Insights | Live Metrics / KQL | Telemetry visible | [value] | ✅/❌ |
## Performance Baseline
| Metric | Baseline Value | Tool / Source | Notes |
|--------|----------------|---------------|-------|
| Initial page load | [ms] | Browser DevTools / Lighthouse | First deployed baseline |
| API p50 latency | [ms] | App Insights requests | 30-minute smoke window |
| API p95 latency | [ms] | App Insights requests | 30-minute smoke window |
| JS bundle size | [KB/MB] | Vite build output | Include gzip if available |
| CSS bundle size | [KB/MB] | Vite build output | Include gzip if available |
## Operational Procedures
### Troubleshooting
| Problem | Diagnostic | Fix |
|---------|------------|-----|
| API `/health` returns 500 | App logs / exceptions | Verify env vars, DB permissions, migrations |
| API returns 401 | Browser token + API logs | Verify Entra audience and scopes |
| CORS errors | Browser DevTools | Add deployed web origin to API allowlist |
| 404 on deep links | `curl -I /some/route` | Fix SWA config or nginx fallback |
| Container revision failing | Container App logs | Check port, startup command, and image |
| App Service startup failure | `az webapp log tail` | Verify `node dist/index.js` and package contents |
| DB permission errors | API logs / DB audit | Re-run managed identity grants |
| No telemetry | App Insights queries | Verify connection string and SDK initialization |
### Rollback per Platform
- **Container Apps**: activate previous healthy revision and shift traffic back.
- **Static Web Apps**: redeploy the previous commit artifact.
- **App Service**: swap back to previous slot or redeploy previous zip.
- **AKS**: run `helm rollback <release-name> <revision> --namespace <namespace>`.
## Cost Snapshot
Record after 24 hours if possible.
| Component | SKU | Observed 24h Cost | Monthly Estimate | Notes |
|-----------|-----|-------------------|------------------|-------|
| Web hosting | [SKU] | [$] | [$] | SWA / Container App / AKS |
| API hosting | [SKU] | [$] | [$] | Container App / App Service / AKS |
| Database | [SKU] | [$] | [$] | PostgreSQL / SQL |
| ACR | [SKU] | [$] | [$] | If container path |
| App Insights | Pay-as-you-go | [$] | [$] | Based on ingestion |
| Log Analytics | PerGB | [$] | [$] | Based on ingestion |
| APIM | [SKU] | [$] | [$] | If applicable |
| **Total** | — | **[$]** | **[$]** | |
Do not include raw secrets, deployment tokens, or full connection strings in the report.
---
## Step 11: Update Status Report
Update `reports/Report-Status.md` after deployment and smoke tests complete.
Record:
- Phase 5 status
- Deployment date and time
- Target environment
- Platform path used
- Web URL
- API URL
- Database migration status
- Smoke test summary
- Link to `reports/Deployment-Report.md`
- Known issues or exceptions
- Phase 6 readiness
Suggested entry:
```markdown
## Phase 5 — Deploy to Azure
**Status**: Complete
**Completed**: [date/time]
**Deployment Path**: [Path A / B / C / D]
**Environment**: [dev/staging/prod]
**Web URL**: https://<web-fqdn>
**API URL**: https://<api-fqdn>
**Database Migration**: [Complete / Not required / Blocked]
**Smoke Tests**: [Passed / Failed]
**Deployment Report**: `reports/Deployment-Report.md`
### Phase 6 Readiness
- [ ] Deployment artifacts and commands are known
- [ ] Secrets are identified for GitHub Actions / federated identity
- [ ] Smoke tests can be automated
- [ ] Rollback path is documented
If any smoke test fails, mark Phase 5 as blocked and document evidence, owner, and next action.
Step N: Update session memory (always run last)
Before declaring Phase 5 complete for the current environment, update reports/Report-Status.md:
- Append final Activity Log entry at the TOP:
| <ts UTC> | Phase 5 | — | Phase 5 complete for env=<env>: web + api deployed, DB migrated, smoke tests passed | ✅ | https://<web-fqdn> + https://<api-fqdn> + reports/Deployment-Report.md | - Update the Phase 5 block in "Phase Summaries" with the environment, URLs, DB migration counts, smoke test results.
- Update the "Overall Progress" table row for Phase 5: ✅ Complete + timestamp (if all target environments deployed). If only some environments are done, leave as ⏳ In Progress with note.
- Update "Session State":
- If more environments remain to deploy (e.g., only staging done, prod still pending): keep
Current PhaseasPhase 5andNext Actionas/phase5-deploytoazure(for the next env). - Otherwise:
Current Phase→Phase 6 — CI/CD Setup,Next Action→/phase6-setupcicd. Last Session Ended→ this timestamp + "Phase 5 complete"Active Skills Loaded→ for Phase 6:azure-fullstack-deployment, auth-and-security-migration(federated credentials)
- If more environments remain to deploy (e.g., only staging done, prod still pending): keep
- Update
Last Updatedat the top. Then report a summary and recommend the next command.
Rules & Constraints
@agent rule: ALWAYS run Step 0 (Load session memory) before any other action in this phase
@agent rule: ALWAYS log each deployment sub-step (image build, container update, DB migration, smoke test) with outcome
@agent rule: ALWAYS include the target environment (dev/staging/prod) in Phase 5 log entries
@agent rule: NEVER re-deploy a resource that the Activity Log shows as already deployed for this session (unless the user explicitly requests it)
@agent rule: ALWAYS run the final "Update session memory" step before declaring Phase 5 complete
@agent rule: Never deploy without successful local pnpm build
@agent rule: Never deploy without Phase 4 what-if validation passing
@agent rule: Confirm target subscription BEFORE deploying
@agent rule: Always tag container images with commit sha (never :latest alone)
@agent rule: Do NOT expose secrets in az cli output (use --query to filter)
@agent rule: Do NOT store deployment tokens in the repo (use GitHub secrets in Phase 6)
@agent rule: ALWAYS run smoke tests before declaring success
Deliverables
- Azure deployment completed using the Phase 1 selected platform.
-
apps/apideployed and reachable over HTTPS. -
apps/webdeployed and reachable over HTTPS. - Database migration completed or documented as not required.
- API managed identity granted database access where supported.
- Environment variables configured without repo-stored secrets.
- APIM configured and OpenAPI imported or updated, if applicable.
- DNS and custom domain verified, if applicable.
- HTTPS enforced and certificate valid.
- CSP and security headers verified on web.
- Backend health smoke test passed.
- Frontend deep-link smoke test passed.
- Auth flow smoke test passed.
- Real-time smoke test passed, if applicable.
- Data create/edit/delete smoke test passed.
- App Insights Live Metrics and KQL validation completed.
- Log Analytics receiving logs from both apps where supported.
- Rollback procedure documented for the selected platform.
- Performance baseline captured.
- Cost snapshot plan documented, with 24-hour snapshot added if possible.
-
reports/Deployment-Report.mdcreated. -
reports/Report-Status.mdupdated. - Phase 6 CI/CD inputs are identified.
Next Step:
/phase6-setupcicdto automate build, test, security checks, and deployment.