Release r1.0 plan
Plan: “Helm for Developers” tutorial (r1.0)
All of this comes from read-only investigation done on 2026-10-08. The coordinator’s book constraint (books are cited only for concepts Helm 4 left unchanged, and Helm-4-changed behavior is sourced from official Helm docs) is built into the Chapter outline, the Steps and the Acceptance criteria.
Environment facts (checked, not assumed)
Tools on PATH
- helm v3.18.3 at
~/.local/bin/helm. This is Helm 3. Latest stable upstream is v4.3.0 (2026-09-09, fromgh release list -R helm/helm). - minikube v1.38.1.
- kubectl v1.32.13, which has kustomize v5.5.0 built in. There is no standalone
kustomize. - podman 5.8.7.
- docker 29.8.2 (real Docker).
- node v22.22.2, with
pptxgenjs@4.0.1installed globally. - gh 2.102.0, authenticated as patterncatalyst. Git identity is
PatternCatalyst <rsedor@patterncatalyst.io>. - go 1.26.8, gpg 2.4.9, skopeo.
- soffice and pdftoppm. 24 Red Hat font files are installed.
- ruby 4.0.7, bundler 4.0.20.
- python3 3.14.7, with pyyaml.
Missing
- python3.15, uv, crc, oc, kubeconform, ct, cosign, helmfile, kind.
- Python packages
python-docxandcairosvg.cairosvgis needed by the deck PNG renderer, following the MEAbuild_diagrams.pypattern.
Host and cluster
- 62 GB RAM, 16 CPUs.
- One minikube profile exists:
datamesh(docker driver, containerd, k8s v1.35.1), currently Stopped. The docker driver is therefore the one already proven on this host.
Python 3.15
- 3.15.0 GA has slipped to 2026-10-09, tomorrow (rc3 came out 10-02).
- There is no UBI Python 3.15 image.
ubi9/python-314exists. Noubi10/python-*image exists. - Docker Hub has
python:3.15.0rc3-*and3.15-rctags.
Other repos and tools
~/Dev/helm-for-developersdoes not exist, and neither does the GitHub repopatterncatalyst/helm-for-developers.- Latest upstream versions: helm-unittest v1.2.1, chart-testing v3.15.0, kubeconform v0.8.0, helm-diff v3.15.15, cosign v3.1.3.
- The hub repo is clean on
main.
Approach
Build one fixed, feature-flagged Python 3.15 / FastAPI application, in final form, once:
- shipping-service: REST API, Postgres, Kafka producer.
- notification-service: Kafka consumer with a small HTTP surface.
Then build a validated golden chart set that represents the end state. Each chapter’s examples/NN-*/ directory is a self-contained snapshot of the charts at that step, stripped back from the golden set. The app image never changes between chapters; only the charts and values do. That keeps every chapter focused on Helm.
Platform pieces:
- Platform operators come from the lgtm-minikube-stack templates, scoped to CNPG, Strimzi and LGTM. Charts ship only the custom resources, never the operators.
- Helm 4.3.x is installed project-locally under
.tools/with isolatedHELM_*_HOMEdirectories, so the user’s global Helm 3.18 keeps working for the other projects. - Verification has two tiers. Offline checks are lint, template, unittest, kubeconform and ct lint. Live checks run on a dedicated minikube profile
helm4dev. - Content follows the lgtm-jekyll, lgtm-tutorial and lgtm-professional-voice conventions.
- Decks follow lgtm-presentation.
- Git follows lgtm-github on the branch
feature/r1-initial-build. - Any outward action (creating or pushing the GitHub repo, enabling Pages, a hub PR or push) is held for user confirmation.
Rejected alternatives
- A single evolving chart with a git tag per chapter. It breaks the “runnable example directory per chapter” rule.
- Reusing the datamesh
charts/capstoneumbrella as-is. It is a skeleton with hard-coded names, no helpers or labels conventions, and many dead toggles. It would teach anti-patterns, so only its patterns are reused. - Bitnami Postgres/Kafka subcharts. Bitnami moved its catalog to legacy/paid images in 2025, and the house stack is operator-based (CNPG and Strimzi).
- Replacing the global helm with Helm 4. Sibling projects (datamesh, MEA) depend on Helm 3.18.
- Flux as the primary GitOps tool. Argo CD matches the OpenShift GitOps Application pattern already used in the sibling repos’
openshift/gitops/application.yaml. - Istio, KEDA and Kiali. They cost a lot of resources and are not Helm-specific; the flags stay
false. docker.io/library/python:3.15-slimas the base image. It breaks the house UBI rule (lgtm-minikube-stackreferences/base-images.md).- Alembic for migrations. It adds a heavy dependency. Versioned SQL plus a roughly 40-line runner is enough and makes the hook Job easy to read.
Reuse map
| Source | What is reused | Lands at |
|---|---|---|
~/Dev/datamesh-reference-arch-python/examples/lgtm-datamesh/services/shipping-service/app/{config.py,db.py,main.py,models.py}, tests/test_health.py, Containerfile (identical copy exists in minikube-on-fedora/examples/17-capstone/...) |
pydantic-settings Settings with env-sourced PG_*; async SQLAlchemy/asyncpg engine; /health liveness vs /healthz readiness split; FastAPI lifespan (Managed Lifecycle); ASGITransport test; UBI multi-stage, USER 1001:0 |
services/shipping-service/app/, services/*/tests/, services/Containerfile |
~/Dev/modernizing-enterprise-applications/examples/06-shipping-service/src/main/java/dev/patterncatalyst/shipping/{Shipment,ShipmentDto,ShipmentDispatched,ShippingResource}.java and src/main/resources/db/migration/V1__create_shipments_table.sql, V3 (unique order_id), outbox SQL |
Domain model: Shipment(id BIGSERIAL, order_id BIGINT, address, status PENDING/DISPATCHED/CANCELLED, created_at); /api/shipments/{id}, /api/shipments?orderId=, 400 on missing orderId; ShipmentDispatched{orderId, shipmentId, address, status, occurredAt} wire contract; unique order_id idempotency |
services/shipping-service/app/{models.py,routes.py,events.py}, services/shipping-service/migrations/V1__shipments.sql, V2__unique_order_id.sql |
~/Dev/observability-python-otel-lgtm/services/common/obs/{otel.py,kafka.py,kafka_propagation.py,logging.py} and services/Containerfile (repo-root context, ARG SERVICE) |
OTel SDK bootstrap over OTLP/HTTP 4318, W3C propagation, FastAPI auto-instrumentation, OTEL_SDK_DISABLED switch; aiokafka producer/consumer with trace context in headers; JSON logging; one parameterized Containerfile |
services/common/pcobs/ (renamed package), services/Containerfile |
.../lgtm-datamesh/charts/capstone/charts/postgres/templates/cluster.yaml + values |
CNPG Cluster CR with inheritedMetadata sidecar opt-out, bootstrap.initdb database/owner, <cluster>-app Secret keys dbname/username/password, 2Gi memory limit lesson |
charts/shipping-postgres/templates/cluster.yaml |
.../lgtm-datamesh/charts/capstone/charts/kafka/templates/{kafka,nodepool,topic}.yaml |
Strimzi KRaft Kafka + KafkaNodePool (dual role, ephemeral) + KafkaTopic (API version must be re-verified for Strimzi 0.51; see Risks) |
charts/shipping-kafka/templates/ |
.../lgtm-datamesh/charts/capstone/charts/shipping-service/templates/deployment.yaml + values |
Probes block (startup 30×2s, liveness /health, readiness /healthz), secretKeyRef wiring to CNPG secret, pullPolicy: Always lesson for mutable tags |
charts/pc-lib/templates/_deployment.tpl (generalized) |
.../lgtm-datamesh/openshift/helm/datamesh/templates/{_helpers.tpl,route.yaml,serviceaccount-infra.yaml}, openshift/gitops/application.yaml, openshift/README.md; ~/Dev/modernizing-enterprise-applications/openshift/{README.md,helm/mea/}, _docs/33-appendix-openshift.md |
Route template (edge TLS, Redirect), “no runAsUser under restricted-v2” rule, internal registry push loop, CRC prerequisites prose (account, pull secret, crc setup/start), Argo CD Application with helm.releaseName |
charts/shipping-platform/templates/route.yaml (gated by Capabilities.APIVersions.Has "route.openshift.io/v1"), examples/27-openshift-crc/, examples/25-gitops-argocd/application-*.yaml, _docs/27-appendix-openshift-local.md |
.../lgtm-datamesh/scripts/tunnel-services.sh |
NodePort + SSH tunnel (no port-forward) | scripts/tunnel.sh |
~/.claude/skills/lgtm-minikube-stack/templates/{setup-profile.sh,bootstrap.sh,setup-postgres-operator.sh,setup-kafka-operator.sh,setup-lgtm.sh,teardown.sh,cluster-status.sh}.template, grafana-datasources.yaml, grafana-dashboards/, snippets/otel-collector-config.yaml |
Platform bring-up, tiers gated on health | scripts/platform/*.sh, platform/observability/ |
~/.claude/skills/lgtm-jekyll/assets/site-template/*, lgtm-tutorial/scripts/generate_diagram.py |
Site scaffold, layouts, CSS, diagram engine | repo root, scripts/generate_diagram.py |
~/Dev/modernizing-enterprise-applications/presentation/modernizing-101/ (layout, package.json, cairosvg build_diagrams.py variant) + lgtm-presentation/scripts/* |
Deck directory shape and PNG rendering without /mnt/skills |
presentation/helm-101/, presentation/helm-201/ |
~/Dev/modernizing-enterprise-applications/.gitignore |
ignore set (plus .tools/, dist/, .venv/, qa/) |
.gitignore |
Data-mesh concept (datamesh-reference-arch-python/_docs/01-concepts.md) |
Per-service schema ownership (shipping schema) and events as a published contract; the library chart emits patterncatalyst.io/domain, /owner, /data-product annotations |
charts/pc-lib/templates/_metadata.tpl, chapters 09, 16, 17 |
House decisions (record in CONTRIBUTING.md → “House style”; executors apply them verbatim)
Project and site
- Project dir:
~/Dev/helm-for-developers. - GitHub repo:
patterncatalyst/helm-for-developers, public. baseurl: "/helm-for-developers",github_username: "patterncatalyst",github_repo: "helm-for-developers".brand_emoji: "⎈"(falls back to “🧭” if the font lacks it).- Accent color: default amber
#e8870c. - License: Apache-2.0.
- Hero eyebrow: “Helm 4 · Python 3.15 · FastAPI · minikube · OpenShift”.
Versions (pinned and dated 2026-10-08; S0 re-verifies them)
- Helm 4.3.0
- helm-unittest 1.2.1
- helm-diff 3.15.15
- chart-testing 3.15.0
- kubeconform 0.8.0
- cosign 3.1.3
- helmfile: latest 1.x that supports Helm 4, optional
- Argo CD Helm chart: latest stable
- CNPG chart: the skill pins 0.23.0; re-verify
- Strimzi 0.51.0
- LGTM chart versions as in
setup-lgtm.sh - Python 3.15.0, FastAPI latest; Pydantic, uvicorn, asyncpg, aiokafka, OTel versions pinned in
pyproject.toml
Tool isolation. scripts/env.sh is sourced by every script. It exports:
PATH=$REPO/.tools/bin:$PATHHELM_CONFIG_HOME,HELM_CACHE_HOME,HELM_DATA_HOMEunder$REPO/.tools/helm/HELM_PLUGINS=$REPO/.tools/helm/pluginsGNUPGHOME=$REPO/.tools/gnupg, for throwaway signing keys onlyMINIKUBE_PROFILE=helm4dev
It also fails if helm version --short is not v4.*.
Cluster.
- Profile
helm4dev,MINIKUBE_DRIVER=dockerby default (the driver already proven on this host), containerd runtime, 12g RAM, 8 CPUs. - Flags:
ENABLE_ISTIO=false ENABLE_KEDA=false ENABLE_KIALI=false ENABLE_POSTGRES=true ENABLE_KAFKA=true ENABLE_LGTM=true. - The bootstrap installs operators only. The tiers that create the Postgres and Kafka cluster CRs are removed, because the charts own those CRs.
- Strimzi goes in namespace
strimziwithwatchAnyNamespace=true. CNPG goes incnpg-system. Observability goes inobservability. - The registry addon is enabled.
- Each example installs into its own namespace
hfd-NNwith release nameshipping(orplatformfor the umbrella), and./demo.sh cleanuninstalls it.
Host access. NodePort plus scripts/tunnel.sh; no kubectl port-forward.
- shipping: 30080 → localhost 8080
- notification: 30081 → localhost 8081
- grafana: 30300 → localhost 3000
- argocd: 30443 → localhost 8443
Images
scripts/build-images.shbuildsshipping-service:0.1.0andnotification-service:0.1.0straight into the profile (minikube -p helm4dev image buildorpodman build+minikube image load).pushmode also pushes them to the registry addon aslocalhost:5000/<name>:0.1.0.- Chart default:
image.repository: shipping-service, tag defaults to.Chart.AppVersion,pullPolicy: IfNotPresent.
Chart versions in snapshots. Version 0.<chapter>.0 per chapter snapshot until chapter 19, which releases 1.0.0. appVersion: "0.1.0" throughout.
Command prefixes. [host]$ for the host, [crc-host]$ for the CRC machine. Commands are single-line. Use 127.0.0.1 rather than localhost in prose for host URLs. Use fully qualified image refs.
Banned vocabulary. Per lgtm-tutorial and lgtm-professional-voice: honest/honestly, deceptive “lie” (person or process as subject), capstone, simply, seamless, leverage, load-bearing, delve. Also no Helm 2 terms in instructions: tiller, helm init, requirements.yaml, helm serve.
Citation line format. Must be one physical line, inside a ## Further reading section at the end of each chapter (before the verification footer):
- <Authors ≤60 chars, or "First Author et al.">, *<Title>* (<Publisher>, <Year>), ISBN <13-digit>. Used here for: <still-valid concepts>.
- Do not put an em dash right before the title. The gen-books
AUTHOR_DASH_REwould capture only the last author. - Known extractor limitation:
is_plausible_titlerejects parentheses, so the CKAD title must be written as*Certified Kubernetes Application Developer (CKAD) Study Guide*and its hub entry is hand-curated.
Helm-4-changed topics must cite official sources only, never books. Sources: helm.sh/docs (Helm 4 overview and “changes since Helm 3” page), the Helm 4 release blog and notes on helm.sh/blog and the GitHub v4.0.0–v4.3.0 releases, and the HIPs in github.com/helm/community/tree/main/hips. Executors must find the exact URLs and confirm they resolve. Topics:
--atomic→--rollback-on-failure--force→--force-replace- server-side apply as the default for new releases (
--server-side, field managers,--force-conflicts) --waitkstatus watcher semantics (--wait=watcher|hookOnly|legacy)- the plugin system (types
cli/v1,getter/v1,postrenderer/v1; subprocess and Wasm/extism runtimes; the plugin.yaml schema; plugin verification) - post-renderers being plugins only
- OCI behavior (install by digest,
helm registrychanges) - dry-run, lint and template flag changes
--take-ownership- slog-based logging and
--debug - removed or renamed flags
- chart API v3 status (still in progress; charts stay
apiVersion: v2)
Executors confirm each one against helm <cmd> --help from .tools/bin/helm before writing it.
Chapter outline
Every hands-on chapter gets examples/NN-slug/{README.md, demo.sh, chart(s)/values}. demo.sh supports these subcommands: (none) = full run, offline = lint/template/unittest/kubeconform only, clean.
Diagram files. Diagram specs live in scripts/diagrams/chNN.py and output to assets/diagrams/NN-*.{svg,excalidraw}.
Book abbreviations used in the table:
| Code | Book |
|---|---|
| LH | Learning Helm, Butcher, Farina, Dolitsky, O’Reilly 2021, 9781492083641 |
| MKR | Managing Kubernetes Resources Using Helm, 2nd ed., Block, Dewey, Packt 2022, 9781803242897 |
| KP | Kubernetes Patterns, 2nd ed., Ibryam, Huß, O’Reilly 2023, 9781098131678 |
| KUR | Kubernetes: Up and Running, 3rd ed., Burns et al., O’Reilly 2022, 9781098110192 |
| CKAD | CKAD Study Guide, 2nd ed., Muschko, O’Reilly 2024, 9781098152857 |
| PEK | Platform Engineering on Kubernetes, Salatino, Manning 2024, 9781617299322 |
| GOK | GitOps and Kubernetes, Yuen et al., Manning 2021, 9781617297274 |
| K4D | Kubernetes for Developers, Denniss, Manning 2024, 9781617297175 |
| EPE | Effective Platform Engineering, Chankramath, Cheneweth, Oliver, Alvarez (verify), Manning 2025, 9781633436497 |
| docs | Official Helm 4 sources only |
Part (part_name, order) |
# / file | Helm capabilities | Example dir | Citations | Diagrams |
|---|---|---|---|---|---|
| Getting started (0) | 00 00-outline.md |
Arc of the book, progressive build table | none | none | 00-build-up-arc |
01 01-prerequisites.md |
Project-local Helm 4 install, helm version, env isolation (HELM_*_HOME), minikube profile, operator-only bootstrap, image build |
01-lab-setup (preflight + scripts/platform/bootstrap.sh driver) |
docs | 01-lab-topology |
|
02 02-helm-4-tour.md |
What Helm is (client-only, releases, charts, repos), install a public OCI chart (oci://ghcr.io/stefanprodan/charts/podinfo), helm show/install/list/status/uninstall, Helm 3→4 changes table |
02-helm-tour |
docs; LH (package-manager concepts only) | 02-helm-architecture |
|
| From manifests to a chart (1) | 03 03-shipping-service-raw-manifests.md |
Why charts: raw Deployment/Service/ConfigMap for shipping-service (memory storage), image build, probes, resources, securityContext | 03-raw-manifests |
KUR (Deployments/Services/ConfigMaps), KP (Health Probe, Predictable Demands, Managed Lifecycle), K4D (containerizing, probes), CKAD (securityContext, probes) | 03-raw-manifest-sprawl |
04 04-first-chart.md |
helm create vs hand-built chart, anatomy, Chart.yaml apiVersion v2, version vs appVersion, type, .helmignore, install/upgrade/rollback/history/uninstall (--keep-history), release storage in Secrets (sh.helm.release.v1.*), HELM_DRIVER |
04-first-chart |
LH (anatomy); docs (lifecycle flags, storage) | 04-chart-anatomy, 04-release-revisions |
|
05 05-values-and-overrides.md |
values.yaml design, precedence (parent → -f order → --set* last), --set, --set-string, --set-file, --set-json, --set-literal, --reuse-values / --reset-values / --reset-then-reuse-values, values.schema.json (draft 2020-12 vs 7; verify Helm 4 support), helm show values |
05-values |
LH (values concept); docs (flags, schema) | 05-values-precedence |
|
06 06-templates.md |
Go templates and Sprig, built-ins (.Release, .Chart, .Capabilities, .Template, .Files), pipelines, quote/default/toYaml/nindent/trim, whitespace chomping, if/with/range, $ scope, variables, tpl, required, fail, lookup (empty under template/client dry-run) |
06-templates |
LH, MKR (templating) | 06-render-pipeline |
|
07 07-helpers-and-notes.md |
Named templates in _helpers.tpl, define/include/template, why include, recommended labels, fullname truncation, NOTES.txt, .Files.Get/Glob/AsConfig |
07-helpers-notes |
LH | 07-named-templates |
|
08 08-config-and-secrets.md |
ConfigMap/Secret from values, checksum/config rollout annotation, immutable ConfigMaps, existingSecret pattern, API_TOKEN Secret, comparison of secrets approaches (Sealed Secrets, External Secrets Operator, SOPS / helm-secrets; Helm 4 plugin compatibility verified or flagged), lookup to preserve generated secrets |
08-config-secrets |
KP (Configuration Resource, Immutable Configuration); docs | 08-secrets-options |
|
| Data and lifecycle (2) | 09 09-dependencies-postgres.md |
dependencies in Chart.yaml, helm dependency update/build/list, Chart.lock, file:// subchart shipping-postgres (CNPG Cluster), condition/tags, alias, import-values, global, wiring the CNPG <cluster>-app secret; SHIPPING_STORAGE=postgres |
09-postgres-subchart |
LH, MKR (dependencies); KP (Operator) | 09-subchart-tree |
10 10-crds-and-operators.md |
crds/ semantics (install only; no templating, upgrade or delete), why app charts ship CRs and not operators, .Capabilities.APIVersions.Has + fail guard for a missing operator, small ShippingRoute demo CRD in crds/ showing upgrade non-behavior, --skip-crds |
10-crds-operators |
KP (Operator, Controller); docs | 10-crd-ownership |
|
11 11-hooks-and-migrations.md |
Migration Job as pre-install,pre-upgrade hook (python -m app.migrate), helm.sh/hook-weight, hook-delete-policy (before-hook-creation,hook-succeeded), hook failure behavior, post-upgrade cache-warm example, hooks vs init containers, helm get hooks |
11-hooks-migrations |
LH (hooks); K4D (Jobs); KP (Init Container); docs (Helm 4 hook/wait behavior) | 11-hook-timeline |
|
12 12-release-lifecycle.md |
--wait (Helm 4 watcher), --timeout, --rollback-on-failure, --cleanup-on-fail, SSA default and field-manager conflicts, --force-replace, --take-ownership, --history-max, helm get all/values/manifest/notes/metadata, helm status, helm rollback, decoding a release Secret |
12-release-lifecycle |
docs only | 12-upgrade-failure-paths |
|
| Debugging and testing (3) | 13 13-debugging-charts.md |
helm lint --strict, helm template --debug --show-only, --dry-run=client vs --dry-run=server, helm get manifest, helm-diff plugin under Helm 4, kubeconform with CRD schemas (datree CRDs-catalog), common errors |
13-debugging |
docs | 13-debug-ladder |
14 14-chart-testing.md |
templates/tests/ + helm test, helm-unittest (suites, snapshot, failedTemplate), chart-testing ct lint / ct install against helm4dev, CI workflow .github/workflows/charts-ci.yml |
14-chart-testing |
MKR (chart testing concepts); docs | 14-test-pyramid |
|
| Multi-service applications (4) | 15 15-kafka-and-notification.md |
shipping-kafka subchart (Strimzi Kafka/KafkaNodePool/KafkaTopic), notification-service chart, KAFKA_ENABLED, event flow dispatch → shipment.dispatched → notification |
15-kafka-notification |
KP; docs | 15-event-flow |
16 16-umbrella-charts.md |
shipping-platform umbrella: deps with alias (shipping, notification, db, kafka), condition/tags (tags.messaging), global (env, OTLP endpoint, image registry), import-values (exports from db), ordering limits (hooks and readiness vs dependency order) |
16-umbrella |
LH, MKR | 16-umbrella-topology |
|
17 17-library-charts.md |
type: library chart pc-lib (deployment, service, labels, probes, securityContext, otelEnv, data-product metadata), consuming it, versioning a library |
17-library-chart |
LH (library charts); EPE (golden paths) | 17-library-reuse |
|
18 18-starters-golden-paths.md |
helm create --starter, starter pc-fastapi built on pc-lib, starter location in $HELM_DATA_HOME/starters, golden paths |
18-starters |
EPE, PEK | 18-starter-flow |
|
| Distribution and supply chain (5) | 19 19-packaging-and-repos.md |
helm package (--version, --app-version, --dependency-update), SemVer for charts, classic repo (helm repo index, served by python3 -m http.server), helm repo add/update/search |
19-packaging-repos |
LH (repositories concept); docs | 19-semver-chart-vs-app |
20 20-oci-registries.md |
helm push/pull/show oci://, helm registry login, local docker.io/library/registry:2 on 127.0.0.1:5001 plus the minikube registry addon, --plain-http, install by digest, OCI dependencies |
20-oci |
docs only | 20-oci-flow |
|
21 21-provenance-and-signing.md |
helm package --sign --key --keyring (throwaway key in project-local GNUPGHOME, legacy keyring export), .prov, helm verify, --verify on install/pull; cosign key-pair signing of the OCI chart artifact and cosign verify; keyless noted as not run here |
21-signing |
docs only (+ sigstore docs) | 21-trust-chain |
|
| Extending Helm (6) | 22 22-plugins.md |
Helm 4 plugin types and runtimes, helm plugin install/list/uninstall (verification flags), writing a subprocess cli/v1 plugin helm shipping-env, Wasm runtime: a minimal extism Go-PDK plugin built with Go GOOS=wasip1 (marked unverified if the build path fails) |
22-plugins |
docs only | 22-plugin-types |
23 23-post-renderers.md |
Post-renderer as a postrenderer/v1 plugin wrapping kubectl kustomize (adds labels plus a patch), --post-renderer <plugin-name> and args |
23-post-renderers |
docs only | 23-post-render-pipeline |
|
| Delivery and operations (7) | 24 24-environment-promotion.md |
values-dev/stage/prod.yaml layering, per-env namespaces, pinning chart version and image digest, promotion by version bump, optional Helmfile (helmfile.yaml, unverified if Helmfile lacks Helm 4 support) |
24-environments |
PEK, EPE | 24-promotion-flow |
25 25-gitops-argocd.md |
Argo CD installed via its Helm chart, Application from the OCI chart in the in-cluster registry (primary, verifiable here) and from Git (after push), helm.valueFiles, Argo renders with helm template (hooks mapped to sync hooks; lookup not available), sync waves vs hook weights |
25-gitops-argocd |
GOK (GitOps principles only), PEK, MKR (Argo CD concepts only); docs (Argo CD + Helm 4) | 25-gitops-loop |
|
26 26-observability-lgtm.md |
Library-driven OTel env (OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.observability.svc.cluster.local:4318, OTEL_SERVICE_NAME, resource attrs from .Release/.Chart), Grafana dashboard ConfigMap shipped by the chart (sidecar label), tracing across Kafka, Tempo/Loki/Mimir queries |
26-observability |
KP (Sidecar / observability context) | 26-telemetry-path |
|
| Appendices (8) | 27 27-appendix-openshift-local.md |
Same umbrella on OCP via CRC: restricted-v2 SCC, arbitrary UID / GID 0, no runAsUser, Route vs Ingress (Capabilities-gated template), oc new-project, internal registry push, HelmChartRepository/ProjectHelmChartRepository CR + Developer console Helm UI, optional ImageStream. Marked untested here, with checklist plus verify-crc.sh |
27-openshift-crc |
docs (OpenShift docs) | 27-openshift-differences |
28 28-appendix-helm3-to-helm4.md |
Migration reference: renamed/removed flags, SSA, plugins, post-renderers, helm-mapkubeapis-style notes, coexistence |
none (reference) | docs only | none | |
29 29-appendix-cheat-sheet.md |
Command and template-function cheat sheet | none | docs | none | |
30 30-appendix-further-reading.md |
Bibliography with all cited books, one line each (citation format), plus the official sources list | none | all kept books | none |
Book decisions under the user constraint. All 9 books are kept, each limited to still-valid scope. No Helm 2 or Tiller-era book is cited.
| Book | Decision | Cite for | Never cite for |
|---|---|---|---|
| LH (2021, Helm 3) | Keep | Chart anatomy, values concept, templating, helpers, dependencies, library charts, hooks, repositories concept | Any flag or command, plugins, post-renderers, OCI, SSA, wait, atomic |
| MKR (2022, Helm 3) | Keep | Templating, dependencies, chart-testing concepts, Argo CD concepts | Same as LH |
| KP | Keep | K8s patterns in 03, 08, 09, 10, 11, 15, 26 | Helm behavior |
| KUR | Keep | Ch 03 K8s objects only | Its Helm section |
| CKAD | Keep | Ch 03 securityContext and probes only | Its Helm-3 exam commands |
| K4D | Keep | Ch 03 and 11 (containerizing, Jobs) | Helm behavior |
| GOK | Keep | Ch 25 GitOps principles only (declarative, reconcile, drift) | Argo CD CLI or version specifics |
| PEK | Keep | Ch 18, 24, 25 | Helm behavior |
| EPE | Keep | Ch 17, 18, 24 | Helm behavior |
Deck outlines
The decks live in presentation/helm-101/ and presentation/helm-201/. Each copies deck-helpers.js, dgen.py, assets/, a build_diagrams.py using cairosvg (MEA variant), and package.json.
- Output:
Helm-101-r1.0.pptxandHelm-201-r1.0.pptx, committed next todeck.js. OUTis a relative filename, not/mnt/....- Every slide gets thick speaker notes (“What it shows / What to show:
examples/NNcommand / Fallback”). - Slide titles are 2–5 word concept noun phrases.
- No slide numbers are referenced.
- Helm 4 syntax only.
Helm 101 (≈36 slides; chapters 02–12):
- Cover: “Helm for Developers 101”, subtitle “Charts, values, templates, releases with Helm 4”
- Agenda
- Divider: Why Helm
- YAML sprawl across environments (diagram)
- Helm as package and release manager
- Helm 4 at a glance (table: SSA default, rollback-on-failure, plugins/Wasm, post-renderer plugins, kstatus wait)
- Divider: Core concepts
- Chart, release, repository, values
- Client-only architecture and release Secrets (diagram)
- Divider: First chart
- Chart anatomy (tree, code)
Chart.yamlv2 (code)- Install, upgrade, rollback (diagram of revisions)
- Release history and storage
- Divider: Values
- Values precedence (diagram)
- Override flags (code:
-f,--set,--set-json,--set-file) values.schema.json(code)- Divider: Templates
- Go templates and Sprig (code)
- Flow control and scope (code: if/with/range/$)
- Named templates (code
_helpers.tpl, include vs template) tpl,required,fail,lookup(table)NOTES.txt- Divider: Config, data, hooks
- Config rollouts with checksums
- Secrets options (table)
- Subcharts and the Postgres operator (diagram)
- Migration hooks (timeline diagram)
- Hook weights and delete policies (table)
- Divider: Safe releases
- Wait and rollback-on-failure
- Server-side apply in Helm 4
- Lint, template, dry-run
- Next: Helm 201
- Appendix: Helm 3 → 4 flag map
Helm 201 (≈42 slides; chapters 13–27):
- Cover
- Agenda
- Recap: Helm 101 in one slide
- Divider: Testing and debugging
- Debug ladder (diagram)
- Diff plugin and server dry-run
- Chart test pyramid (diagram)
- helm-unittest (code)
- chart-testing and kubeconform
- Chart CI pipeline
- Divider: Multi-service applications
- Kafka via Strimzi
- Umbrella topology (diagram)
- Conditions, tags, alias (code)
- Globals and import-values
- CRDs and operators (table)
- Capabilities guards (code)
- Library charts (diagram)
- Starters and golden paths
- Divider: Distribution
- Chart SemVer vs appVersion
- Classic repos vs OCI
- Push and pull with OCI (diagram)
- Provenance files
- Cosign for OCI charts
- Divider: Extending Helm
- Helm 4 plugin types (table)
- Wasm plugins
- Post-renderer plugins (diagram)
- Divider: Delivery
- Environment promotion (diagram)
- Helmfile, optional
- GitOps with Argo CD (diagram)
- Hooks vs sync waves
- Observability via the library chart
- Telemetry path to LGTM (diagram)
- Divider: OpenShift
- SCCs and arbitrary UIDs
- Routes and the Helm console
- Takeaways
- Appendix: cheat sheet
- Appendix: reading list (only kept books + official docs)
Golden app and chart contract (S3 and S4 both code against this; neither may deviate)
shipping-service (services/shipping-service, port 8080)
Endpoints:
GET /healthGET /healthz: checks the DB only whenSHIPPING_STORAGE=postgresGET /api/info: returns{service, version, environment, defaultCarrier, storage, kafkaEnabled}POST /api/shipments {orderId, address}: returns 201 with status PENDING. IfAPI_TOKENis set, it requiresAuthorization: Bearer <token>and returns 401 otherwise.GET /api/shipments/{id}: 404 if absentGET /api/shipments?orderId=: 400 if missingPOST /api/shipments/{id}/dispatch: returns DISPATCHED and publishes theShipmentDispatchedJSON toKAFKA_TOPIC_DISPATCHEDwhenKAFKA_ENABLED=true
Environment variables:
SERVICE_NAME,SERVICE_VERSION,DEPLOY_ENV,LOG_LEVELSHIPPING_DEFAULT_CARRIERSHIPPING_STORAGE=memory|postgres(defaultmemory)PG_HOST,PG_PORT,PG_DATABASE,PG_USER,PG_PASSWORD,PG_SCHEMA=shippingKAFKA_ENABLED=false,KAFKA_BOOTSTRAP,KAFKA_TOPIC_DISPATCHED=shipment.dispatchedAPI_TOKENOTEL_SDK_DISABLED=true(default),OTEL_EXPORTER_OTLP_ENDPOINT,OTEL_SERVICE_NAME,OTEL_RESOURCE_ATTRIBUTES
python -m app.migrate applies migrations/V*.sql in order into schema PG_SCHEMA, records them in <schema>.schema_migrations, is idempotent, and exits 0. The app also tolerates the DB until it is migrated: readiness fails with 503 until the tables exist.
notification-service (port 8080)
- Endpoints:
/health,/healthz(consumer started),GET /api/notifications(last 50 received) - Background aiokafka consumer (group
notification-service) runs in the lifespan and continues the trace context. - Environment:
KAFKA_BOOTSTRAP,KAFKA_TOPIC_DISPATCHED,KAFKA_GROUP_ID, plus the OTel variables.
Image
- One
services/Containerfile, built fromservices/as the build context, withARG SERVICE,ARG PYTHON_VERSION=3.15.0, andARG UV_IMAGE=ghcr.io/astral-sh/uv:<pinned>. - Builder:
registry.access.redhat.com/ubi10/ubi-minimal. It copies/uv, runsuv python install ${PYTHON_VERSION}into/opt/python, creates a venv at/opt/venv, and installscommon/plus the service. Atesttarget runs pytest. - Runtime:
ubi10/ubi-minimal. It copies/opt/pythonand/opt/venv, runs asUSER 1001:0, needs no writable root filesystem (an/tmpemptyDir is enough), and its CMD runs uvicorn on port 8080. - Fallback F1:
PYTHON_VERSION=3.14(same build). Fallback F2:PYTHON_BASE=registry.access.redhat.com/ubi9/python-314. Whichever is used gets recorded inCONTRIBUTING.mdand the reconciliation plan.
Golden charts (charts/ at the repo root)
pc-lib(library)shipping-serviceandnotification-service(applications, depending on pc-lib viafile://../pc-lib)shipping-postgres(CNPGCluster)shipping-kafka(Strimzi)shipping-platform(umbrella), withvalues-{dev,stage,prod,openshift}.yamlstarters/pc-fastapi
Plugins (plugins/):
helm-shipping-env(cli/v1, subprocess)kustomize-postrender(postrenderer/v1)wasm-hello(cli/v1, Wasm, Go extism PDK)
Requirements across the charts:
- Every app chart has
values.schema.json,NOTES.txt,templates/tests/test-connection.yaml, atests/helm-unittest suite, andci/ci-values.yamlfor ct. securityContext:runAsNonRoot: true, norunAsUser(OpenShift-safe),allowPrivilegeEscalation: false, capabilities drop ALL,seccompProfile: RuntimeDefault.
Steps
The orchestrator does all git commits. Parallel executors never run git commit, which avoids index-lock races. After each step or parallel group lands, the orchestrator runs git add <owned paths> && git commit -m "<type>(<scope>): ..." on feature/r1-initial-build, then updates the step-status table in _plans/r1-plan.md.
Commits follow ~/.claude/skills/lgtm-github/references/commit-conventions.md:
- Types: docs, site, demo, ci, chore, fix, feat.
- Scopes:
§NN,demo-NN,r1.0. - No AI attribution trailers.
- WIP checkpoints are allowed.
S1: Scaffold the repo (serial, first)
- Owns:
~/Dev/helm-for-developers/root files:_config.yml,Gemfile,index.html,_layouts/,_includes/(header nav: Tutorial →/docs/00-outline/, Prerequisites →/docs/01-prerequisites/, Decks, GitHub),assets/css/site.css,assets/diagrams/README.md.github/workflows/pages.yml,.gitignore(MEA set plus.tools/ dist/ .venv/ qa/ presentation/*/node_modules),LICENSE,README.md,CLAUDE.md,CONTRIBUTING.md(house style from above)_parts/00..08-*.md, all nine parts, withpart_nameexactly as in the outline table_docs/00-outline.md_plans/r1-plan.md(this plan verbatim;render_with_liquid: false),_plans/iteration-plan.md,_plans/reconciliation-plan.md(skeleton),_plans/claims/.gitkeepscripts/generate_diagram.py(copied from~/.claude/skills/lgtm-tutorial/scripts/),scripts/diagrams/.gitkeep
- Process:
git init -b main, initial commitchore: scaffold Jekyll site from lgtm-jekyll template, thengit checkout -b feature/r1-initial-build. - Deps: none.
- Group: 0.
- Skills to read:
~/.claude/skills/lgtm-jekyll/SKILL.md~/.claude/skills/lgtm-jekyll/references/{authoring-conventions,theming}.md~/.claude/skills/lgtm-tutorial/references/conventions.md~/.claude/skills/lgtm-github/SKILL.md§1, §5
- Acceptance:
- Every
_partsfile parses and haspart_nameandorder0–8. 00-outline.mdlists all 31 chapters by title._config.ymlhas the values above.git branch --show-current=feature/r1-initial-build.mainhas exactly one commit.
- Every
S2: Tools and platform scripts (group A)
- Owns:
scripts/env.sh,scripts/install-tools.sh,scripts/platform/{setup-profile,bootstrap,setup-postgres-operator,setup-kafka-operator,setup-lgtm,teardown,cluster-status}.sh,platform/observability/{otel-collector-config.yaml,grafana-datasources.yaml,dashboards/},scripts/build-images.sh,scripts/tunnel.sh,scripts/check-helm-commands.sh,scripts/validate-site.sh(the 5 lgtm-tutorial static checks plus alt-text check plus part match),scripts/forbidden-syntax.sh. - Deps: S1.
- Group: A.
install-tools.sh: downloads into.tools/binonly. It covers Helm 4.3.x (checksum verified), kubeconform, ct (plus yamllint/yamale in.tools/venvif ct needs them), cosign, optional helmfile, and the helm-unittest and helm-diff plugins viahelm plugin installusingHELM_PLUGINS. Executors must check the Helm 4 plugin-verification flag inhelm plugin install --help.- Platform scripts: substitute
{{PROFILE_NAME}}=helm4dev,{{NAMESPACE}}/{{PROJECT_NAME}}as appropriate, and remove the CR tiers. Re-verify the CNPG, Strimzi and LGTM chart versions against current releases, and confirm they install under Helm 4 with SSA. check-helm-commands.sh: extracts every line startinghelm(and[host]$ helm) from_docs/*.md,examples/**/{demo.sh,README.md}andpresentation/*/deck.js. For each, it checks that the subcommand exists and that every--flagappears in.tools/bin/helm <sub> --help. Non-zero exit on any miss.forbidden-syntax.sh: greps_docs/ examples/ charts/ presentation/*/deck.jsfor--atomic,helm upgrade .*--force( |$),--post-renderer [./~],tiller,helm init,requirements.yaml,helm serve,apiVersion: v1in anyChart.yaml. Hits allowed only in28-appendix-helm3-to-helm4.mdand in lines marked<!-- helm3-reference -->.- Skills to read:
~/.claude/skills/lgtm-minikube-stack/SKILL.mdreferences/{preflight-and-prerequisites,known-issues,ports-and-endpoints,lgtm-on-minikube-sizing,opt-in-flags}.mdsnippets/{helm-repo-patterns,readiness-wait-patterns}.md
- Acceptance:
bash -npasses on all scripts.source scripts/env.sh && helm version --shortprintsv4.3.*(or newer 4.x).~/.local/bin/helm version --shortis stillv3.18.3.helm plugin listshows unittest and diff.kubeconform -v,ct versionandcosign versionsucceed.scripts/platform/bootstrap.shcontains nokind: Cluster/kind: Kafkacreation.- Downloading the tools needs network but does not touch system paths.
S3: Services (group A)
- Owns:
services/(common/pcobs,shipping-service,notification-service,Containerfile, migrations, tests). - Deps: S1.
- Group: A.
- Skills to read:
~/.claude/skills/lgtm-minikube-stack/references/base-images.mdand the Reuse map rows above. Read the source files listed there. - Gate first: confirm the Python 3.15.0 GA tag exists (
python.org/uv python list --all-versionsinside the uv image) and confirm cp315 wheels for pydantic-core, asyncpg and aiokafka (pip download --only-binary=:all: --python-version 3.15 ...in the builder). Apply fallbacks F1/F2 if not, and record the decision. - Acceptance:
podman build -f services/Containerfile --build-arg SERVICE=shipping-service --target test services/passes the tests, which cover:/health,/api/infoenv reflection, create/get/list/400/404 in memory mode, the 401 token path, the migration runner being idempotent (unit-tested against a fake connection or skipped with a reason), and a dispatch event payload matching theShipmentDispatchedfield names.- The same passes for notification-service.
podman run --rm <img> python -c 'import sys;print(sys.version)'prints 3.15.x (or the recorded fallback).- The runtime image runs as uid 1001 and also starts with an arbitrary uid:
podman run --user 123456:0.
S4: Golden charts and plugins (group A)
- Owns:
charts/,plugins/. - Deps: S1. Codes to the contract above.
- Group: A.
- Skills to read: Reuse map rows for charts and OpenShift. Helm 4 docs for any changed behavior.
- Acceptance:
- With
scripts/env.shsourced,helm lint --strictpasses for every chart, withhelm dependency buildrun first where needed. helm unittest charts/{shipping-service,notification-service,shipping-platform}passes, with at least 20 tests in total including schema-failure (failedTemplate) cases.helm template platform charts/shipping-platform -f charts/shipping-platform/values-dev.yaml | kubeconform -strict -summary -schema-location default -schema-location '<datree CRDs-catalog URL template>'shows 0 invalid.- The same template with
--api-versions route.openshift.io/v1 -f values-openshift.yamlrenders Routes, and without that flag renders none. - No rendered Deployment sets
runAsUser. kubectl kustomizepost-renderer plugin:helm template ... --post-renderer kustomize-postrenderadds the label.helm shipping-envruns.- The Wasm plugin either builds and runs, or is documented as unverified with the exact error.
- With
S5: Golden integration run on minikube (serial)
- Owns:
_plans/evidence/golden-*.txt. - Deps: S2, S3, S4.
- Group: serial.
- Process: start profile
helm4dev(do not touch thedatameshprofile), runbootstrap.sh,build-images.sh, then installshipping-platformwithvalues-dev.yaml --wait --rollback-on-failure. - Acceptance, with evidence captured:
- The migration hook Job completes.
curl -s 127.0.0.1:8080/api/infothrough the tunnel reflects dev values.- POST then dispatch, then
GET 127.0.0.1:8081/api/notificationscontains thatshipmentId. That is the observable cross-service effect. helm test platformpasses.- Negative control: upgrade with
--set shipping.image.tag=doesnotexist --wait --timeout 90s --rollback-on-failurefails andhelm historyshows the rollback to the previous revision. - A Tempo trace contains spans from both services. Query and result are recorded.
- Any criterion not met is recorded as not met.
S6.0 – S6.8: Chapter plus example authoring by Part (group B, parallel)
- Deps: S5.
- Group: B.
- Each executor owns:
- its
_docs/NN-*.md examples/NN-*/scripts/diagrams/chNN.pyandassets/diagrams/NN-*.{svg,excalidraw}_plans/claims/partN.md(new claims, allunverified)
- its
- Assignments:
- S6.0: ch01–02
- S6.1: ch03–08
- S6.2: ch09–12
- S6.3: ch13–14 plus
.github/workflows/charts-ci.yml - S6.4: ch15–18
- S6.5: ch19–21
- S6.6: ch22–23
- S6.7: ch24–26
- S6.8: ch27–30, including
examples/27-openshift-crc/{verify-crc.sh,CHECKLIST.md,values-openshift.yaml,build-and-push.sh}. Banner: “UNTESTED on the authoring machine; run on the CRC host”.
- Rules:
- Snapshots are derived from
charts/and stripped back to the chapter’s state. An example never references../../charts, so it stays self-contained. - Each chapter: front matter (
title,order,partexact, quoteddescription,duration), hook paragraph, the run-hint line, at least one diagram with alt text and a “Figure NN.x —” caption, concept sections, a full How the code works walk of the real template/values/plugin code (depth standard), Build, run, observe, a Cross-check (e.g.,kubectl getvshelm get manifest, kubeconform,helm diff), What you learned, Further reading (citation format; allowed scope only), and the verification footerunverified. - 1,400–1,900 words for hands-on chapters.
- Literal
{{ }}wrapped in{% raw %}…{% endraw %}. - Every Helm command checked against
helm <cmd> --help(Helm 4). - Each executor runs
examples/NN/demo.sh offlinefor its chapters and may not run live cluster demos; that is S7.
- Snapshots are derived from
- Skills to read:
~/.claude/skills/lgtm-tutorial/SKILL.mdreferences/{chapter-template,example-template,conventions,diagram-engine}.md~/.claude/skills/lgtm-jekyll/references/authoring-conventions.md~/.claude/skills/lgtm-professional-voice/SKILL.md+references/phrase-list.md(draft in-voice)~/.claude/skills/lgtm-diagram-generator/SKILL.md
- Acceptance (per executor):
scripts/validate-site.shpasses for its files.scripts/check-helm-commands.shpasses andscripts/forbidden-syntax.shis clean for its files.demo.sh offlineexits 0 for each example.bash -npasses on demo.sh.- The diagram pair parses.
- Word count in range.
- No book is cited for a docs-only topic: the docs-only chapters 12, 13, 20, 21, 22, 23, 28 contain zero ISBN lines, and other chapters cite only the scopes in the book decision table.
~/.claude/skills/lgtm-professional-voice/scripts/scan.sh --tier ban <files>shows 0 hits, or each survivor has a reason in the claims file.
S7: Live verification sweep (serial)
- Owns:
_plans/reconciliation-plan.md(merging_plans/claims/*),_plans/evidence/NN-*.txt, and the verification-footer paragraph only in_docs/*.mdand example README “Verification status” sections. - Deps: all of S6.
- Process: run
examples/NN/demo.shfor 01–26 in order onhelm4dev, with clean between. Promote a footer toverifiedonly with a behavioral observation (what changed and what was seen, with a negative control where cheap, e.g., the hook Job ran before the new pods, the rollback restored revision N, an unsigned chart was rejected by--verify, the cosign verify failure on a tampered tag, Argo CD reached Synced/Healthy and drift was reverted). - Stays unverified: ch27, plus Git-sourced Argo CD until the push happens. Also anything that failed, with the failure text.
- Acceptance: the reconciliation plan has one row per claim with status and evidence path, and no footer says verified without an evidence file.
S8a / S8b: Decks 101 / 201 (group C, parallel)
- Owns:
presentation/helm-101/orpresentation/helm-201/respectively, pluspresentation/README.md(S8a only). - Deps: S6 (and S7 preferred, for consistency).
- Setup: python venv
presentation/.venvwithcairosvg, which is gitignored. - Skills to read:
~/.claude/skills/lgtm-presentation/SKILL.md,references/{deck-builder,theme,diagram-engine}.md,~/.claude/skills/lgtm-professional-voice/references/surfaces.md. - Acceptance:
NODE_PATH=$(npm root -g) node deck.jswrites the pptx.- Slide count within ±4 of the outline.
- A python-pptx (or unzip/XML) check shows notes on every slide, so notes count = slide count.
soffice --headless --convert-to pdfsucceeds.- Cover, one code slide, one diagram slide and one table slide rendered with
pdftoppmand eyeballed: logo bottom-right, captions single-line. check-helm-commands.shcoversdeck.js.
S9: Hub integration (group C; separate repo ~/Dev/patterncatalyst-workshops-tutorials-list)
- Owns (in the hub repo, on branch
feature/add-helm-for-developers):_data/sites.yml,_data/books.yml,_data/book_categories.yml,scripts/gen-books.py(allowlist only). - Deps: S6.8 (final citations).
- Changes:
- Append
"helm-for-developers"toALLOWED_REPOS. Commitchore(scripts): allowlist helm-for-developers for book scan. - Dry-run only:
python3 -I scripts/gen-books.py --repos-root ~/Dev --out <session scratchpad>/books.gen.yml. Never with--out _data/books.yml. Both modes rewrite the file from the scan and would drop curated entries, e.g.otel-observability-tutorialreferences that are not in the allowlist. Confirm the generated output contains all 9 ISBNs withreferenced_byincludinghelm-for-developers. - Hand-add the 9 entries to
_data/books.ymlin alphabetical title position, matching the existing schema (title,authors,publisher,year,isbn,url= publisher product page (oreilly.com / manning.com / packtpub.com), optionalreview_notefor print/ebook ISBN differences,referenced_by: ["helm-for-developers"]). Verify ISBNs and titles against the O’Reilly platform or publisher pages, especially the EPE author list and print vs ebook ISBNs. - Add a category
"Kubernetes, Helm & Platform Engineering"tobook_categories.yml, listing the 9 exact titles (Helm books first). - Add a
sites.ymlentry under"Cloud-Native & Kubernetes": slughelm-for-developers, quoted title “Helm for Developers”, synopsis (no em dashes, voice-scanned),repo_url, andsite_url: nullwithnote: "site publishing pending"until Pages is live (S12 flips it).
- Append
- Commit message style: follow the hub history, e.g.
content(books): .../content(sites): .... - Acceptance:
python3 -c "import yaml;[yaml.safe_load(open(f)) for f in ['_data/sites.yml','_data/books.yml','_data/book_categories.yml']]"succeeds.- Every title in the new category exists in books.yml.
bundle exec jekyll buildexits 0 (or a Ruby 3.3 container build if Ruby 4 breaks Jekyll).git diff main -- _data/books.ymlshows only additions.- No push.
S10: Professional-voice pass (group D, parallel partitions)
- Partitions: ch00–10; ch11–20; ch21–30 + all READMEs +
examples/*/README.md; deck 101deck.js; deck 201deck.js; hub copy (synopsis). - Deps: S7, S8, S9.
- Process: each partition edits only its files. One final executor rebuilds both decks and regenerates any diagram whose spec changed.
- Skills to read:
~/.claude/skills/lgtm-professional-voice/SKILL.mdand all its references. Usescan.sh --filesto balance the partitions. - Acceptance:
scan.sh --tier ban --fail ~/Dev/helm-for-developersexits 0, or each survivor is listed with a reason in_plans/voice-pass.md.git diffshows no changes inside fenced code blocks, commands, identifiers or evidence.- Decks rebuilt.
S11: Package iteration (serial)
- Owns:
dist/helm-for-developers_r1.0.tar.gz(gitignored) and_plans/iteration-plan.md. - Deps: S10.
- Process: clean
__pycache__,.tools,node_modules,.venv,qafrom the tarball. Run all global checks. Tagr1.0only after Phase 3 validation passes. - Acceptance: the tarball exists and
ls -d examples/*/ | wc -l= 26 (examples 01–27 minus the absent 02? No: 01–27 hands-on = 27 dirs; see global criteria).
S12: Outward-facing actions (REQUIRES USER CONFIRMATION, after Phase 3)
gh repo create patterncatalyst/helm-for-developers --public --source=. --remote=origin --description "Helm 4 for developers: a chaptered tutorial with a Python 3.15 FastAPI shipping app, progressive chart examples, and Helm 101/201 decks" --push(pushesmain), thengit push -u origin feature/r1-initial-build,gh pr create, CI green,gh pr merge --squash --delete-branch.- Set Settings → Pages → Source: GitHub Actions (
gh api -X POST repos/patterncatalyst/helm-for-developers/pages -f build_type=workflow), thengh run watch. - Re-run ch25’s Git-sourced Argo CD path and update its footer.
- Hub: set
site_urltohttps://patterncatalyst.github.io/helm-for-developers/, push the branch, open a PR (hub CLAUDE.md implies main-push deploys; follow lgtm-github PR flow). - Tag and release
r1.0with the tarball andsha256sums.
Parallelism summary:
- 0: S1
- A: S2 ∥ S3 ∥ S4
- Serial: S5
- B: S6.0–S6.8 (9 executors, disjoint files)
- Serial: S7
- C: S8a ∥ S8b ∥ S9
- D: S10 partitions
- Serial: S11
- Gated: S12
Acceptance criteria (global)
Run these from ~/Dev/helm-for-developers after source scripts/env.sh unless noted.
helm version --shortmatches^v4\.and~/.local/bin/helm version --shortstill printsv3.18.3.ls _docs/*.md | wc -l= 31 (00–30).ls -d examples/*/ | wc -l= 27 (examples 01–27; 00 and 28–30 have none).scripts/validate-site.shexits 0. It covers: front matter parses; eachpart∈part_names; no stray{{outside raw/includes; SVG and Excalidraw parse; every include has non-empty alt and a “Figure” caption;bash -non allexamples/*/demo.sh.bundle exec jekyll buildexits 0. If Ruby 4.0 breaks Jekyll 4.3, thenpodman run --rm -v $PWD:/srv:Z -w /srv docker.io/library/ruby:3.3 sh -c 'bundle install && bundle exec jekyll build'exits 0.scripts/check-helm-commands.shexits 0, so everyhelmcommand in chapters, examples and decks uses subcommands and flags present in Helm 4--help.scripts/forbidden-syntax.shexits 0.- Book-citation rule:
grep -l ISBN _docs/{12,13,20,21,22,23,28}-*.mdreturns nothing.- Every ISBN line in
_docsbelongs to one of the 9 kept books. - Each kept book appears in ≥1 chapter plus ch30.
- A validator spot-check of every LH/MKR citation confirms its “Used here for” scope is in the allowed list.
- Every Helm-4-changed topic paragraph links a helm.sh/docs, blog or HIP URL.
for d in examples/*/; do [ -x $d/demo.sh ] && (cd $d && ./demo.sh offline) || exit 1; doneexits 0 (ch27 offline = template with--api-versions route.openshift.io/v1+ kubeconform).helm unittestacrosscharts/*(non-library) passes, with ≥20 tests._plans/evidence/golden-*.txtshows a dispatchedshipmentIdpresent in notification-service’s/api/notifications, a passinghelm test, and the rollback negative control.- Every
_docsfooter readingverifiedhas a matching_plans/evidence/NN-*.txt. Ch27 footer isunverifiedand states “untested on the authoring machine”.examples/27-openshift-crc/verify-crc.shpassesbash -nand checks:oc whoamicrc statusoc new-project hfd-ocp- image push to the internal registry
helm upgrade --install platform ... -f values-openshift.yaml --wait --rollback-on-failure- pods Ready with
openshift.io/scc: restricted-v2annotation - uid ≠ 1001 inside a pod (arbitrary UID)
- Route host resolves and
curl -k https://<route>/api/inforeturns 200 helm test- It prints PASS/FAIL per check.
- Decks:
presentation/helm-101/Helm-101-r1.0.pptxandpresentation/helm-201/Helm-201-r1.0.pptxexist. Slide counts are 32–40 and 38–46. Notes count equals slide count, checked by script. ~/.claude/skills/lgtm-professional-voice/scripts/scan.sh --tier ban --fail .exits 0, or the survivors are justified in_plans/voice-pass.md.grep -rniE '\bhonest(ly)?\b|capstone' _docs examples/*/README.mdreturns nothing.- Container: the shipping-service image’s
python -c 'import sys;print(sys.version_info[:2])'prints(3, 15), orCONTRIBUTING.mdand the reconciliation plan record the fallback with the reason. - Hub branch: YAML parses, the jekyll build exits 0, the diff of
books.ymlis additions only (9 entries), the new category lists 9 existing titles,sites.ymlhas ahelm-for-developersentry, andALLOWED_REPOScontainshelm-for-developers. - Git:
git log main --oneline | wc -l= 1 before S12.- All work sits on
feature/r1-initial-buildin Conventional Commits format. git log --format=%B | grep -ci 'co-authored-by\|generated with'= 0.- No remote exists until S12 is confirmed.
Risks
- Python 3.15 timing. GA is 2026-10-09, python-build-standalone 3.15.0 may lag by days, and cp315 wheels may be missing for asyncpg, pydantic-core or aiokafka. Detected by the S3 gate. Handled by recorded fallbacks F1/F2, never silently.
- Helm 4 flag drift. Executors may write Helm 3 flags from memory (
--atomic,--force, a path given to--post-renderer). Detected bycheck-helm-commands.shandforbidden-syntax.sh, with a validator spot-check. - Platform charts under Helm 4 SSA. The LGTM, CNPG and Strimzi installs may hit field-manager conflicts or need newer chart versions. Detected in S2/S5 bring-up. The pinned versions get bumped and recorded.
- Strimzi API version. 0.49+ introduced
kafka.strimzi.io/v1and v1beta2 is deprecated or removed in newer releases. The reused templates use v1beta2. Detected bykubectl api-resources --api-group=kafka.strimzi.ioin S5 and kubeconform. Use whatever the installed operator serves. - ct container bundling Helm 3. Detected by
ct version/helm versioninside ct. Handled by using the binary with the project-local Helm 4. - helm-diff / helm-unittest plugin install under Helm 4 verification. May need a verification flag. Detected by
helm plugin listin S2. - Wasm plugin build path (extism Go PDK + wasip1). May not work. Mitigation: chapter 22 marks it unverified with the exact error; the subprocess plugin carries the runnable demo.
- Argo CD pulling OCI from the in-cluster insecure registry may need specific repo-secret fields (
enableOCI,insecure). Detected in S7. The Git path waits for S12. - Parallel executors clobbering shared files (
_plans/reconciliation-plan.md,assets/diagrams/README.md, header nav). Handled by the ownership table: claims go to per-part files, and only the orchestrator commits. - Snapshot drift between
charts/(golden) and theexamples/*copies, e.g. a fix in golden not propagated. Detected bydemo.sh offlinein every example plus S7 live runs. Any fix found in S7 must be applied to both, and the validator diffs the final example (26) against golden. - Hub data loss. Running gen-books (with or without
--enrich) into_data/books.ymlwould wipe curated URLs andreview_notes, and dropotel-observability-tutorial. Handled by scratch-output-only rule; acceptance item 14 checks for additions only. - gen-books extraction quirks. Dash-before-title captures only the last author, parentheses in the CKAD title are rejected, and hard-wrapped citation lines are missed. Handled by the fixed citation format and the S9 dry-run diff.
- Ruby 4.0 with Jekyll 4.3 locally (missing default gems). Fallback: Ruby 3.3 container build. CI uses 3.3.
- Resource contention if the stopped
datameshprofile is started at the same time. The scripts only touchhelm4dev, andsetup-profile.shrefuses--replacewithout an explicit flag. - Self-promotion of verification. Executors may claim “verified” from a clean exit. Handled by S7 owning all promotions, with evidence files required (acceptance item 10).
- Book metadata (EPE authors, print vs ebook ISBNs). Detected by S9 verification against the O’Reilly platform and publisher pages, with
review_notewhere they differ.
Open questions for the user
- Python 3.15 base image. No UBI 3.15 image exists and GA is tomorrow. The plan’s default is UBI 10 minimal with a uv-installed CPython 3.15.0, falling back to 3.14 (same build), then
ubi9/python-314. Is a non-UBIpython:3.15-slimbase acceptable instead, if wheels or python-build-standalone lag? - Helm 4 install location. The plan installs Helm 4.3 project-locally (
.tools/), leaving the global Helm 3.18.3 alone. Would you rather upgrade~/.local/bin/helmglobally? That affects datamesh and MEA scripts. - Publishing. Confirm the public repo
patterncatalyst/helm-for-developersand GitHub Pages athttps://patterncatalyst.github.io/helm-for-developers/, and whether the hub change goes in as a PR or a direct push tomain. S12 waits for this either way.
Sources consulted for version facts:
- Helm 3 End of Life
- Helm v4 key changes from v3
- Helm 4 migration guide
- Python 3.15.0rc3
- PEP 790
- Python 3.15 stable set for Oct 9
gh release listfor helm/helm, chart-testing, helm-unittest, kubeconform, helm-diff, cosign
Critical Files for Implementation
- /home/rsedor/Dev/datamesh-reference-arch-python/examples/lgtm-datamesh/services/shipping-service/app/main.py (plus config.py, db.py)
- /home/rsedor/Dev/observability-python-otel-lgtm/services/common/obs/otel.py (plus kafka.py, kafka_propagation.py, services/Containerfile)
- /home/rsedor/Dev/datamesh-reference-arch-python/examples/lgtm-datamesh/charts/capstone/charts/{postgres,kafka,shipping-service}/templates/
- /home/rsedor/Dev/modernizing-enterprise-applications/examples/06-shipping-service/src/main/resources/db/migration/V1__create_shipments_table.sql (plus Shipment.java, ShipmentDispatched.java)
- /home/rsedor/Dev/patterncatalyst-workshops-tutorials-list/scripts/gen-books.py (plus _data/books.yml, _data/book_categories.yml, _data/sites.yml, CLAUDE.md)
- /home/rsedor/.claude/skills/lgtm-minikube-stack/templates/bootstrap.sh.template (plus setup-profile, setup-postgres-operator, setup-kafka-operator, setup-lgtm.sh)
- /home/rsedor/.claude/skills/lgtm-tutorial/references/chapter-template.md and /home/rsedor/.claude/skills/lgtm-jekyll/assets/site-template/
User decisions (2026-10-08)
- Base image: UBI10 ubi-minimal + uv-installed CPython 3.15.0; fallbacks F1 (3.14 same build) then F2 (ubi9/python-314), recorded, never silent. No Docker Hub python base.
- Helm 4 installed project-local under
.tools/; global~/.local/bin/helm(3.18.3) untouched. - Publishing (S12, re-confirm before running): public repo
patterncatalyst/helm-for-developers, GitHub Pages, hub change via PR. - Plan approved; execution started.
Step status
| Step | Status | |—|—| | S1 | done | | S2 | done | | S3 | done (F1: Python 3.14) | | S4 | done | | S5 | done (7/7 met) | | S6.0–S6.8 | done (+ repair pass) | | S7 | done (minikube; ch27 verified on CRC, see _plans/claims/s7-d.md) | | S8a/S8b | done | | S9 | done (hub branch, not pushed) | | S10 | done | | S11 | pending | | S12 | gated |
Plan change (2026-10-08): CRC available on the authoring machine
OpenShift Local 2.64.0 (OpenShift 4.22.14) and oc 4.22.17 installed in ~/.local/bin; crc config: preset openshift, memory 20480, cpus 6, disk 80, pull secret from ~/Downloads. User runs crc setup (sudo). Ch27 is now verified live in the last phase: after S7b/S7c finish, stop minikube helm4dev (no delete) to free memory, crc start, run examples/27-openshift-crc/verify-crc.sh, promote ch27 with evidence, drop the “untested on the authoring machine” banners in ch27, its README, and the 201 deck.