Skip to content

Upgrade guide

Upgrade guide

This page is for users coming from v0.13.x or earlier who want to bring their templates_dir up to the current YAML-first artifact format. If you're already on a recent srekit and your templates dir is empty or fresh, you don't need this page — srekit templates init produces the new layout directly.

The artifact format moved from per-generator Go-template files (postmortem.md.tmpl + optional postmortem.sections.yaml sidecar) to a single YAML artifact per generator (postmortem.yaml). The migration ran incrementally across v0.14.0 → v0.20.0 (one or two generators per release); v0.20.0 is the cutover for the embedded set. Your templates_dir upgrades the same way each time you run srekit templates upgrade. Legacy files in your dir remain readable and are surfaced via a stderr WARN until you remove them.

For the per-release journal (what changed when, why), see Migration history.

Quick check: where am I?

ls your templates dir (the path in ~/.srekit.yaml templates_dir: / $SREKIT_TEMPLATES_DIR / $XDG_CONFIG_HOME/srekit/templates):

  • See *.yaml (postmortem.yaml, task.yaml, …) — you're on v1. Done.
  • See *.md.tmpl + maybe *.sections.yaml — you have legacy files. Run the upgrade recipe below.
  • Mixed (.yaml and .tmpl for the same generator) — you've started; finish by deleting the legacy .tmpl after verifying the new .yaml renders correctly.

Upgrade recipe (v0.13.x → current)

Each step is isolated; you can stop after any step and re-run.

Order matters: templates migrate runs first to convert your customized .tmpl files into .yaml. If you run templates upgrade first, it scaffolds the embedded .yaml artifacts and templates migrate then skips your customized .tmpl (target already exists) — your customizations end up ignored.

TPL=~/.srekit/templates   # or wherever your dir is

# 1. Convert your customized .tmpl files in the dir to .yaml. Defaults
#    to a dry-run that prints the converted YAML; --apply writes files.
#    The converter copies template expressions verbatim — see the
#    rewrite step below.
srekit templates migrate "$TPL"           # preview
srekit templates migrate "$TPL" --apply   # writes <name>.yaml next to each .tmpl

# 2. Rewrite data-shape references inside the generated YAML.
#    Most generators moved their template root from .X to .Meta.X.
#    Skip files that ALREADY use .Meta.X (postmortem was on .Meta.X
#    since v0.13.0 — its sidecar drove the typed access).
for f in "$TPL"/*.yaml; do
  grep -q '{{ \.Meta\.' "$f" && continue   # already on .Meta.X — leave alone
  sed -E -i '' 's/\{\{ \.([A-Z][a-zA-Z]*)/\{\{ .Meta.\1/g' "$f"
done
# rfc-specific: function-call form `{{ shortID .ID 8 }}` isn't covered
# by the main regex; rewrite it separately.
[ -f "$TPL"/rfc.yaml ] && sed -E -i '' 's/shortID \.ID/shortID .Meta.ID/g' "$TPL"/rfc.yaml

# (Linux/GNU sed: drop the empty `''` after `-i` — it's a BSD/macOS oddity.)

# 3. Bring in any v1 artifacts the binary ships that you don't have yet
#    (e.g. you skipped some generators in v0.13.x). Existing user files
#    are not touched (3-way merged on later runs once snapshots exist).
#    Orphaned snapshots for retired layouts get GC'd from .srekit-embedded/.
srekit templates upgrade "$TPL"

# 4. Verify the result.
srekit templates validate "$TPL"
# OK    postmortem.yaml
# OK    task.yaml
# ...

# 5. Once you trust the new YAML, render-test, then delete the legacy
#    files. They aren't auto-deleted — they're your customizations.
srekit --templates-dir "$TPL" postmortem --title smoke --severity SEV-2 --stdout > /dev/null
rm "$TPL"/*.md.tmpl "$TPL"/*.sections.yaml 2>/dev/null

Tips:

  • Section IDs are part of the structured --json contract; if the converter slugified a section title awkwardly (e.g. bilingual headings with abbreviations), open the YAML and rename the id: before relying on --json consumers.
  • Sections containing Go-template control flow ({{ if }} / {{ range }} / {{ with }}) are wrapped in git merge-style diff markers — the converter doesn't translate control flow into the typed-sections vocabulary. Resolve manually.
  • header_body: is the freeform-Markdown escape hatch — use it for blameless callouts, custom blockquotes, anything that doesn't fit the typed sections. (For postmortem-style .tmpl files that end with a {{ range .Sections }} loop, the migrator correctly omits header_body since v0.26.0.)
  • license_*.tmpl files are skipped; license bodies were inlined into the binary in v0.14.0.

JSON shape changes by version

srekit <generator> --json went through two breaking shape changes. Migrate jq consumers accordingly:

From → To Shape change jq migration
0.12.x → 0.13.0 flat {title, severity, …}{meta, sections} jq '.title'jq '.meta.title'
0.13.x → 0.20 bootstrap envelope (sections: [{id:"body", body:<markdown>}]) → structured per-artifact sections jq '.sections[0].body'jq '.sections[] | select(.id=="<id>").body'

Per-section IDs are in internal/tmpl/templates/<name>.yaml in the binary repo. The structured contract is stable as of v0.20.0.

--template FILE

The flag is now license-only. Other generators (postmortem, task, retro, slo, ebp, capacity, incident, rfc, runbook, oncall-report, changelog) reject it with Error: unknown flag: --template. This is the v0.22.0 cleanup of a flag that had become a silent no-op once each generator moved to the artifact path.

Per-artifact customization in the v1 model: drop a <name>.yaml into your templates_dir. See Custom templates workflow for the full loop.

Stability boundaries

Stable contracts (will not change without a major version bump):

  • The <name>.yaml schema fields: version, frontmatter, title, meta_bullets, header_body, sections. New fields may be added; existing ones won't be removed before 2.0.
  • The --json outer shape ({meta, sections}) and per-section shape ({id, title, type, required, body}).
  • The section type vocabulary (text / list / table).
  • Per-command meta field names (additions are minor; removals are breaking).
  • CLI flags shown in --help on each command.

Compatibility kept, removal candidates for v2.0:

  • The legacy .tmpl loader path (Loader.Parse) for user files in templates_dir. Still works with a stderr WARN.
  • The legacy .sections.yaml sidecar parser (sections.ParseManifest) — used by templates validate / templates migrate to read pre-v0.14 dirs.

Not stable yet (may change in 1.x or 2.0):

  • The frontmatter field is a free-form map. A typed JSON Schema may be introduced; that would be breaking only for authors who relied on free-form structure.
  • The exact stderr WARN wording for legacy .tmpl files.

Troubleshooting

WARN: <file> in <dir> is a legacy pre-v1.0 format and is being ignored. — A legacy .tmpl or .sections.yaml sits next to a v1 <name>.yaml in your dir. Migrate using the recipe above; the legacy files are not auto-deleted (they're your customizations). The WARN is suppressed by --quiet.

Error: load <name>.yaml: ... — The embedded artifact is missing or the user-dir version is malformed. Run templates validate to surface the parse error.

Error: parse <name>.yaml: unknown type "..." — Your user-dir artifact declares a section type: the binary doesn't recognize. Supported types: text, list, table. Fix the YAML.

Section heading shows raw template syntax ({{ .Meta.X }}) — pre-v0.20.0 srekit didn't template-evaluate section titles. Upgrade the binary to v0.20.0+ or use static titles.

See also