Phase C of the multi-env extension to the new-web-app runbook conventions discussed in the design thread. Pure refactor — prod helm render is byte-identical (10857 bytes both before and after, diff exit 0).
This PR ONLY templates the chart and prepares the sandbox overlay. It does NOT activate sandbox (the factory tfvars schema change, the tools app_roles module evolution, the actual sandbox iac/main.tf for_each, the ArgoCD app, the DB and Vault paths — none of those are touched here).
What changes
5 chart template files had a hardcoded erp / creds/erp / erp/config / erp.arcodange.lab literal — now they read from .Values.*:
The elision rule (env=prod → no suffix, env=non-prod → <app>-<env> suffix) keeps the prod render character-for-character identical.
chart/values-sandbox.yaml is added as the ready-to-use overlay for Phase D. NOT wired into any helm install or ArgoCD app today — the platform side isn't evolved yet. The file documents the convention so the Phase D commit can simply helm install -f values.yaml -f values-sandbox.yaml.
Bonus fix
.gitea/workflows/vault.yaml had a real CI bug: the vault_step JWT role was gitea_cicd_webapp (copy-paste leftover from the template repo) instead of gitea_cicd_erp. The erp repo's CI would have failed JWT auth against Vault. Bundled here because it touches the same file family and is a 1-line fix.
Verification
# Before refactor (captured on origin/main)
helm template erp chart/ --namespace erp > /tmp/before.yaml # 10857 bytes# After refactor (this branch)
helm template erp chart/ --namespace erp > /tmp/after.yaml # 10857 bytes
diff /tmp/before.yaml /tmp/after.yaml # exit 0, no output
Sandbox overlay smoke test:
helm template erp chart/ -f chart/values.yaml -f chart/values-sandbox.yaml --namespace erp-sandbox
# All substitutions produce erp-sandbox / creds/erp-sandbox / DOLI_URL_ROOT=https://erp-sandbox.arcodange.lab
What's NOT in this PR (Phases A, B, D, E)
Phase A — arcodange-org/tools/hashicorp-vault/iac/modules/app_roles: add optional env parameter (default "prod") + compute local.instance + propagate to derived names. Additive change, backwards-compatible for every app that doesn't set env.
Phase B — arcodange-org/factory: postgres/iac tfvars schema (set(string) → list(object({name, envs})) with envs defaulting to ["prod"]), argocd templates render one Application per env, conventions.md updated.
Phase D — when A+B+C are merged: this repo's iac/main.tf switches to for_each over local.envs = toset(["prod", "sandbox"]), factory tfvars adds envs = ["prod", "sandbox"] to erp.
Phase E — ArgoCD Application "erp-sandbox" registered, DNS for erp-sandbox.arcodange.lab provisioned.
.gitea/workflows/vault.yaml CI still triggers cleanly (the typo fix is the actual unblock)
ArgoCD picks up the new manifest with no spec drift (Phase D will introduce real drift; this PR alone should be silent)
## Summary
Phase C of the multi-env extension to the new-web-app runbook conventions discussed in the design thread. **Pure refactor — prod helm render is byte-identical** (10857 bytes both before and after, `diff` exit 0).
This PR ONLY templates the chart and prepares the sandbox overlay. It does NOT activate sandbox (the factory tfvars schema change, the tools `app_roles` module evolution, the actual sandbox iac/main.tf for_each, the ArgoCD app, the DB and Vault paths — none of those are touched here).
### What changes
5 chart template files had a hardcoded `erp` / `creds/erp` / `erp/config` / `erp.arcodange.lab` literal — now they read from `.Values.*`:
| File | Before | After |
|---|---|---|
| `chart/templates/vaultauth.yaml` | `role: erp` | `role: {{ .Values.vault.k8sRole }}` |
| `chart/templates/vaultdynamicsecret.yaml` | `path: creds/erp` | `path: {{ .Values.vault.dynamicPath }}` |
| `chart/templates/vaultsecret.yaml` | `path: erp/config` | `path: {{ .Values.vault.staticPath }}` |
| `chart/templates/config.yaml` | `DOLI_DB_NAME: erp` + `DOLI_URL_ROOT: https://erp.arcodange.lab` | `DOLI_DB_NAME: {{ .Values.db.name }}` + `DOLI_URL_ROOT: 'https://{{ .Values.host }}'` |
`chart/values.yaml` gains a documented multi-env coordinate block at the top with prod defaults:
```yaml
env: prod
instance: erp
host: erp.arcodange.lab
db:
name: erp
vault:
k8sRole: erp
dynamicPath: creds/erp
staticPath: erp/config
```
The elision rule (env=prod → no suffix, env=non-prod → `<app>-<env>` suffix) keeps the prod render character-for-character identical.
`chart/values-sandbox.yaml` is added as the **ready-to-use overlay** for Phase D. NOT wired into any helm install or ArgoCD app today — the platform side isn't evolved yet. The file documents the convention so the Phase D commit can simply `helm install -f values.yaml -f values-sandbox.yaml`.
### Bonus fix
`.gitea/workflows/vault.yaml` had a real CI bug: the vault_step JWT role was `gitea_cicd_webapp` (copy-paste leftover from the template repo) instead of `gitea_cicd_erp`. The erp repo's CI would have failed JWT auth against Vault. Bundled here because it touches the same file family and is a 1-line fix.
### Verification
```sh
# Before refactor (captured on origin/main)
helm template erp chart/ --namespace erp > /tmp/before.yaml # 10857 bytes
# After refactor (this branch)
helm template erp chart/ --namespace erp > /tmp/after.yaml # 10857 bytes
diff /tmp/before.yaml /tmp/after.yaml # exit 0, no output
```
Sandbox overlay smoke test:
```sh
helm template erp chart/ -f chart/values.yaml -f chart/values-sandbox.yaml --namespace erp-sandbox
# All substitutions produce erp-sandbox / creds/erp-sandbox / DOLI_URL_ROOT=https://erp-sandbox.arcodange.lab
```
## What's NOT in this PR (Phases A, B, D, E)
- **Phase A** — `arcodange-org/tools/hashicorp-vault/iac/modules/app_roles`: add optional `env` parameter (default `"prod"`) + compute `local.instance` + propagate to derived names. Additive change, backwards-compatible for every app that doesn't set `env`.
- **Phase B** — `arcodange-org/factory`: postgres/iac tfvars schema (`set(string)` → `list(object({name, envs}))` with `envs` defaulting to `["prod"]`), argocd templates render one Application per env, conventions.md updated.
- **Phase D** — when A+B+C are merged: this repo's `iac/main.tf` switches to `for_each` over `local.envs = toset(["prod", "sandbox"])`, factory tfvars adds `envs = ["prod", "sandbox"]` to erp.
- **Phase E** — ArgoCD Application "erp-sandbox" registered, DNS for `erp-sandbox.arcodange.lab` provisioned.
## Test plan
- [ ] `helm template erp chart/ --namespace erp` byte-identical to origin/main (`diff` exit 0)
- [ ] `helm template erp chart/ -f chart/values.yaml -f chart/values-sandbox.yaml --namespace erp-sandbox` produces erp-sandbox derived names everywhere
- [ ] `.gitea/workflows/vault.yaml` CI still triggers cleanly (the typo fix is the actual unblock)
- [ ] ArgoCD picks up the new manifest with no spec drift (Phase D will introduce real drift; this PR alone should be silent)
Phase C of the multi-env evolution discussed in the runbook design thread
(see PR description). Pure refactor — the prod helm template render is
verified byte-identical (10857 bytes both before and after, diff exit 0).
What was hardcoded, now templated:
- chart/templates/vaultauth.yaml role: erp → role: {{ .Values.vault.k8sRole }}
- chart/templates/vaultdynamicsecret.yaml path: creds/erp → path: {{ .Values.vault.dynamicPath }}
- chart/templates/vaultsecret.yaml path: erp/config → path: {{ .Values.vault.staticPath }}
- chart/templates/config.yaml DOLI_DB_NAME: erp → DOLI_DB_NAME: {{ .Values.db.name }}
DOLI_URL_ROOT: https://erp..lab → DOLI_URL_ROOT: 'https://{{ .Values.host }}'
values.yaml gains a documented multi-env coordinate block with prod defaults
(env, instance, host, db.name, vault.k8sRole, vault.dynamicPath, vault.staticPath).
The elision rule (env=prod → no suffix, env=non-prod → "<app>-<env>" suffix)
guarantees the prod render is unchanged.
chart/values-sandbox.yaml is added as the ready-to-use overlay for Phase D.
It is NOT wired into any helm install / ArgoCD app today — the platform side
(factory/postgres/iac tfvars, tools/hashicorp-vault/iac module signature) is
not yet evolved. The file documents the convention so the Phase D commit can
just `helm install -f values.yaml -f values-sandbox.yaml`.
Also fixes .gitea/workflows/vault.yaml CI typo: the vault_step JWT role was
gitea_cicd_webapp (copy-paste from the template repo) instead of
gitea_cicd_erp. Real bug — the erp CI would have failed JWT auth against
Vault. Fix unrelated to multi-env but bundled here because it's small and
touches the same file family.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Phase C of the multi-env extension to the new-web-app runbook conventions discussed in the design thread. Pure refactor — prod helm render is byte-identical (10857 bytes both before and after,
diffexit 0).This PR ONLY templates the chart and prepares the sandbox overlay. It does NOT activate sandbox (the factory tfvars schema change, the tools
app_rolesmodule evolution, the actual sandbox iac/main.tf for_each, the ArgoCD app, the DB and Vault paths — none of those are touched here).What changes
5 chart template files had a hardcoded
erp/creds/erp/erp/config/erp.arcodange.labliteral — now they read from.Values.*:chart/templates/vaultauth.yamlrole: erprole: {{ .Values.vault.k8sRole }}chart/templates/vaultdynamicsecret.yamlpath: creds/erppath: {{ .Values.vault.dynamicPath }}chart/templates/vaultsecret.yamlpath: erp/configpath: {{ .Values.vault.staticPath }}chart/templates/config.yamlDOLI_DB_NAME: erp+DOLI_URL_ROOT: https://erp.arcodange.labDOLI_DB_NAME: {{ .Values.db.name }}+DOLI_URL_ROOT: 'https://{{ .Values.host }}'chart/values.yamlgains a documented multi-env coordinate block at the top with prod defaults:The elision rule (env=prod → no suffix, env=non-prod →
<app>-<env>suffix) keeps the prod render character-for-character identical.chart/values-sandbox.yamlis added as the ready-to-use overlay for Phase D. NOT wired into any helm install or ArgoCD app today — the platform side isn't evolved yet. The file documents the convention so the Phase D commit can simplyhelm install -f values.yaml -f values-sandbox.yaml.Bonus fix
.gitea/workflows/vault.yamlhad a real CI bug: the vault_step JWT role wasgitea_cicd_webapp(copy-paste leftover from the template repo) instead ofgitea_cicd_erp. The erp repo's CI would have failed JWT auth against Vault. Bundled here because it touches the same file family and is a 1-line fix.Verification
Sandbox overlay smoke test:
What's NOT in this PR (Phases A, B, D, E)
arcodange-org/tools/hashicorp-vault/iac/modules/app_roles: add optionalenvparameter (default"prod") + computelocal.instance+ propagate to derived names. Additive change, backwards-compatible for every app that doesn't setenv.arcodange-org/factory: postgres/iac tfvars schema (set(string)→list(object({name, envs}))withenvsdefaulting to["prod"]), argocd templates render one Application per env, conventions.md updated.iac/main.tfswitches tofor_eachoverlocal.envs = toset(["prod", "sandbox"]), factory tfvars addsenvs = ["prod", "sandbox"]to erp.erp-sandbox.arcodange.labprovisioned.Test plan
helm template erp chart/ --namespace erpbyte-identical to origin/main (diffexit 0)helm template erp chart/ -f chart/values.yaml -f chart/values-sandbox.yaml --namespace erp-sandboxproduces erp-sandbox derived names everywhere.gitea/workflows/vault.yamlCI still triggers cleanly (the typo fix is the actual unblock)Phase C of the multi-env evolution discussed in the runbook design thread (see PR description). Pure refactor — the prod helm template render is verified byte-identical (10857 bytes both before and after, diff exit 0). What was hardcoded, now templated: - chart/templates/vaultauth.yaml role: erp → role: {{ .Values.vault.k8sRole }} - chart/templates/vaultdynamicsecret.yaml path: creds/erp → path: {{ .Values.vault.dynamicPath }} - chart/templates/vaultsecret.yaml path: erp/config → path: {{ .Values.vault.staticPath }} - chart/templates/config.yaml DOLI_DB_NAME: erp → DOLI_DB_NAME: {{ .Values.db.name }} DOLI_URL_ROOT: https://erp..lab → DOLI_URL_ROOT: 'https://{{ .Values.host }}' values.yaml gains a documented multi-env coordinate block with prod defaults (env, instance, host, db.name, vault.k8sRole, vault.dynamicPath, vault.staticPath). The elision rule (env=prod → no suffix, env=non-prod → "<app>-<env>" suffix) guarantees the prod render is unchanged. chart/values-sandbox.yaml is added as the ready-to-use overlay for Phase D. It is NOT wired into any helm install / ArgoCD app today — the platform side (factory/postgres/iac tfvars, tools/hashicorp-vault/iac module signature) is not yet evolved. The file documents the convention so the Phase D commit can just `helm install -f values.yaml -f values-sandbox.yaml`. Also fixes .gitea/workflows/vault.yaml CI typo: the vault_step JWT role was gitea_cicd_webapp (copy-paste from the template repo) instead of gitea_cicd_erp. Real bug — the erp CI would have failed JWT auth against Vault. Fix unrelated to multi-env but bundled here because it's small and touches the same file family. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>