Skip to content

Commit ad56f0e

Browse files
committed
docs: document chart vendoring and drift detection
Add a README section explaining the embed -> vendor -> render model: how init vendors charts/talm/, why a binary upgrade does not touch it, the `talm init --update --preset <preset>` re-sync workflow (the preset is required because an init'd Chart.yaml does not record it), and the content-based drift warning with its strictCharts / --strict-charts enforcement, including that strict mode also blocks read-only commands. Rework manual-test-plan B5 into a runnable drift-detection script: default warning is stderr-only with the exit code unchanged, the re-vendor step that clears it, strict mode short-circuiting before the command body, and the no-false-alarm cases (version-only difference, dev build, freshly synced project) that must stay silent. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Aleksei Sviridkin <f@lex.la>
1 parent 45cafe5 commit ad56f0e

2 files changed

Lines changed: 66 additions & 3 deletions

File tree

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,41 @@ talm template -f nodes/node1.yaml -I
226226
>
227227
> `talm template -f node.yaml` (with or without `-I`) does **not** apply the same overlay: its output is the rendered template plus the modeline and the auto-generated warning, byte-identical to what the template alone would produce. Routing it through the patcher would drop every YAML comment (including the modeline) and re-sort keys, breaking downstream commands that read the file back. Use `apply --dry-run` if you want to preview the exact bytes that will be sent to the node.
228228

229+
## Keeping charts in sync after a binary upgrade
230+
231+
`talm init` **vendors** its preset and library charts into the project directory — the preset templates plus a copy of the talm library chart under `charts/talm/`:
232+
233+
```text
234+
mycluster/
235+
├── Chart.yaml
236+
├── values.yaml
237+
├── templates/ # preset templates — you own and edit these
238+
└── charts/
239+
└── talm/ # talm library chart — vendored from the binary
240+
├── Chart.yaml
241+
└── templates/_helpers.tpl
242+
```
243+
244+
Render commands (`template`, `apply`, `upgrade`) read this **local** copy, never the binary's built-in charts. That makes a project self-contained and reproducible — but it also means upgrading the `talm` binary does not touch `charts/talm/`. The vendored library stays frozen at whatever version last ran `init`, so a binary upgrade can leave you rendering with stale chart logic.
245+
246+
Re-sync the vendored library with `talm init --update`:
247+
248+
```bash
249+
talm init --update --preset <your-preset>
250+
```
251+
252+
This refreshes `charts/talm/` (always) and offers to update the preset templates (interactively, since you may have edited them). Your `values.yaml`, secrets, and node files are left untouched.
253+
254+
To catch drift automatically, a release build compares the vendored `charts/talm/` against its own built-in copy on every config-loading command. The comparison is by **content**, not version number — re-vendoring after a binary bump that did not change the library is a no-op and raises no warning. When the content genuinely differs, talm prints a non-fatal warning to stderr (stdout and the exit code are unchanged):
255+
256+
```text
257+
WARN: project's vendored charts/talm/ library differs from the copy built into talm <version>; run `talm init --update --preset <preset>` to re-sync (or ignore if this is intentional)
258+
```
259+
260+
The remediation needs the preset name because `talm init --update` resolves the preset from `Chart.yaml`, which an init'd project does not record — pass `--preset <your-preset>` (the one you ran `talm init` with) explicitly.
261+
262+
Teams that want this enforced can turn the warning into a hard error (exit 1): set `strictCharts: true` in `Chart.yaml` so the whole team and CI inherit it, or pass `--strict-charts` for a single run. Strict mode applies to every config-loading command, including read-only ones such as `talm get` — run `talm init --update --preset <preset>`, or drop the flag / unset `strictCharts`, to unblock. The check stays silent for `dev`/source builds, whose embedded charts are a moving target the developer controls.
263+
229264
## Apply with side-patches
230265

231266
`talm apply -f` accepts a chain of files. The FIRST `-f` is the **anchor** — it must carry a `# talm: nodes=[…], templates=[…]` modeline and live under a `talm init`'d project (Chart.yaml + secrets.yaml). Any subsequent `-f` files are **side-patches**: they are merged in order on top of the anchor's rendered config, and a single `ApplyConfiguration` is issued per node carrying the composed result.

docs/manual-test-plan.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,39 @@ Expected: `Updated.` on stdout. The rendered body replaces the previous body of
222222

223223
Regression anchor: write `nodes/node0.yaml` as `# Operator note A\n# Operator note B\n# talm: ...\n<body>`. After `template -I -f nodes/node0.yaml`, the first two lines (`# Operator note A`, `# Operator note B`) MUST still be there, followed by the modeline, the talm-rendered warning header, then the body. Re-run idempotent: a second `template -I` keeps the same prefix structure — leading comments don't drift, multiply, or disappear.
224224

225-
### B5. Render with stale chart preset
225+
### B5. Render with stale chart preset (chart-drift detection)
226226

227-
When the local `charts/talm/` is older than the talm binary's embedded preset, `talm template` succeeds against the local preset — it does NOT auto-bump. The operator must run `init --update`. Confirm by inspecting `talm version` against `Chart.yaml`.
227+
`talm` vendors its library chart into `charts/talm/` at `init` time; render commands read that local copy, never the binary's embedded charts. Upgrading the binary therefore leaves `charts/talm/` frozen at the version that last ran `init`. A release build surfaces this drift by **content** — the `Chart.yaml` version stamp is normalized away, so a pure version bump is never flagged.
228228

229-
**Regression anchor**: `template -I` is rewrite, not merge — verify by adding a `# my comment` line above the modeline in `nodes/node0.yaml`, running B4, and confirming the comment is GONE in the new body. If the comment survives, a behaviour change shipped (could be either an intentional new `--preserve-comments` flag or an undocumented merge mode — neither should appear silently).
229+
Simulate drift by editing the vendored library, then render:
230+
231+
```bash
232+
printf '\n{{- /* stale edit */ -}}\n' >> charts/talm/templates/_helpers.tpl
233+
talm template -f nodes/node0.yaml --offline 2>&1 >/dev/null | grep '^WARN:'
234+
```
235+
236+
Expected (default): a single line on **stderr**`WARN: project's vendored charts/talm/ library differs from the copy built into talm <version>; run talm init --update --preset <preset> to re-sync ...` — while stdout (the rendered config) and the exit code are unchanged. Clear it and re-confirm silence:
237+
238+
```bash
239+
talm init --update --preset generic --force
240+
talm template -f nodes/node0.yaml --offline 2>&1 >/dev/null | grep '^WARN:' && echo "FAIL: drift not cleared" || echo "OK: drift cleared"
241+
```
242+
243+
The `--preset` is required: `talm init --update` alone resolves the preset from `Chart.yaml`, which an init'd project does not record, so it errors with "preset not found in Chart.yaml dependencies" (pinned by A8) and never re-vendors. Expected: `OK: drift cleared`.
244+
245+
Strict mode turns the same drift into a hard error (exit 1) raised before the command body runs. Opt in per project via `strictCharts: true` in `Chart.yaml`, or per invocation via `--strict-charts`:
246+
247+
```bash
248+
talm template -f nodes/node0.yaml --offline --strict-charts; echo "exit=$?"
249+
```
250+
251+
Expected: exit 1, the drift message plus a hint pointing at `talm init --update --preset <preset>`, and no rendered output — the command body never runs (no modeline/render errors follow the hint).
252+
253+
No-false-alarm checks — each MUST stay silent (no `WARN:` line):
254+
255+
- A project vendored by an older release, run under a newer binary whose `charts/talm/` is byte-identical: the version stamp differs but the content does not.
256+
- A `dev`/source build: its embedded charts are a moving target the developer controls, so the check is a no-op.
257+
- A freshly synced project (`talm init --update --preset <preset>`) under the matching binary.
230258

231259
### B6. Scope-filter symmetry across v1.11 and v1.12 renders
232260

0 commit comments

Comments
 (0)