Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions .agents/skills/release-chart/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
---
name: release-chart
description: Cut and publish a new release of the Zabbix Helm chart in this repository, following the versioning rules and maintainer release process documented in CONTRIBUTING.md and CLAUDE.md (bump Chart.yaml/artifacthub-pkg.yml/values.yaml, regenerate docs, tag the release so CI publishes it). Trigger on requests like "release a new chart version", "cut a release", "bump the chart version", "publish v7.1.0", "prepare the next Zabbix chart release".
---

# Release a new version of the helm-zabbix chart

This skill walks through the maintainer-only release process documented in `CONTRIBUTING.md` ("For code mainteners only") and `CLAUDE.md` ("Versioning and release rules"). Its final steps are hard to reverse — pushing a git tag triggers a public GitHub Release via CI — so **always confirm the version number and each push/tag/PR action with the user before running it**. Do not skip confirmation because a step "seems obvious".

## Installing and invoking this skill

This repo keeps skills under `.agents/skills/` rather than `.claude/skills/` so the same file can be reused by any AI assistant that supports a skills convention, not just Claude Code. To get Claude Code's native `/release-chart` invocation, symlink this directory in:

- **Project-level** (this repo only):
```bash
mkdir -p .claude/skills
ln -s ../../.agents/skills/release-chart .claude/skills/release-chart
```
- **Personal** (available in every repo you work in):
```bash
mkdir -p ~/.claude/skills
ln -s /absolute/path/to/helm-zabbix/.agents/skills/release-chart ~/.claude/skills/release-chart
```

Once linked, run it with `/release-chart`, or just describe the task in natural language — e.g. "release a new chart version", "cut a release", "bump the chart version", "prepare the next Zabbix chart release" (these phrases match the `description` frontmatter above).

No symlink is strictly required to benefit from this file: `CLAUDE.md` already tells Claude Code to read and follow it whenever a maintainer asks to cut/publish a release, so it works out of the box in this repo. The symlink is only needed for the formal `/release-chart` slash invocation or to reuse the skill from other repositories.

## 0. Preconditions

- Confirm with the user (if not already given):
- The new chart `version` (and whether `appVersion`/`zabbixImageTag` — the Zabbix version — is also changing).
- Whether this is a **major** bump (the middle digit, e.g. `7.0.12` → `7.1.0` — signals a change that may require users to update their `values.yaml`) or a **minor** bump (the last digit, e.g. `7.0.12` → `7.0.13` — no API/interface changes).
- Verify all PRs intended for this release are already merged into `main`, and local `main` is up to date.
- Never bump versions or tag directly on `main` — always use a release branch.

## 1. Create the release branch

```bash
git checkout main
git pull upstream main
git checkout -b BRANCH_NAME
```

## 2. Run local tests

```bash
cd charts/zabbix
make help # lists all available targets with descriptions
make lint
```

Fix any lint errors before continuing.

## 3. Bump versions — exact files, nothing else

