Environment variables
There are two ways to use this tool, and the difference is one key.
Image only
Section titled “Image only”Leave env and envFrom out, and the tool sets the image tag and touches
nothing else. Every environment variable stays exactly as Terraform left it.
This needs no mode of its own, because a config that sets nothing merges nothing. The whole file:
cloud: provider: azure subscription: bbbf237a-8c9e-492a-b6a3-9b0bd4869690 resource_group: evolve-tst
services: purchase: version: 27ec167 targets: - { type: container-app, name: evolve-tst-purchase }Start here. Move to the other mode when you actually want a variable to change
on a deploy rather than on a terraform apply.
Environment under deploy control
Section titled “Environment under deploy control”Declare env, and those variables are laid over the ones the target already
carries. Terraform declares the environment; the config refines it. So listing
one variable sets one variable, and the other thirty keep the values Terraform
gave them.
services: purchase: version: 27ec167 env: LOG_LEVEL: info CTP_API_URL: https://api.europe-west1.gcp.commercetools.com CTP_CLIENT_SECRET: ${secret:purchase-server-token-commercetools} targets: - { type: container-app, name: evolve-tst-purchase }The trade is that the config sets but never removes. Deleting a variable means deleting it where it is declared, which is Terraform — the next release then carries that through.
The four layers
Section titled “The four layers”The environment a target ends up with is four layers, each with the last word over the one before it:
- What Terraform declares — everything already on the running resource.
envFrom— a JSON object expanded into the environment.env— the variables named in the config, service level then target level.strategy.env— for a blue-green service, the values for the side being staged. PlusEVOLVE_DEPLOY_SIDE, which the tool writes itself.
services: discover: version: abc1234 envFrom: - ${param:/evolve/${env}/discover/setup} # layer 2 env: LOG_LEVEL: debug # layer 3, wins over envFrom targets: - type: container-app name: evolve-tst-discover env: LOG_LEVEL: info # layer 3 too, and more specificenvFrom
Section titled “envFrom”envFrom expands a JSON object into the environment — what Terraform already
writes with jsonencode(local.env_vars):
resource "azurerm_app_configuration_key" "discover_setup" { key = "/evolve/tst/discover/setup" value = jsonencode(local.discover_env)}It must point at a parameter store, never a secret store, so bulk expansion
can never mean reading a secret. Anything in env wins over it, and both are
laid over what the target already carries.
Refusing to delete
Section titled “Refusing to delete”A variable can still disappear — when Terraform stops declaring one that a
running target has. apply refuses to be the release that carries that through
unless it is confirmed. Secrets are among the things that go this way:
$ evolve-deploy apply deploy/tst.yaml
Would delete 3 environment variable(s): - container-app/evolve-tst-purchase: API_EXTENSION_SECRET - container-app/evolve-tst-purchase: OTEL_EXPORTER_OTLP_HEADERS - container-app/evolve-tst-purchase: SENTRY_DSN
The deploy config only ever sets variables, so these are gone from whatTerraform declares. Put them back there if that was not intended.
error: refusing to delete 3 environment variable(s); pass --allow-env-removal if you meant itTwo ways out, and they are not equivalent:
- You meant it. Pass
--allow-env-removalon that one run. - You did not. Put them back in Terraform. The refusal is almost always
telling you that a
terraform applydid something you did not read.
diff shows the same list without failing, so a pipeline can see it coming.
Once env is in the config, extend ignore_changes
Section titled “Once env is in the config, extend ignore_changes”Terraform must stop trying to own what the deploy now owns:
lifecycle { ignore_changes = [ template[0].container[0].image, template[0].container[0].env, # add this once env moves into the config ]}Otherwise the two write over each other on alternate applies. See What Terraform must do.
Not managed
Section titled “Not managed”function-app targets manage no environment at all — see Clouds and
targets. Declaring env on one is an error.

