Both deploy paths now take their token values from
config/environments.yml instead of defining their own copies.
CI / shell path:
* scripts/ci/render_subs.py renders deployed files via agebd.subs.
* deploy-and-restart-service.sh drops its dev/prod if-else and its four
sed calls for one render_subs.py invocation, and aborts the deploy if
rendering fails rather than restarting a service whose files still
contain placeholders.
Ansible path:
* ansible/tasks/utils/load-substitutions.yml reads the central config on
the controller and exposes the token table for this environment.
* ioc-install and service-deploy-and-restart now loop over that table
instead of listing tokens inline, so a new token needs no ansible
edit.
* env_suffix_upper/lower are gone from both inventories. The inventory
says which environment it is; the central config says what that
environment means. The facts are renamed to agebd_env_suffix_upper /
_lower to match the token names, removing a rename trap.
Ansible keeps using ansible.builtin.replace rather than calling
agebd.subs, because ioc-install runs on hosts with no uv or Python
environment for this repo. Only the mechanism differs now; the values and
the token list are shared.
Verified: both playbook paths run locally against dev and prod and
produce the expected output, an undeclared environment fails loudly in
both paths, and a misspelled token exits non-zero instead of shipping the
placeholder.
Not addressed here, still step 5: ansible/tasks/utils/get-ioc-port.yml
matches CamelCase registry names against a lowercase input and returns
nothing, so the ansible ioc-install path cannot resolve a port. This is
pre-existing and unchanged by this commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>