1. `charts/zabbix/Chart.yaml` — `version:` (chart version) and `appVersion:` (Zabbix version, only if it's changing).
2. `charts/zabbix/artifacthub-pkg.yml` — three separate spots, all must match `Chart.yaml`:
- `version:` and `appVersion:` fields near the top.
- `createdAt:` — set to the output of `date +%Y-%m-%dT%TZ`.
- The hardcoded `export ZABBIX_CHART_VERSION='...'` line inside the `install:` block. This file is plain YAML (not Go-templated), so this string must be edited by hand.
3. `charts/zabbix/values.yaml` — `zabbixImageTag:` if the Zabbix version (`appVersion`) changed.
4. If this is a **major** release: add a new subsection under "Breaking changes of this helm chart" in `charts/zabbix/README.md.gotmpl`, explaining what changed and what users need to check in their own `values.yaml`.

**Do not hand-edit** `charts/zabbix/README.md`, and do not touch the `export ZABBIX_CHART_VERSION=...` line inside `README.md.gotmpl` — that one is templated from `Chart.yaml`'s `version` via `{{ template "chart.version" . }}` and regenerates automatically in the next step. Only `artifacthub-pkg.yml`'s copy of that line is a plain hardcoded string.

## 4. Regenerate chart docs

```bash
cd charts/zabbix
make gen-docs
```

Confirm the resulting diff to `charts/zabbix/README.md` only touches the version number and (if `values.yaml` changed) the values table — nothing else should move.

## 5. Commit, push, and open a PR

Confirm with the user before pushing or opening the PR (visible, shared-state actions):

```bash
git add charts/zabbix/Chart.yaml charts/zabbix/artifacthub-pkg.yml charts/zabbix/values.yaml charts/zabbix/README.md charts/zabbix/README.md.gotmpl
git commit -m "Release x.y.z"
git push --set-upstream origin BRANCH_NAME
```

Open a PR to `main`, address review feedback, then merge.

## 6. Tag and publish — confirm explicitly before this step

After the release PR is merged into `main`:

```bash
git checkout main
git pull upstream main
git tag -a x.y.z -m "New release"
git push upstream --tags
```

Pushing the tag triggers `.github/workflows/helm-chart-releaser.yml`, which packages the chart and publishes a GitHub Release named `zabbix-x.y.z`. This is the point of no easy return for this process — do not run it without the user explicitly confirming the exact tag/version first.

## 7. Finalize release notes

Edit the auto-generated GitHub Release notes to match the style of previous releases (see the repo's Releases page). If this was a major release, make sure the breaking-changes write-up from step 3.4 is reflected in the release notes.

## Reference

- Full command-by-command detail: `CONTRIBUTING.md` → "For code mainteners only".
- Version semantics and cross-doc consistency notes: `CLAUDE.md` → "Versioning and release rules".
- A visual summary (Mermaid flowchart) of this same process: root `README.md` → "Release process".

Keep this file, `CONTRIBUTING.md`, and `CLAUDE.md` in sync — if the release steps change, update all three.
69 changes: 69 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Repository overview

This repo contains a single Helm chart, `charts/zabbix`, that deploys [Zabbix](https://www.zabbix.com) (monitoring solution) on Kubernetes, backed by PostgreSQL/TimescaleDB only (no MySQL/MariaDB support planned). There is no application source code — all logic lives in Helm templates (Go templates) and `values.yaml`.

## Common commands

All chart commands are run from `charts/zabbix/` and are wrapped in the `Makefile` there, which runs `helm`/`helm-docs` inside Docker containers (no local Helm install required):

```bash
cd charts/zabbix
make help # lists all targets below with their one-line descriptions
make lint # helm lint . (via dockerized helm)
make package # helm package . -d packages
make gen-docs # regenerates charts/zabbix/README.md from README.md.gotmpl via helm-docs (run after editing values.yaml)
```

`help` is self-documenting: it greps the Makefile for `target: ## description` comments, so any new target added with a trailing `## ...` comment shows up automatically — no separate list to maintain.

If `helm` is installed locally, the equivalent direct commands work too, e.g. `helm lint .` from `charts/zabbix/`.

There is no unit test suite in the traditional sense. Chart correctness is validated by:
- `helm lint`
- `helm template`/`--dry-run` against the chart
- The built-in Helm test hooks in `charts/zabbix/templates/tests/` (`test-server-connection.yaml`, `test-web-connection.yaml`), run post-install via `helm test <release> -n <namespace>`
- CI in `.github/workflows/tests.yaml`, which spins up `kind` clusters and runs full install/upgrade/test/uninstall cycles across three scenarios: internal DB without HA, external DB with HA + external secret, and external DB with HA without external secret. Each scenario also exercises upgrades across Zabbix LTS/non-LTS image tags (`ubuntu-6.0-latest`, default `appVersion`, `ubuntu-7.2-latest`).

To test changes locally against a real cluster (e.g. `kind`), follow `charts/zabbix/docs/example/README.md`, which uses `charts/zabbix/docs/example/kind/values.yaml` as an override file.

## Versioning and release rules (see CONTRIBUTING.md and README.md)

- Never bump `version`/`appVersion` in `charts/zabbix/Chart.yaml` or `charts/zabbix/artifacthub-pkg.yml` on your own initiative — that's the maintainers' release process, done via git tag (`zabbix-x.y.z` triggers `.github/workflows/helm-chart-releaser.yml`). If a maintainer explicitly asks to cut/publish a new release, use the `release-chart` skill at `.agents/skills/release-chart/SKILL.md` — it encodes the exact file list, ordering, and confirmation points (especially before pushing a tag, which is hard to reverse) instead of re-deriving the process from scratch.
- Never hand-edit `charts/zabbix/README.md` — it is generated by `make gen-docs` from `charts/zabbix/README.md.gotmpl` (which contains the prose/docs) plus the `values.yaml` comments (which become the values table). Edit the `.gotmpl` file and/or `values.yaml` comments, then regenerate.
- Keep `values.yaml` defaults working/sane, since templates reference them directly and CI installs with mostly-default values.
- The maintainer-only release steps are documented in three places, and all need to stay consistent if the process changes: `CONTRIBUTING.md` ("For code mainteners only" section, exact commands), the root `README.md` ("Release process" section, a summary plus a Mermaid flowchart), and `.agents/skills/release-chart/SKILL.md` (the actionable, step-by-step version meant to be followed directly).
- Version semantics: bumping the middle digit (`major`, e.g. `6.0.2` → `6.1.0`) signals a change that may require users to update their `values.yaml`; bumping the last digit (`minor`, e.g. `6.0.2` → `6.0.3`) is a safe, no-API-change upgrade.
- The root `README.md` also has a "Repository structure" section with an annotated directory tree. Update it (and this file, if the architecture notes below are affected) when adding, removing, or renaming top-level files/templates.

## Architecture

### Template/value organization

Every component follows the same pattern in `values.yaml`: a top-level key (`zabbixServer`, `zabbixProxy`, `zabbixAgent`, `zabbixWeb`, `zabbixWebService`, `zabbixJavaGateway`, `zabbixBrowserMonitoring`, `postgresql`) with `enabled`, `image`, `resources`, `extraEnv`, `extraVolumes`/`extraVolumeMounts`, `extraDeploymentAnnotations`/`extraDeploymentLabels`, `extraPodAnnotations`/`extraPodLabels`, etc. following consistent naming across components. `global.commonLabels` applies to all resources. When adding a new tunable, mirror the sibling component's pattern rather than inventing a new shape.

Each component's Kubernetes objects live in one template file named `<kind>-<component>.yaml` under `charts/zabbix/templates/` (e.g. `deployment-zabbix-server.yaml`, `statefulset-zabbix-proxy.yaml`, `daemonset-zabbix-agent.yaml`). Shared template helpers/macros are in `templates/_helpers.tpl`.

### Database access (`postgresAccess`)

All DB connection info (host/port/user/password/db/schema) is centralized in one Secret (named `<release>-db-access` by default, or `postgresAccess.existingSecretName` if pointing at an externally-managed secret, e.g. one generated by CNPG/PGO). The helper `zabbix.postgresAccess.variables` in `_helpers.tpl` generates the env vars for any container needing DB access, and its behavior branches on a `context` argument (`db_client` uses `PGHOST`/`PGUSER`/etc. for psql-based cron jobs, `db_init_upgrade` uses plain values instead of secret refs for the pre-install job, everything else uses `DB_SERVER_HOST`/`POSTGRES_USER`/etc. via `secretKeyRef`). When touching DB env var logic, changes usually need to be made in this one helper, not per-template.

### Zabbix Server High Availability (`zabbixServer.zabbixServerHA`)

This is the most complex part of the chart:
- HA is a native Zabbix Server feature (hot-standby via heartbeat rows in the DB), gated in this chart by `zabbixServer.zabbixServerHA.enabled`.
- HA is **mutually exclusive with `postgresql.enabled=true`** (enforced by a `fail` in `templates/job-create-upgrade-db.yaml`) — HA requires bringing your own (ideally HA) external Postgres.
- When HA is enabled, `templates/job-create-upgrade-db.yaml` runs as a Helm `pre-install,pre-upgrade` hook Job that prepares/migrates the DB schema and reconciles the `ha_node` table *before* any Zabbix Server pod starts (this ordering is why it can't be a post-install hook and why `postgresql.enabled` + HA can't coexist — Helm has no way to deploy a DB pod before a pre-install hook runs).
- A separate sidecar ("HA Labels sidecar", image from `zabbix-community/helm-zabbix-image-ha-labels-sidecar`) watches each Zabbix Server pod's process count to determine active/standby status and updates pod labels accordingly, so Services can route Active checks/Active Proxies to the right pod without probing the Zabbix Server port directly (probing pollutes Zabbix Server logs).
- `templates/cronjob-hanodes-autoclean.yaml`, `templates/role-ha-helper.yaml`, `templates/rolebinding-ha-helper.yaml`, `templates/serviceaccount-ha-helper.yaml` support this HA machinery (stale HA node cleanup, RBAC for the helper containers).
- See the "Native Zabbix Server High Availability" section of `charts/zabbix/README.md.gotmpl` before changing anything here — the reasoning behind the hook ordering and constraints is non-obvious and documented there.

### Other notable behaviors

- `templates/extra-manifests.yaml` lets users inject arbitrary extra manifests via `.Values.extraManifests`, rendered through `zabbix.tools.render` in `_helpers.tpl` (supports both plain YAML values and Helm template strings needing `tpl`).
- Zabbix Proxy (`statefulset-zabbix-proxy.yaml`) uses SQLite3 locally and supports multiple replicas for proxy groups; when replicated, `ZBX_HOSTNAME` can't be statically set and falls back to the pod name.
- Zabbix Agent supports both DaemonSet mode (`zabbixAgent.runAsDaemonSet=true`, uses `hostNetwork: true`) and Deployment/sidecar modes, plus a dynamic hostname mode via `ZBX_HOSTNAMEITEM`.
- Breaking changes between major chart versions are tracked in the "Breaking changes of this helm chart" section of `charts/zabbix/README.md.gotmpl` — check it when bumping `postgresAccess`, label/selector, or naming-convention behavior, since those have caused required-reinstall breakage before.
12 changes: 11 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ cd charts/zabbix
make lint
```

Run ``make help`` to list all available ``make`` targets (``lint``, ``package``, ``gen-docs``, etc.) with a short description of each:

```bash
cd charts/zabbix
make help
```

- Method using locally installed ``helm`` command:

```bash
Expand Down Expand Up @@ -107,6 +114,9 @@ References:

## For code mainteners only

> [!TIP]
> If you're using an AI coding assistant that supports skills (e.g. Claude Code), the `release-chart` skill at [.agents/skills/release-chart/SKILL.md](.agents/skills/release-chart/SKILL.md) automates the steps below end-to-end, including the exact files to bump and explicit confirmation points before any push/tag. Point your assistant at that file, or ask it to "release a new chart version", instead of following each step manually.

To generate a new release of the helm chart, follow these instructions:

- Review and merge the opened PRs
Expand Down Expand Up @@ -140,7 +150,7 @@ A **minor** is the "dot-dot" release. Example: *6.0.2* -> *6.0.3* is **minor upg
- Change the ``version`` and ``appVersion`` parameters (helm chart and Zabbix version, respectively) in ``charts/zabbix/Chart.yaml`` and ``charts/zabbix/artifacthub-pkg.yml`` files.
- Change the ``zabbixImageTag`` value (Zabbix version) in ``charts/zabbix/values.yaml`` file.
- Change the ``createdAt`` parameter in ``charts/zabbix/artifacthub-pkg.yml`` file using the output of the command ``date +%Y-%m-%dT%TZ`` command.
- Change the ``ZABBIX_CHART_VERSION`` variable in ``charts/zabbix/artifacthub-pkg.yml`` and ``charts/zabbix/README.md`` files.
- Change the ``ZABBIX_CHART_VERSION`` variable in ``charts/zabbix/artifacthub-pkg.yml``.
- Run the following commands to update the documentation of the helm chart.

```bash
Expand Down
Loading
Loading