Files
The-transit-Project/.github/agents/azure-deploy/deploy/references/code-deployment-functions-flex.md
T
Sven laptop 635a130f0b
Build and Push Docker Images / detect-changes (push) Successful in 11s
Build and Push Docker Images / build-auth-api (push) Successful in 1m0s
Build and Push Docker Images / build-employee-api (push) Successful in 1m2s
Build and Push Docker Images / build-transit-api (push) Successful in 1m1s
Build and Push Docker Images / build-error-log-api (push) Successful in 1m5s
Build and Push Docker Images / build-admin-ui (push) Successful in 1m13s
Build and Push Docker Images / build-monitoring-ui (push) Successful in 1m15s
Build and Push Docker Images / deploy-test-node (push) Successful in 3s
──────
### Summary of Changes
  1. Documentation Consolidation:
      • Relocated the docs/ folder and all repository .md files (README.md, DEPLOYMENT.md, DOCKER_README.md,
      DOMAINS_README.md, GETTING_STARTED.md, CI_CD_PORTAINER_GUIDE.md, ADMIN_DEPLOYMENT_SUMMARY.md,
      SECURITY_PRIVATE_FILES.md, handoff.md, azure-project-plan.md, plus service-specific READMEs) into .
      • Updated document links in README.md.
  2. AI Agent Project Map:
      • Created PROJECT_MAP.md in the project root containing complete architecture diagrams, service specs, ports, DB
      schemas, environment variables, and developer workflows.
      • Added PROJECT_MAP.md to .gitignore.
  3. Monitoring UI & Infrastructure Integration:
      • Added monitoring_ui service to docker-compose.yml (port 5175).
      • Configured Gitea workflow docker-build.yml for monitoring_ui builds.
      • Added CORS middleware headers in index.js.
      • Added nginx.conf copy step in Dockerfile.

  ──────
  ### Recommended Commit Message

    docs: consolidate project documentation into monitoring_ui and add agent project map

    - Move all markdown documentation files and docs/ folder into monitoring_ui/docs/
    - Update documentation hub index (monitoring_ui/docs/README.md) with relative paths
    - Generate comprehensive AI agent reference map (PROJECT_MAP.md) in repository root
    - Add PROJECT_MAP.md and monitoring_ui build output/env overrides to .gitignore
    - Integrate monitoring_ui service into docker-compose.yml and Gitea CI workflow
    - Configure CORS handling in employee_api for monitoring dashboard access
    ──────
  ### Alternative Short Commit Message

    refactor(docs): move docs to monitoring_ui and create AI agent PROJECT_MAP.md
2026-09-20 23:33:55 +02:00

5.8 KiB

Important: This skill provides guidance and recommended instructions to assist the AI system. Outputs are not guaranteed to be complete, correct, secure, or applicable to every scenario. Results should be reviewed and validated by a human before being applied. The AI model may choose not to follow all instructions exactly, and additional verification may be required.

Code Deployment — Azure Functions (Flex Consumption)

How to deploy application code to a Flex Consumption function app after its IaC is provisioned. This is a different channel from App Service — read this instead of code-deployment-appservice.md whenever the compute is Functions on Flex Consumption (the default Functions floor). Only Functions on Premium (EP1) use the App Service SCM/Kudu path.

⛔ --subscription {subscriptionId} on EVERY az command.

The Flex deploy model (why the App Service path does not apply)

Flex Consumption has a single deployment path: you build and zip your project, the package is written to a blob storage container, and the app runs from that package on startup. There is no Kudu SCM_DO_BUILD_DURING_DEPLOYMENT/Oryx-on-SCM build, no az webapp deploy --type zip, and no basicPublishingCredentialsPolicies (scm/ftp) enable/re-disable dance. Do not run any of those against a Flex app — they either error or silently do nothing.

Deploy the package

Build/zip the project, then deploy with the Functions channel. Prefer a remote build for interpreted runtimes so native wheels/modules are built on Linux, not on the local machine:

# Python / Node / TypeScript — zip the PROJECT ROOT (manifest at the zip root) and request a remote build.
az functionapp deployment source config-zip `
  --subscription {sub} -g {rg} -n {app} `
  --src $zipPath --build-remote true

# .NET (isolated) / Java / Go — deploy a precompiled package (build output at the zip root); no remote build.
az functionapp deployment source config-zip --subscription {sub} -g {rg} -n {app} --src $zipPath

func azure functionapp publish {app} (Azure Functions Core Tools) is an equivalent channel and also performs a remote build — use it if Core Tools is already the project's workflow.

  • The runtime is fixed by functionAppConfig.runtime in IaC — do not pass or set FUNCTIONS_WORKER_RUNTIME.
  • The deploying identity writes the package to the deployment container. With shared-key access disabled, that identity (the signed-in user for a local deploy, or the CI principal) needs Storage Blob Data Contributor on the deployment storage account, in addition to the function app's own identity role.
  • After deploy, sync is automatic; then run the health check below.

⛔ Local (non-CI) deploys: hardening can lock you out — do not deny-by-default before first deploy

This pipeline hardens network access, which is CI/CD-friendly but can block a deploy run from a developer machine. Two Flex-specific facts matter:

  1. Flex outbound is a platform-managed gateway pool, not a per-instance IP. An SCM/site allow rule built from the deployer's observed public IP (e.g. via ipify) will not match the channel's real egress, so it does not unblock the deploy and often changes between attempts. Do not try to punch a /32 SCM hole to fix a 403 — it is the wrong lever for Flex.
  2. Model the main site and the deployment/SCM surface independently. Restricting one must not implicitly deny the other.

Rules for the deploy phase:

  • ⛔ Do NOT set publicNetworkAccess: 'Disabled' or a deny-by-default rule on the function app or its deployment storage BEFORE the first successful code deploy + health check. Provision with access open, deploy, verify, then harden.
  • Before hardening, tell the user (once, plainly): "This deployment hardens network access for production. Publishing the code from your machine happens first, while access is still open; after the app is healthy I'll restrict it. If you need to redeploy later from your machine, you may need to temporarily re-open access or deploy from CI."
  • If a package deploy returns HTTP 403, the cause is network hardening applied too early or a missing Storage Blob Data role — not a missing SCM allow rule. Re-open public access on the app + deployment storage, confirm the deployer's role assignment, redeploy, then re-harden. Never fall back to imperative provisioning.
  • ⛔ Azure inserts a terminal "Deny all" rule as the last entry of any ipSecurityRestrictions / scmIpSecurityRestrictions list — this is the expected default sentinel, NOT an error. Validation must treat a trailing deny-all with priority 2147483647 (name Deny all/Explicit deny) as normal. Only flag it if there are no preceding allow rules AND you intended the surface to be reachable.

Hardening (only AFTER a healthy deploy)

If the plan calls for a locked-down app, apply publicNetworkAccess/IP restrictions as the last step, after the health check passes. Keep the deployment storage reachable by the app identity. Record any access you re-open for a local deploy so cleanup is idempotent (re-running the step must not error if the rule is already gone).

Health check

HTTP GET the function endpoint(s) (max 3 iterations, honoring cold start). A Flex app can take up to ~30s to initialize on first start; System.TimeoutException/gRPC host messages during that window are startup noise, not deploy failures. Inspect the response body for error patterns (connection refused, MODULE_NOT_FOUND, SET-IN-DEPLOY-PHASE) — HTTP 200 alone is not proof of health when the app depends on another service.

Database post-deploy

⛔ If the app uses a managed database, run database-post-deploy.md for migration discovery and execution.