From 1fdb5faca48afaf5b1bf79f12afd3dafb01e593e Mon Sep 17 00:00:00 2001 From: "James N." Date: Tue, 9 Jun 2026 16:54:35 -0700 Subject: [PATCH] fix(infra): delegate Container Apps subnet + stop masking failed terraform apply PRODUCTION RECOVERY. Two bugs combined to take down the production Container Apps environment during the private-topology redeploy (#429): 1. The container_apps subnet had no delegation, so creating the VNet-integrated Container Apps environment failed with: ManagedEnvironmentSubnetDelegationError: The subnet of the environment must be delegated to the service 'Microsoft.App/environments'. Add the required delegation (Microsoft.App/environments + Microsoft.Network/virtualNetworks/subnets/join/action). 2. The deploy step ran 'terraform apply ... | tee' inside an if-condition with no pipefail, so the pipeline reported tee's (success) exit status and MASKED the failed apply. The old environment had already been destroyed, so the job went green while production was left with no environment and no container apps. Capture terraform's real exit code via PIPESTATUS so a failed apply fails the job instead of silently reporting success. With the delegation in place the environment can be (re)created, and the PIPESTATUS fix ensures any future apply failure surfaces instead of corrupting the environment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/infrastructure.yml | 8 +++++++- infra/terraform/network.tf | 11 +++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/infrastructure.yml b/.github/workflows/infrastructure.yml index f02e2302a..d02294204 100644 --- a/.github/workflows/infrastructure.yml +++ b/.github/workflows/infrastructure.yml @@ -124,7 +124,13 @@ jobs: terraform plan -out tfplan "${TF_VARS[@]}" - if terraform apply -auto-approve tfplan 2>&1 | tee /tmp/tf_apply.log; then + # Capture Terraform's exit code via PIPESTATUS — the pipe through + # `tee` otherwise reports tee's (success) status and masks a failed + # apply, which can leave the environment partially destroyed while + # the job reports success. + terraform apply -auto-approve tfplan 2>&1 | tee /tmp/tf_apply.log + apply_rc=${PIPESTATUS[0]} + if [ "$apply_rc" -eq 0 ]; then echo "✅ Terraform apply succeeded" break fi diff --git a/infra/terraform/network.tf b/infra/terraform/network.tf index 77ec1aaa9..31da737c7 100644 --- a/infra/terraform/network.tf +++ b/infra/terraform/network.tf @@ -17,6 +17,17 @@ resource "azurerm_subnet" "container_apps" { resource_group_name = azurerm_resource_group.rg.name virtual_network_name = azurerm_virtual_network.vnet[0].name address_prefixes = [var.container_apps_subnet_prefix] + + # Container App Environments require the infrastructure subnet to be + # delegated to Microsoft.App/environments, otherwise creation fails with + # ManagedEnvironmentSubnetDelegationError (400). + delegation { + name = "Microsoft.App.environments" + service_delegation { + name = "Microsoft.App/environments" + actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"] + } + } } # Subnet for Private Endpoints