From bf0c3020b574574a9dbc7be87ca8f9a1162332a1 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:15:14 +0530 Subject: [PATCH 01/11] feat(helm): auto-generate README with helm-docs Add helm-docs integration to auto-generate the Helm chart README from values.yaml comments, preventing documentation drift between the two files. Changes: - Add `# --` documentation comments to all values in values.yaml - Create README.md.gotmpl template for helm-docs generation - Add helm-docs installation support to setup-helm-tools.sh - Add README drift validation to test-helm.sh validate command - Enable helm-docs in CI workflow for validate task - Remove nginx-specific ingress examples (controller-neutral) The CI will now fail if README.md drifts from values.yaml, ensuring the documentation stays in sync with the chart configuration. Closes #2985 Made-with: Cursor --- .../actions/utils/setup-helm-tools/action.yml | 21 +- .github/workflows/_test.yml | 1 + helm/charts/iggy/README.md | 299 ++++++------------ helm/charts/iggy/README.md.gotmpl | 142 +++++++++ helm/charts/iggy/values.yaml | 156 ++++----- scripts/ci/setup-helm-tools.sh | 24 +- scripts/ci/test-helm.sh | 21 ++ 7 files changed, 385 insertions(+), 279 deletions(-) create mode 100644 helm/charts/iggy/README.md.gotmpl diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index 971796613e..620bd7426d 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -16,12 +16,16 @@ # under the License. name: setup-helm-tools -description: Install pinned Helm and optionally kind for Helm chart CI jobs +description: Install pinned Helm and optionally kind and helm-docs for Helm chart CI jobs inputs: install-kind: description: "Whether to install kind in addition to Helm" required: false default: "false" + install-helm-docs: + description: "Whether to install helm-docs for README generation" + required: false + default: "false" helm-version: description: "Helm release version" required: false @@ -38,6 +42,14 @@ inputs: description: "SHA256 checksum for the kind binary" required: false default: "eb244cbafcc157dff60cf68693c14c9a75c4e6e6fedaf9cd71c58117cb93e3fa" + helm-docs-version: + description: "helm-docs release version" + required: false + default: "v1.14.2" + helm-docs-checksum: + description: "SHA256 checksum for the helm-docs tarball" + required: false + default: "f3c755c2b9d319ba993e0b4cc80e77ae16c8533b1bb24048d3d013c73e10211b" runs: using: "composite" @@ -51,17 +63,22 @@ runs: exit 1 fi - - name: Install Helm and optional kind + - name: Install Helm and optional kind/helm-docs shell: bash env: HELM_VERSION: ${{ inputs.helm-version }} HELM_CHECKSUM: ${{ inputs.helm-checksum }} KIND_VERSION: ${{ inputs.kind-version }} KIND_CHECKSUM: ${{ inputs.kind-checksum }} + HELM_DOCS_VERSION: ${{ inputs.helm-docs-version }} + HELM_DOCS_CHECKSUM: ${{ inputs.helm-docs-checksum }} run: | set -euo pipefail args=() if [[ "${{ inputs.install-kind }}" == "true" ]]; then args+=(--install-kind) fi + if [[ "${{ inputs.install-helm-docs }}" == "true" ]]; then + args+=(--install-helm-docs) + fi scripts/ci/setup-helm-tools.sh "${args[@]}" diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 75a7b7c1dd..6567d4f83d 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -198,6 +198,7 @@ jobs: uses: ./.github/actions/utils/setup-helm-tools with: install-kind: ${{ inputs.task == 'smoke' }} + install-helm-docs: ${{ inputs.task == 'validate' }} - name: Setup Helm smoke cluster if: inputs.component == 'helm' && inputs.task == 'smoke' diff --git a/helm/charts/iggy/README.md b/helm/charts/iggy/README.md index 9082cb9685..b7d5e359ef 100644 --- a/helm/charts/iggy/README.md +++ b/helm/charts/iggy/README.md @@ -1,6 +1,8 @@ # iggy -A Helm chart for [Apache Iggy](https://github.com/apache/iggy) server and web-ui. +A Helm chart for Apache Iggy server and web-ui + +![Version: 0.5.0](https://img.shields.io/badge/Version-0.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.7.0](https://img.shields.io/badge/AppVersion-0.7.0-informational?style=flat-square) ## Prerequisites @@ -80,202 +82,7 @@ command line with `--set server.serviceMonitor.enabled=true`. helm uninstall iggy ``` -## Configuration - -### Server Configuration - -| Key | Type | Default | Description | -| --- | ---- | ------- | ----------- | -| `server.enabled` | bool | `true` | Enable the Iggy server deployment | -| `server.replicaCount` | int | `1` | Number of server replicas | -| `server.image.repository` | string | `"apache/iggy"` | Server image repository | -| `server.image.tag` | string | `"0.7.0"` | Server image tag | -| `server.ports.http` | int | `3000` | HTTP API port | -| `server.ports.tcp` | int | `8090` | TCP protocol port | -| `server.ports.quic` | int | `8080` | QUIC protocol port | - -### Persistence Configuration - -| Key | Type | Default | Description | -| --- | ---- | ------- | ----------- | -| `server.persistence.enabled` | bool | `false` | Enable persistence using PVC | -| `server.persistence.size` | string | `"8Gi"` | PVC storage size | -| `server.persistence.storageClass` | string | `""` | Storage class (empty = default) | -| `server.persistence.accessMode` | string | `"ReadWriteOnce"` | PVC access mode | -| `server.persistence.existingClaim` | string | `""` | Use existing PVC | - -### Security Configuration - -| Key | Type | Default | Description | -| --- | ---- | ------- | ----------- | -| `server.users.root.username` | string | `"iggy"` | Root user username | -| `server.users.root.password` | string | `"changeit"` | Root user password | -| `server.users.root.createSecret` | bool | `true` | Create secret for root user | -| `server.users.root.existingSecret.name` | string | `""` | Use existing secret | -| `securityContext.capabilities.add` | list | `["IPC_LOCK"]` | Server container capabilities (required for io_uring) | -| `podSecurityContext.seccompProfile.type` | string | `"Unconfined"` | Server pod seccomp profile (required for io_uring) | - -### Monitoring Configuration - -| Key | Type | Default | Description | -| --- | ---- | ------- | ----------- | -| `server.serviceMonitor.enabled` | bool | `false` | Enable ServiceMonitor for Prometheus Operator | -| `server.serviceMonitor.interval` | string | `"30s"` | Scrape interval | -| `server.serviceMonitor.path` | string | `"/metrics"` | Metrics endpoint path | - -### Web UI Configuration - -| Key | Type | Default | Description | -| --- | ---- | ------- | ----------- | -| `ui.enabled` | bool | `true` | Enable the Web UI deployment | -| `ui.replicaCount` | int | `1` | Number of UI replicas | -| `ui.image.repository` | string | `"apache/iggy-web-ui"` | UI image repository | -| `ui.ports.http` | int | `3050` | UI HTTP port | -| `ui.server.endpoint` | string | `""` | Iggy server endpoint (auto-detected if empty) | -| `ui.securityContext` | object | `{}` | UI container security context | -| `ui.podSecurityContext` | object | `{}` | UI pod security context | - -## Testing - -The chart CI paths are also available locally from the repository root. - -### Render Validation - -If `helm` is already installed locally: - -```bash -scripts/ci/test-helm.sh validate -``` - -If you want the pinned Linux CI tool version instead: - -```bash -scripts/ci/setup-helm-tools.sh -scripts/ci/test-helm.sh validate -``` - -This runs `helm lint --strict` plus the CI render scenarios, including: - -* default chart output -* all-features render -* legacy Kubernetes 1.18 API coverage -* server-only render -* UI-only render -* existing-secret render - -### Runtime Smoke Test - -The smoke path requires `helm`, `kind`, `kubectl`, and `curl`. - -Before running the local smoke path, keep these common gotchas in mind: - -* the Iggy server requires working `io_uring` support from the Kubernetes node/kernel/runtime -* the server also needs enough available memory and locked-memory headroom during startup -* `scripts/ci/test-helm.sh cleanup-smoke` removes the Helm release and smoke namespace, but it does not delete the reusable kind cluster created by `scripts/ci/setup-helm-smoke-cluster.sh` - -If `helm` and `kind` are already installed: - -```bash -scripts/ci/setup-helm-smoke-cluster.sh -scripts/ci/test-helm.sh smoke --cleanup -``` - -If you want the pinned Linux CI tool versions: - -```bash -scripts/ci/setup-helm-tools.sh --install-kind -scripts/ci/setup-helm-smoke-cluster.sh -scripts/ci/test-helm.sh smoke --cleanup -``` - -If a previous local smoke install failed and left resources behind, reset the smoke namespace with: - -```bash -scripts/ci/test-helm.sh cleanup-smoke -``` - -On Apple Silicon hosts, the released `apache/iggy:0.7.0` `arm64` image may still fail during the runtime smoke path in kind. If your Docker setup supports amd64 emulation well enough, you can try recreating the dedicated smoke cluster with: - -```bash -HELM_SMOKE_KIND_PLATFORM=linux/amd64 scripts/ci/setup-helm-smoke-cluster.sh -``` - -The smoke script defaults `IGGY_SYSTEM_SHARDING_CPU_ALLOCATION=1` for the server pod so the local kind path avoids the chart's `numa:auto` default and keeps the local runtime to a single shard, which has been more reliable on containerized local nodes. If you need a different local override, set `HELM_SMOKE_SERVER_CPU_ALLOCATION` before running `scripts/ci/test-helm.sh smoke`. Pass `--cleanup` to remove the smoke namespace after a successful run; omit it if you want to inspect the deployed resources. - -On smoke-test failures you can collect the same diagnostics as CI with: - -```bash -scripts/ci/test-helm.sh collect-smoke-diagnostics -``` - -> **Note:** `scripts/ci/setup-helm-tools.sh` currently supports Linux `x86_64` only. -> On other local platforms, install equivalent `helm` and `kind` binaries yourself and then use the same scripts above. -> The runtime smoke test may still fail on some local/containerized clusters if the node/kernel does not provide the `io_uring` support required by the server runtime even after the local sharding override, or if the local environment does not provide enough memory for the server to initialize cleanly. - -## Troubleshooting - -### Pod CrashLoopBackOff with "Out of memory" error - -If you see: - -```text -Cannot create runtime: Out of memory (os error 12) -``` - -This means io_uring cannot lock sufficient memory. Ensure: - -1. `securityContext.capabilities.add` includes `IPC_LOCK` -2. `podSecurityContext.seccompProfile.type` is `Unconfined` - -These server settings are set by default but may be overridden. - -### Pod CrashLoopBackOff with "Invalid argument" during server startup - -If the Iggy server exits with a panic similar to: - -```text -called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" } -``` - -the Kubernetes node may not support the `io_uring` runtime configuration required by the server. -This has been observed on local/container-based clusters even when `IPC_LOCK` and -`podSecurityContext.seccompProfile.type=Unconfined` are set. - -### ServiceMonitor CRD not found - -If you see: - -```text -no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" -``` - -Either install Prometheus Operator or disable ServiceMonitor: - -```bash -helm install iggy ./helm/charts/iggy --set server.serviceMonitor.enabled=false -``` - -### Server not accessible from other pods - -Ensure the server binds to `0.0.0.0` instead of `127.0.0.1`. This is configured by default via environment variables: - -* `IGGY_HTTP_ADDRESS=0.0.0.0:3000` -* `IGGY_TCP_ADDRESS=0.0.0.0:8090` -* `IGGY_QUIC_ADDRESS=0.0.0.0:8080` - -## Accessing the Server - -### Port Forward - -```bash -# HTTP API -kubectl port-forward svc/iggy 3000:3000 - -# Web UI -kubectl port-forward svc/iggy-ui 3050:3050 -``` - -### Using Ingress +## Using Ingress Enable ingress in values. Set `className` and any controller-specific annotations to match your ingress implementation: @@ -285,13 +92,109 @@ server: ingress: enabled: true className: "" + annotations: {} hosts: - host: iggy.example.com paths: - path: / pathType: Prefix + tls: [] + +ui: + ingress: + enabled: true + className: "" + annotations: {} + hosts: + - host: iggy-ui.example.com + paths: + - path: / + pathType: Prefix + tls: [] ``` +The chart is controller-neutral and works with any Ingress controller (nginx, Traefik, HAProxy, Contour, etc.). + ## Values -See [values.yaml](values.yaml) for the full list of configurable values. +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalLabels | object | `{}` | Additional labels for all resources | +| autoscaling.enabled | bool | `false` | Enable horizontal pod autoscaling | +| autoscaling.maxReplicas | int | `100` | Maximum replicas for autoscaling | +| autoscaling.minReplicas | int | `1` | Minimum replicas for autoscaling | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization for autoscaling | +| fullnameOverride | string | `""` | Override full release name | +| imagePullSecrets | list | `[]` | Image pull secrets for private registries | +| nameOverride | string | `""` | Override chart name | +| podAnnotations | object | `{}` | Pod annotations | +| podSecurityContext | object | `{"seccompProfile":{"type":"Unconfined"}}` | Pod security context (server uses io_uring, requires unconfined seccomp) | +| resources | object | `{}` | Resource limits and requests for server | +| securityContext | object | `{"capabilities":{"add":["IPC_LOCK"]}}` | Container security context (server requires IPC_LOCK for io_uring) | +| server | object | `{"affinity":{},"enabled":true,"env":[{"name":"RUST_LOG","value":"info"},{"name":"IGGY_HTTP_ADDRESS","value":"0.0.0.0:3000"},{"name":"IGGY_TCP_ADDRESS","value":"0.0.0.0:8090"},{"name":"IGGY_QUIC_ADDRESS","value":"0.0.0.0:8080"},{"name":"IGGY_WEBSOCKET_ADDRESS","value":"0.0.0.0:8092"}],"image":{"pullPolicy":"Always","repository":"apache/iggy","tag":"0.7.0"},"ingress":{"annotations":{},"className":"","enabled":false,"hosts":[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}],"tls":[]},"nodeSelector":{},"persistence":{"accessMode":"ReadWriteOnce","annotations":{},"enabled":false,"existingClaim":"","size":"8Gi","storageClass":""},"ports":{"http":3000,"quic":8080,"tcp":8090},"replicaCount":1,"service":{"port":3000,"type":"ClusterIP"},"serviceMonitor":{"additionalLabels":{},"enabled":false,"honorLabels":false,"interval":"30s","namespace":"","path":"/metrics","scrapeTimeout":"10s"},"tolerations":[],"users":{"root":{"createSecret":true,"existingSecret":{"name":"","passwordKey":"password","usernameKey":"username"},"password":"changeit","username":"iggy"}}}` | Iggy server configuration | +| server.affinity | object | `{}` | Affinity rules for server pods | +| server.enabled | bool | `true` | Enable the Iggy server deployment | +| server.env | list | `[{"name":"RUST_LOG","value":"info"},{"name":"IGGY_HTTP_ADDRESS","value":"0.0.0.0:3000"},{"name":"IGGY_TCP_ADDRESS","value":"0.0.0.0:8090"},{"name":"IGGY_QUIC_ADDRESS","value":"0.0.0.0:8080"},{"name":"IGGY_WEBSOCKET_ADDRESS","value":"0.0.0.0:8092"}]` | Environment variables for the server container | +| server.image.pullPolicy | string | `"Always"` | Image pull policy | +| server.image.repository | string | `"apache/iggy"` | Server image repository | +| server.image.tag | string | `"0.7.0"` | Server image tag (overrides chart appVersion) | +| server.ingress.annotations | object | `{}` | Ingress annotations (controller-specific) | +| server.ingress.className | string | `""` | Ingress class name (controller-neutral) | +| server.ingress.enabled | bool | `false` | Enable ingress for the server | +| server.ingress.hosts | list | `[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}]` | Ingress hosts configuration | +| server.ingress.tls | list | `[]` | Ingress TLS configuration | +| server.nodeSelector | object | `{}` | Node selector for server pods | +| server.persistence.accessMode | string | `"ReadWriteOnce"` | PVC access mode | +| server.persistence.annotations | object | `{}` | PVC annotations | +| server.persistence.enabled | bool | `false` | Enable persistence using PVC | +| server.persistence.existingClaim | string | `""` | Use existing PVC (requires persistence.enabled: true) | +| server.persistence.size | string | `"8Gi"` | PVC storage size | +| server.persistence.storageClass | string | `""` | Storage class for PVC (empty uses default provisioner) | +| server.ports.http | int | `3000` | HTTP API port | +| server.ports.quic | int | `8080` | QUIC protocol port | +| server.ports.tcp | int | `8090` | TCP protocol port | +| server.replicaCount | int | `1` | Number of server replicas | +| server.service.port | int | `3000` | Service port for the server | +| server.service.type | string | `"ClusterIP"` | Service type for the server | +| server.serviceMonitor.additionalLabels | object | `{}` | Additional labels for the ServiceMonitor | +| server.serviceMonitor.enabled | bool | `false` | Enable ServiceMonitor for Prometheus Operator | +| server.serviceMonitor.honorLabels | bool | `false` | Honor labels from the target | +| server.serviceMonitor.interval | string | `"30s"` | Scrape interval (fallback to Prometheus default) | +| server.serviceMonitor.namespace | string | `""` | Namespace to deploy the ServiceMonitor | +| server.serviceMonitor.path | string | `"/metrics"` | Path to scrape metrics from | +| server.serviceMonitor.scrapeTimeout | string | `"10s"` | Timeout for scrape metrics request | +| server.tolerations | list | `[]` | Tolerations for server pods | +| server.users.root.createSecret | bool | `true` | Create a secret for the root user credentials | +| server.users.root.existingSecret.name | string | `""` | Name of existing secret for root credentials | +| server.users.root.existingSecret.passwordKey | string | `"password"` | Key in secret for password | +| server.users.root.existingSecret.usernameKey | string | `"username"` | Key in secret for username | +| server.users.root.password | string | `"changeit"` | Root password | +| server.users.root.username | string | `"iggy"` | Root username | +| serviceAccount.annotations | object | `{}` | Service account annotations | +| serviceAccount.create | bool | `true` | Create a service account | +| serviceAccount.name | string | `""` | Service account name (generated if not set) | +| ui | object | `{"affinity":{},"enabled":true,"env":{},"image":{"pullPolicy":"Always","repository":"apache/iggy-web-ui","tag":"edge"},"ingress":{"annotations":{},"className":"","enabled":false,"hosts":[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}],"tls":[]},"nodeSelector":{},"podSecurityContext":{},"ports":{"http":3050},"replicaCount":1,"resources":{},"securityContext":{},"server":{"endpoint":""},"service":{"port":3050,"type":"ClusterIP"},"tolerations":[]}` | Iggy web UI configuration | +| ui.affinity | object | `{}` | Affinity rules for UI pods | +| ui.enabled | bool | `true` | Enable the web UI deployment | +| ui.env | object | `{}` | Extra environment variables for UI container | +| ui.image.pullPolicy | string | `"Always"` | UI image pull policy | +| ui.image.repository | string | `"apache/iggy-web-ui"` | UI image repository | +| ui.image.tag | string | `"edge"` | UI image tag (overrides chart appVersion) | +| ui.ingress.annotations | object | `{}` | Ingress annotations (controller-specific) | +| ui.ingress.className | string | `""` | Ingress class name (controller-neutral) | +| ui.ingress.enabled | bool | `false` | Enable ingress for the UI | +| ui.ingress.hosts | list | `[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}]` | Ingress hosts configuration | +| ui.ingress.tls | list | `[]` | Ingress TLS configuration | +| ui.nodeSelector | object | `{}` | Node selector for UI pods | +| ui.podSecurityContext | object | `{}` | Pod security context for UI pods | +| ui.ports.http | int | `3050` | HTTP port for web UI | +| ui.replicaCount | int | `1` | Number of UI replicas | +| ui.resources | object | `{}` | Resource limits and requests for UI | +| ui.securityContext | object | `{}` | Container security context for UI | +| ui.server.endpoint | string | `""` | Iggy server endpoint (blank uses service URL) | +| ui.service.port | int | `3050` | Service port for the UI | +| ui.service.type | string | `"ClusterIP"` | Service type for the UI | +| ui.tolerations | list | `[]` | Tolerations for UI pods | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/helm/charts/iggy/README.md.gotmpl b/helm/charts/iggy/README.md.gotmpl new file mode 100644 index 0000000000..6d8b1d53c0 --- /dev/null +++ b/helm/charts/iggy/README.md.gotmpl @@ -0,0 +1,142 @@ +{{- /* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ -}} +# {{ template "chart.name" . }} + +{{ template "chart.description" . }} + +{{ template "chart.versionBadge" . }}{{ template "chart.typeBadge" . }}{{ template "chart.appVersionBadge" . }} + +## Prerequisites + +* Kubernetes 1.19+ +* Helm 3.2.0+ +* PV provisioner support in the underlying infrastructure (if persistence is enabled) +* Prometheus Operator CRDs if `server.serviceMonitor.enabled=true` + +### io_uring Requirements + +Iggy server uses `io_uring` for high-performance async I/O. This requires: + +1. **IPC_LOCK capability** - For locking memory required by io_uring +2. **Unconfined seccomp profile** - To allow io_uring syscalls + +These are configured by default for the Iggy server via the chart's root-level +`securityContext` and `podSecurityContext`. The web UI uses `ui.securityContext` +and `ui.podSecurityContext`, which default to empty. + +Some local or container-based Kubernetes environments may still fail during Iggy runtime +initialization if the node/kernel does not provide the `io_uring` support required by the +server runtime. + +## Quick Start + +```bash +# Clone the repository +git clone https://github.com/apache/iggy.git +cd iggy + +# Install with persistence enabled +helm install iggy ./helm/charts/iggy \ + --set server.persistence.enabled=true + +# Install with custom root credentials +helm install iggy ./helm/charts/iggy \ + --set server.persistence.enabled=true \ + --set server.users.root.username=admin \ + --set server.users.root.password=secretpassword +``` + +> **Note:** `server.serviceMonitor.enabled` defaults to `false`. +> Enable it only if Prometheus Operator is installed and you want a `ServiceMonitor` resource. +> The server still requires node/kernel support for `io_uring`, including on clean local clusters such as `kind` or `minikube`. + +## Installation + +### From Git Repository + +```bash +git clone https://github.com/apache/iggy.git +cd iggy +helm install iggy ./helm/charts/iggy +``` + +### With Persistence + +```bash +helm install iggy ./helm/charts/iggy \ + --set server.persistence.enabled=true \ + --set server.persistence.size=50Gi +``` + +### With Custom Values File + +```bash +helm install iggy ./helm/charts/iggy -f custom-values.yaml +``` + +If Prometheus Operator is installed and you want monitoring, set +`server.serviceMonitor.enabled=true` in `custom-values.yaml` or pass it on the +command line with `--set server.serviceMonitor.enabled=true`. + +## Uninstallation + +```bash +helm uninstall iggy +``` + +## Using Ingress + +Enable ingress in values. Set `className` and any controller-specific annotations to match your +ingress implementation: + +```yaml +server: + ingress: + enabled: true + className: "" + annotations: {} + hosts: + - host: iggy.example.com + paths: + - path: / + pathType: Prefix + tls: [] + +ui: + ingress: + enabled: true + className: "" + annotations: {} + hosts: + - host: iggy-ui.example.com + paths: + - path: / + pathType: Prefix + tls: [] +``` + +The chart is controller-neutral and works with any Ingress controller (nginx, Traefik, HAProxy, Contour, etc.). + +{{ template "chart.requirementsSection" . }} + +## Values + +{{ template "chart.valuesTable" . }} + +{{ template "helm-docs.versionFooter" . }} diff --git a/helm/charts/iggy/values.yaml b/helm/charts/iggy/values.yaml index a7316942df..0c8e019f51 100644 --- a/helm/charts/iggy/values.yaml +++ b/helm/charts/iggy/values.yaml @@ -15,78 +15,80 @@ # specific language governing permissions and limitations # under the License. ---- -# Iggy server configuration +# -- Iggy server configuration server: + # -- Enable the Iggy server deployment enabled: true + # -- Number of server replicas replicaCount: 1 image: + # -- Server image repository repository: apache/iggy + # -- Image pull policy pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. + # -- Server image tag (overrides chart appVersion) tag: "0.7.0" ports: + # -- HTTP API port http: 3000 + # -- QUIC protocol port quic: 8080 + # -- TCP protocol port tcp: 8090 service: + # -- Service type for the server type: ClusterIP + # -- Service port for the server port: 3000 serviceMonitor: - # -- Enable this if you're using [Prometheus Operator](https://github.com/coreos/prometheus-operator) + # -- Enable ServiceMonitor for Prometheus Operator enabled: false # -- Namespace to deploy the ServiceMonitor namespace: "" - # -- Fallback to the prometheus default unless specified + # -- Scrape interval (fallback to Prometheus default) interval: 30s - # -- Add custom labels to the ServiceMonitor resource + # -- Additional labels for the ServiceMonitor additionalLabels: {} + # -- Honor labels from the target honorLabels: false - # -- Path to scrape metrics + # -- Path to scrape metrics from path: /metrics # -- Timeout for scrape metrics request scrapeTimeout: 10s users: root: - # -- Create a secret for the root user + # -- Create a secret for the root user credentials createSecret: true + # -- Root username username: iggy + # -- Root password password: changeit - # -- Whether to use an existing secret for the root user existingSecret: + # -- Name of existing secret for root credentials name: "" - # -- Key in the secret to get the root username from + # -- Key in secret for username usernameKey: username - # -- Key in the secret to get the root password from + # -- Key in secret for password passwordKey: password - # -- Add persistence volume claim configuration persistence: - # -- Enable persistence using a PVC + # -- Enable persistence using PVC enabled: false # -- PVC annotations annotations: {} - # -- Persistent Volume Storage Class - # If defined, storageClassName: - # If set to "-", storageClassName: "", which disables dynamic provisioning - # If undefined (the default) or set to null, no storageClassName spec is - # set, choosing the default provisioner. (gp2 on AWS, standard on - # GKE, AWS & OpenStack) + # -- Storage class for PVC (empty uses default provisioner) storageClass: "" - - # -- A manually managed Persistent Volume and Claim - # Requires persistence.enabled: true - # If defined, PVC must be created manually before volume will be bound + # -- Use existing PVC (requires persistence.enabled: true) existingClaim: "" - - # -- PVC Access mode + # -- PVC access mode accessMode: ReadWriteOnce - # -- PVC claim size + # -- PVC storage size size: 8Gi - # -- Set up environmental variables to be added to the container + + # -- Environment variables for the server container env: - name: RUST_LOG value: info @@ -99,134 +101,134 @@ server: - name: IGGY_WEBSOCKET_ADDRESS value: "0.0.0.0:8092" + # -- Node selector for server pods nodeSelector: {} + # -- Tolerations for server pods tolerations: [] + # -- Affinity rules for server pods affinity: {} ingress: + # -- Enable ingress for the server enabled: false + # -- Ingress class name (controller-neutral) className: "" + # -- Ingress annotations (controller-specific) annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" + # -- Ingress hosts configuration hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific - tls: - [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local + # -- Ingress TLS configuration + tls: [] -# Iggy web-ui configuration +# -- Iggy web UI configuration ui: + # -- Enable the web UI deployment enabled: true ports: + # -- HTTP port for web UI http: 3050 server: - # -- Set the Iggy server endpoint explicitly. If kept blank, the Iggy service URL will be used + # -- Iggy server endpoint (blank uses service URL) endpoint: "" service: + # -- Service type for the UI type: ClusterIP + # -- Service port for the UI port: 3050 + # -- Number of UI replicas replicaCount: 1 - # -- Extra environmental variables to add to the container + # -- Extra environment variables for UI container env: {} image: + # -- UI image repository repository: apache/iggy-web-ui + # -- UI image pull policy pullPolicy: Always - # Overrides the image tag whose default is the chart appVersion. + # -- UI image tag (overrides chart appVersion) tag: "edge" ingress: + # -- Enable ingress for the UI enabled: false + # -- Ingress class name (controller-neutral) className: "" + # -- Ingress annotations (controller-specific) annotations: {} - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" + # -- Ingress hosts configuration hosts: - host: chart-example.local paths: - path: / pathType: ImplementationSpecific + # -- Ingress TLS configuration tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - resources: - {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - - # -- Web UI pod security context. Leave empty unless your UI deployment needs explicit pod-level settings. + # -- Resource limits and requests for UI + resources: {} + + # -- Pod security context for UI pods podSecurityContext: {} - # -- Web UI container security context. Leave empty unless your UI deployment needs explicit container-level settings. + # -- Container security context for UI securityContext: {} + # -- Node selector for UI pods nodeSelector: {} + # -- Tolerations for UI pods tolerations: [] + # -- Affinity rules for UI pods affinity: {} +# -- Image pull secrets for private registries imagePullSecrets: [] +# -- Override chart name nameOverride: "" +# -- Override full release name fullnameOverride: "" -# -- Additional labels to add to all resources +# -- Additional labels for all resources additionalLabels: {} serviceAccount: - # Specifies whether a service account should be created + # -- Create a service account create: true - # Annotations to add to the service account + # -- Service account annotations annotations: {} - # The name of the service account to use. - # If not set and create is true, a name is generated using the fullname template + # -- Service account name (generated if not set) name: "" +# -- Pod annotations podAnnotations: {} +# -- Pod security context (server uses io_uring, requires unconfined seccomp) podSecurityContext: - # Required for Iggy server io_uring syscalls in containerized environments seccompProfile: type: Unconfined +# -- Container security context (server requires IPC_LOCK for io_uring) securityContext: capabilities: add: - # Required for Iggy server memlock (io_uring memory) - IPC_LOCK -resources: - {} - # We usually recommend not to specify default resources and to leave this as a conscious - # choice for the user. This also increases chances charts run on environments with little - # resources, such as Minikube. If you do want to specify resources, uncomment the following - # lines, adjust them as necessary, and remove the curly braces after 'resources:'. - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi +# -- Resource limits and requests for server +resources: {} autoscaling: + # -- Enable horizontal pod autoscaling enabled: false + # -- Minimum replicas for autoscaling minReplicas: 1 + # -- Maximum replicas for autoscaling maxReplicas: 100 + # -- Target CPU utilization for autoscaling targetCPUUtilizationPercentage: 80 + # -- Target memory utilization for autoscaling (optional) # targetMemoryUtilizationPercentage: 80 diff --git a/scripts/ci/setup-helm-tools.sh b/scripts/ci/setup-helm-tools.sh index 5c4a2686fb..ee36ca021c 100755 --- a/scripts/ci/setup-helm-tools.sh +++ b/scripts/ci/setup-helm-tools.sh @@ -22,27 +22,34 @@ set -euo pipefail usage() { cat <<'EOF' -Usage: scripts/ci/setup-helm-tools.sh [--install-kind] +Usage: scripts/ci/setup-helm-tools.sh [--install-kind] [--install-helm-docs] Install the pinned Helm toolchain used by Helm chart CI jobs. When requested, -also install the pinned kind binary used by the Helm smoke test. +also install the pinned kind binary used by the Helm smoke test or helm-docs +for README generation. Environment: HELM_VERSION Helm release version (default: v4.1.3) HELM_CHECKSUM SHA256 checksum for the Helm tarball KIND_VERSION kind release version (default: v0.31.0) KIND_CHECKSUM SHA256 checksum for the kind binary + HELM_DOCS_VERSION helm-docs release version (default: v1.14.2) + HELM_DOCS_CHECKSUM SHA256 checksum for the helm-docs tarball HELM_TOOLS_BIN_DIR Target binary directory (default: /usr/local/bin) EOF } INSTALL_KIND="false" +INSTALL_HELM_DOCS="false" while [ $# -gt 0 ]; do case "$1" in --install-kind) INSTALL_KIND="true" ;; + --install-helm-docs) + INSTALL_HELM_DOCS="true" + ;; --help|-h|help) usage exit 0 @@ -60,6 +67,8 @@ HELM_VERSION="${HELM_VERSION:-v4.1.3}" HELM_CHECKSUM="${HELM_CHECKSUM:-02ce9722d541238f81459938b84cf47df2fdf1187493b4bfb2346754d82a4700}" KIND_VERSION="${KIND_VERSION:-v0.31.0}" KIND_CHECKSUM="${KIND_CHECKSUM:-eb244cbafcc157dff60cf68693c14c9a75c4e6e6fedaf9cd71c58117cb93e3fa}" +HELM_DOCS_VERSION="${HELM_DOCS_VERSION:-v1.14.2}" +HELM_DOCS_CHECKSUM="${HELM_DOCS_CHECKSUM:-f3c755c2b9d319ba993e0b4cc80e77ae16c8533b1bb24048d3d013c73e10211b}" HELM_TOOLS_BIN_DIR="${HELM_TOOLS_BIN_DIR:-/usr/local/bin}" require_command() { @@ -109,3 +118,14 @@ if [ "$INSTALL_KIND" = "true" ]; then echo "${KIND_CHECKSUM} ${kind_binary}" | sha256sum -c - install_binary "$kind_binary" "${HELM_TOOLS_BIN_DIR}/kind" fi + +if [ "$INSTALL_HELM_DOCS" = "true" ]; then + helm_docs_archive="/tmp/helm-docs.tar.gz" + helm_docs_dir="/tmp/helm-docs-extract" + wget -qO "$helm_docs_archive" "https://github.com/norwoodj/helm-docs/releases/download/${HELM_DOCS_VERSION}/helm-docs_${HELM_DOCS_VERSION#v}_Linux_x86_64.tar.gz" + echo "${HELM_DOCS_CHECKSUM} ${helm_docs_archive}" | sha256sum -c - + rm -rf "$helm_docs_dir" + mkdir -p "$helm_docs_dir" + tar -zxf "$helm_docs_archive" -C "$helm_docs_dir" helm-docs + install_binary "$helm_docs_dir/helm-docs" "${HELM_TOOLS_BIN_DIR}/helm-docs" +fi diff --git a/scripts/ci/test-helm.sh b/scripts/ci/test-helm.sh index c8cd377f50..c9b73c1559 100755 --- a/scripts/ci/test-helm.sh +++ b/scripts/ci/test-helm.sh @@ -145,6 +145,25 @@ extract_kind_names() { ' "$file" } +validate_helm_docs() { + if ! command -v helm-docs >/dev/null 2>&1; then + echo "Warning: helm-docs not found, skipping README drift check" >&2 + return 0 + fi + + local readme_before + local readme_after + + readme_before="$(cat "$CHART_DIR/README.md")" + helm-docs --chart-search-root "$CHART_DIR" --template-files README.md.gotmpl + readme_after="$(cat "$CHART_DIR/README.md")" + + if [ "$readme_before" != "$readme_after" ]; then + echo "Error: README.md is out of sync with values.yaml. Run 'helm-docs' locally and commit the updated README." >&2 + exit 1 + fi +} + validate() { require_command helm @@ -218,6 +237,8 @@ validate() { exit 1 fi grep -q 'name: supersecret' "$HELM_RENDER_DIR/existing-secret.yaml" + + validate_helm_docs } smoke() { From d01c7881e4ea79b18ac25b515366ef508f68cd86 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:18:48 +0530 Subject: [PATCH 02/11] fix: correct helm-docs checksum and exclude generated README from lint - Fix helm-docs SHA256 checksum for v1.14.2 Linux x86_64 - Exclude helm/charts/iggy/README.md from markdown linting since it's auto-generated by helm-docs and its format can't be easily controlled Made-with: Cursor --- .github/actions/utils/setup-helm-tools/action.yml | 2 +- scripts/ci/markdownlint.sh | 3 ++- scripts/ci/setup-helm-tools.sh | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index 620bd7426d..f6e5b71651 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -49,7 +49,7 @@ inputs: helm-docs-checksum: description: "SHA256 checksum for the helm-docs tarball" required: false - default: "f3c755c2b9d319ba993e0b4cc80e77ae16c8533b1bb24048d3d013c73e10211b" + default: "a8cf72ada34fad93285ba2a452b38bdc5bd52cc9a571236244ec31022928d6cc" runs: using: "composite" diff --git a/scripts/ci/markdownlint.sh b/scripts/ci/markdownlint.sh index 61ba624678..60bf739f1d 100755 --- a/scripts/ci/markdownlint.sh +++ b/scripts/ci/markdownlint.sh @@ -45,7 +45,8 @@ if ! command -v markdownlint &> /dev/null; then fi # Files to ignore (in addition to .gitignore) -IGNORE_FILES="CLAUDE.md" +# helm/charts/iggy/README.md is auto-generated by helm-docs +IGNORE_FILES="CLAUDE.md,helm/charts/iggy/README.md" if [ "$MODE" = "fix" ]; then echo "🔧 Fixing markdown files..." diff --git a/scripts/ci/setup-helm-tools.sh b/scripts/ci/setup-helm-tools.sh index ee36ca021c..4f2d6e6886 100755 --- a/scripts/ci/setup-helm-tools.sh +++ b/scripts/ci/setup-helm-tools.sh @@ -68,7 +68,7 @@ HELM_CHECKSUM="${HELM_CHECKSUM:-02ce9722d541238f81459938b84cf47df2fdf1187493b4bf KIND_VERSION="${KIND_VERSION:-v0.31.0}" KIND_CHECKSUM="${KIND_CHECKSUM:-eb244cbafcc157dff60cf68693c14c9a75c4e6e6fedaf9cd71c58117cb93e3fa}" HELM_DOCS_VERSION="${HELM_DOCS_VERSION:-v1.14.2}" -HELM_DOCS_CHECKSUM="${HELM_DOCS_CHECKSUM:-f3c755c2b9d319ba993e0b4cc80e77ae16c8533b1bb24048d3d013c73e10211b}" +HELM_DOCS_CHECKSUM="${HELM_DOCS_CHECKSUM:-a8cf72ada34fad93285ba2a452b38bdc5bd52cc9a571236244ec31022928d6cc}" HELM_TOOLS_BIN_DIR="${HELM_TOOLS_BIN_DIR:-/usr/local/bin}" require_command() { From faaba7ba89dcaaa29e86b6510e18c9523a1bb291 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:24:15 +0530 Subject: [PATCH 03/11] fix: use separate --ignore flags for markdownlint markdownlint-cli requires separate --ignore flags for each file, not comma-separated values Made-with: Cursor --- scripts/ci/markdownlint.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/ci/markdownlint.sh b/scripts/ci/markdownlint.sh index 60bf739f1d..7fe0c2b13e 100755 --- a/scripts/ci/markdownlint.sh +++ b/scripts/ci/markdownlint.sh @@ -46,15 +46,15 @@ fi # Files to ignore (in addition to .gitignore) # helm/charts/iggy/README.md is auto-generated by helm-docs -IGNORE_FILES="CLAUDE.md,helm/charts/iggy/README.md" +IGNORE_ARGS=(--ignore "helm/charts/iggy/README.md") if [ "$MODE" = "fix" ]; then echo "🔧 Fixing markdown files..." - markdownlint '**/*.md' --ignore-path .gitignore --ignore "$IGNORE_FILES" --fix + markdownlint '**/*.md' --ignore-path .gitignore "${IGNORE_ARGS[@]}" --fix echo "✅ Markdown files have been fixed" else echo "🔍 Checking markdown files..." - if markdownlint '**/*.md' --ignore-path .gitignore --ignore "$IGNORE_FILES"; then + if markdownlint '**/*.md' --ignore-path .gitignore "${IGNORE_ARGS[@]}"; then echo "✅ All markdown files are properly formatted" else echo "❌ Markdown linting failed" From 0a9400965c05dacb176623bd977c050830fa3300 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:30:17 +0530 Subject: [PATCH 04/11] feat: add yamllint for Helm chart YAML validation - Add .yamllint.yml config for helm chart (ignores templates/ with Go templating) - Add yamllint validation to test-helm.sh validate - Add install-yamllint option to setup-helm-tools action - Enable yamllint in CI workflow for validate task This ensures values.yaml and Chart.yaml follow consistent YAML formatting while excluding template files that contain Go templating syntax. Made-with: Cursor --- .../actions/utils/setup-helm-tools/action.yml | 11 +++- .github/workflows/_test.yml | 1 + helm/charts/iggy/.yamllint.yml | 65 +++++++++++++++++++ scripts/ci/test-helm.sh | 11 ++++ 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 helm/charts/iggy/.yamllint.yml diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index f6e5b71651..0a771e98dc 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -16,7 +16,7 @@ # under the License. name: setup-helm-tools -description: Install pinned Helm and optionally kind and helm-docs for Helm chart CI jobs +description: Install pinned Helm and optionally kind, helm-docs, and yamllint for Helm chart CI jobs inputs: install-kind: description: "Whether to install kind in addition to Helm" @@ -26,6 +26,10 @@ inputs: description: "Whether to install helm-docs for README generation" required: false default: "false" + install-yamllint: + description: "Whether to install yamllint for YAML linting" + required: false + default: "false" helm-version: description: "Helm release version" required: false @@ -82,3 +86,8 @@ runs: args+=(--install-helm-docs) fi scripts/ci/setup-helm-tools.sh "${args[@]}" + + - name: Install yamllint + if: inputs.install-yamllint == 'true' + shell: bash + run: pip install yamllint diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 6567d4f83d..a48f8a5850 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -199,6 +199,7 @@ jobs: with: install-kind: ${{ inputs.task == 'smoke' }} install-helm-docs: ${{ inputs.task == 'validate' }} + install-yamllint: ${{ inputs.task == 'validate' }} - name: Setup Helm smoke cluster if: inputs.component == 'helm' && inputs.task == 'smoke' diff --git a/helm/charts/iggy/.yamllint.yml b/helm/charts/iggy/.yamllint.yml new file mode 100644 index 0000000000..b2bdc28583 --- /dev/null +++ b/helm/charts/iggy/.yamllint.yml @@ -0,0 +1,65 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# yamllint configuration for Helm charts +# Note: templates/ contains Go templating which yamllint cannot parse, +# so we only lint values.yaml and Chart.yaml + +yaml-files: + - '*.yaml' + - '*.yml' + +ignore: | + templates/ + +rules: + braces: + min-spaces-inside: 0 + max-spaces-inside: 1 + brackets: + min-spaces-inside: 0 + max-spaces-inside: 0 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + comments: + require-starting-space: true + min-spaces-from-content: 1 + document-end: disable + document-start: disable + empty-lines: + max: 2 + max-start: 0 + max-end: 1 + indentation: + spaces: 2 + indent-sequences: true + key-duplicates: enable + line-length: + max: 200 + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + new-line-at-end-of-file: enable + new-lines: + type: unix + trailing-spaces: enable + truthy: + allowed-values: ['true', 'false', 'yes', 'no'] diff --git a/scripts/ci/test-helm.sh b/scripts/ci/test-helm.sh index c9b73c1559..70ecb219b3 100755 --- a/scripts/ci/test-helm.sh +++ b/scripts/ci/test-helm.sh @@ -145,6 +145,16 @@ extract_kind_names() { ' "$file" } +validate_yamllint() { + if ! command -v yamllint >/dev/null 2>&1; then + echo "Warning: yamllint not found, skipping YAML lint check" >&2 + return 0 + fi + + echo "Running yamllint on Helm chart..." + yamllint -c "$CHART_DIR/.yamllint.yml" "$CHART_DIR" +} + validate_helm_docs() { if ! command -v helm-docs >/dev/null 2>&1; then echo "Warning: helm-docs not found, skipping README drift check" >&2 @@ -238,6 +248,7 @@ validate() { fi grep -q 'name: supersecret' "$HELM_RENDER_DIR/existing-secret.yaml" + validate_yamllint validate_helm_docs } From 348ac6fc08efeb1f005d32766ca60a8b0b4563a5 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:33:33 +0530 Subject: [PATCH 05/11] feat: add helmfmt for Helm template formatting - Add helmfmt to format Go template syntax in Helm templates - Add install-helmfmt option to setup-helm-tools action - Add validate_helmfmt() to test-helm.sh validate - Format all existing templates with helmfmt helmfmt properly indents Go template control structures (if/else/range/with) making templates more readable while keeping them valid. Made-with: Cursor --- .../actions/utils/setup-helm-tools/action.yml | 14 ++++ .github/workflows/_test.yml | 1 + helm/charts/iggy/templates/_helpers.tpl | 42 +++++----- helm/charts/iggy/templates/deployment.yaml | 84 +++++++++---------- helm/charts/iggy/templates/hpa.yaml | 22 ++--- helm/charts/iggy/templates/iggy-pvc.yaml | 6 +- helm/charts/iggy/templates/ingress.yaml | 80 +++++++++--------- .../charts/iggy/templates/servicemonitor.yaml | 4 +- scripts/ci/test-helm.sh | 14 ++++ 9 files changed, 148 insertions(+), 119 deletions(-) diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index 0a771e98dc..dfb3acc754 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -30,6 +30,10 @@ inputs: description: "Whether to install yamllint for YAML linting" required: false default: "false" + install-helmfmt: + description: "Whether to install helmfmt for Helm template formatting" + required: false + default: "false" helm-version: description: "Helm release version" required: false @@ -91,3 +95,13 @@ runs: if: inputs.install-yamllint == 'true' shell: bash run: pip install yamllint + + - name: Install helmfmt + if: inputs.install-helmfmt == 'true' + shell: bash + run: | + set -euo pipefail + HELMFMT_VERSION="v0.5.0" + wget -qO /tmp/helmfmt.tar.gz "https://github.com/digitalstudium/helmfmt/releases/download/${HELMFMT_VERSION}/helmfmt_${HELMFMT_VERSION#v}_linux_amd64.tar.gz" + tar -xzf /tmp/helmfmt.tar.gz -C /tmp helmfmt + sudo install -m 0755 /tmp/helmfmt /usr/local/bin/helmfmt diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index a48f8a5850..5feb0e5ae1 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -200,6 +200,7 @@ jobs: install-kind: ${{ inputs.task == 'smoke' }} install-helm-docs: ${{ inputs.task == 'validate' }} install-yamllint: ${{ inputs.task == 'validate' }} + install-helmfmt: ${{ inputs.task == 'validate' }} - name: Setup Helm smoke cluster if: inputs.component == 'helm' && inputs.task == 'smoke' diff --git a/helm/charts/iggy/templates/_helpers.tpl b/helm/charts/iggy/templates/_helpers.tpl index 9f6b2fdcc9..92f69780e0 100644 --- a/helm/charts/iggy/templates/_helpers.tpl +++ b/helm/charts/iggy/templates/_helpers.tpl @@ -11,23 +11,23 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this If release name contains chart name it will be used as a full name. */}} {{- define "iggy.fullname" -}} -{{- if .Values.fullnameOverride }} + {{- if .Values.fullnameOverride }} {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} + {{- else }} + {{- $name := default .Chart.Name .Values.nameOverride }} + {{- if contains $name .Release.Name }} {{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} + {{- else }} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} + {{- end }} + {{- end }} {{- end }} {{/* Create chart name and version as used by the chart label. */}} {{- define "iggy.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* @@ -36,15 +36,15 @@ Common labels {{- define "iggy.labels" -}} helm.sh/chart: {{ include "iggy.chart" . }} {{ include "iggy.selectorLabels" . }} -{{- if .Chart.AppVersion }} + {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} + {{- end }} app.kubernetes.io/component: server app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/part-of: iggy-server -{{- if .Values.additionalLabels }} + {{- if .Values.additionalLabels }} {{ toYaml .Values.additionalLabels }} -{{- end }} + {{- end }} {{- end }} {{/* @@ -59,7 +59,7 @@ app.kubernetes.io/instance: {{ .Release.Name }} Create chart name and version as used by the chart label. */}} {{- define "iggy-ui.chart" -}} -{{- printf "%s-ui-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} + {{- printf "%s-ui-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{- end }} {{/* @@ -68,15 +68,15 @@ Common labels {{- define "iggy-ui.labels" -}} helm.sh/chart: {{ include "iggy-ui.chart" . }} {{ include "iggy-ui.selectorLabels" . }} -{{- if .Chart.AppVersion }} + {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} + {{- end }} app.kubernetes.io/component: server app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/part-of: iggy-server -{{- if .Values.additionalLabels }} + {{- if .Values.additionalLabels }} {{ toYaml .Values.additionalLabels }} -{{- end }} + {{- end }} {{- end }} {{/* @@ -91,9 +91,9 @@ app.kubernetes.io/instance: {{ .Release.Name }}-ui Create the name of the service account to use */}} {{- define "iggy.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} + {{- if .Values.serviceAccount.create }} {{- default (include "iggy.fullname" .) .Values.serviceAccount.name }} -{{- else }} + {{- else }} {{- default "default" .Values.serviceAccount.name }} -{{- end }} + {{- end }} {{- end }} diff --git a/helm/charts/iggy/templates/deployment.yaml b/helm/charts/iggy/templates/deployment.yaml index d669d6aba7..ba76362c8b 100644 --- a/helm/charts/iggy/templates/deployment.yaml +++ b/helm/charts/iggy/templates/deployment.yaml @@ -15,9 +15,9 @@ # specific language governing permissions and limitations # under the License. {{ if .Values.server.enabled }} -{{- if hasKey .Values.server "podSecurityContext" }} -{{- fail "server.podSecurityContext has been moved to podSecurityContext (root level). Please update your values." }} -{{- end }} + {{- if hasKey .Values.server "podSecurityContext" }} + {{- fail "server.podSecurityContext has been moved to podSecurityContext (root level). Please update your values." }} + {{- end }} --- apiVersion: apps/v1 kind: Deployment @@ -34,17 +34,17 @@ spec: {{ include "iggy.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} + {{- with .Values.podAnnotations }} annotations: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} labels: {{ include "iggy.labels" . | nindent 8 }} spec: - {{- with .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} serviceAccountName: {{ include "iggy.serviceAccountName" . }} securityContext: {{ toYaml .Values.podSecurityContext | nindent 8 }} @@ -65,7 +65,7 @@ spec: containerPort: {{ .Values.server.ports.quic }} protocol: TCP env: - {{ if .Values.server.users.root.existingSecret.name }} + {{ if .Values.server.users.root.existingSecret.name }} - name: IGGY_ROOT_USERNAME valueFrom: secretKeyRef: @@ -76,7 +76,7 @@ spec: secretKeyRef: name: {{ .Values.server.users.root.existingSecret.name }} key: {{ .Values.server.users.root.existingSecret.passwordKey }} - {{ else }}{{ if .Values.server.users.root.createSecret }} + {{ else }}{{ if .Values.server.users.root.createSecret }} - name: IGGY_ROOT_USERNAME valueFrom: secretKeyRef: @@ -87,13 +87,13 @@ spec: secretKeyRef: name: {{ include "iggy.fullname" . }}-root-credentials key: password - {{- end }}{{- end}} - {{ if .Values.server.env }} - {{- range .Values.server.env }} + {{- end }}{{- end}} + {{ if .Values.server.env }} + {{- range .Values.server.env }} - name: {{ .name }} value: {{ .value | quote }} - {{- end }} - {{ end }} + {{- end }} + {{ end }} volumeMounts: - name: iggy-server-data mountPath: /app/local_data @@ -115,26 +115,26 @@ spec: port: http resources: {{- toYaml .Values.resources | nindent 12 }} - {{- with .Values.server.nodeSelector }} + {{- with .Values.server.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.server.affinity }} + {{- end }} + {{- with .Values.server.affinity }} affinity: {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.server.tolerations }} + {{- end }} + {{- with .Values.server.tolerations }} tolerations: {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} volumes: - name: iggy-server-data - {{- if .Values.server.persistence.enabled }} + {{- if .Values.server.persistence.enabled }} persistentVolumeClaim: claimName: {{ if .Values.server.persistence.existingClaim }}{{ .Values.server.persistence.existingClaim }}{{- else }}{{ template "iggy.fullname" . }}{{- end }} - {{- else }} + {{- else }} emptyDir: {} - {{- end }} + {{- end }} {{- end }} {{ if .Values.ui.enabled }} --- @@ -151,28 +151,28 @@ spec: {{ include "iggy-ui.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} + {{- with .Values.podAnnotations }} annotations: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} labels: {{ include "iggy-ui.labels" . | nindent 8 }}-ui spec: - {{- with .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} serviceAccountName: {{ include "iggy.serviceAccountName" . }} - {{- with .Values.ui.podSecurityContext }} + {{- with .Values.ui.podSecurityContext }} securityContext: {{ toYaml . | nindent 8 }} - {{- end }} + {{- end }} containers: - name: {{ .Chart.Name }} - {{- with .Values.ui.securityContext }} + {{- with .Values.ui.securityContext }} securityContext: {{ toYaml . | nindent 12 }} - {{- end }} + {{- end }} image: "{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.ui.image.pullPolicy }} ports: @@ -191,23 +191,23 @@ spec: {{ toYaml .Values.ui.resources | nindent 12 }} env: - name: PUBLIC_IGGY_API_URL - {{- if .Values.ui.server.endpoint }} + {{- if .Values.ui.server.endpoint }} value: {{ .Values.ui.server.endpoint }} - {{- else }} + {{- else }} value: http://{{ include "iggy.fullname" . }}:{{ .Values.server.ports.http }}{{- end }} - {{- with .Values.ui.env }} + {{- with .Values.ui.env }} {{ . | toYaml | nindent 10 }} - {{- end }} - {{- with .Values.ui.nodeSelector }} + {{- end }} + {{- with .Values.ui.nodeSelector }} nodeSelector: {{ toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.ui.affinity }} + {{- end }} + {{- with .Values.ui.affinity }} affinity: {{ toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.ui.tolerations }} + {{- end }} + {{- with .Values.ui.tolerations }} tolerations: {{ toYaml . | nindent 8 }} - {{- end }} -{{- end }} + {{- end }} + {{- end }} diff --git a/helm/charts/iggy/templates/hpa.yaml b/helm/charts/iggy/templates/hpa.yaml index 5d9f635d9a..51612fdc02 100644 --- a/helm/charts/iggy/templates/hpa.yaml +++ b/helm/charts/iggy/templates/hpa.yaml @@ -15,11 +15,11 @@ # specific language governing permissions and limitations # under the License. {{ if .Values.autoscaling.enabled -}} -{{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion -}} + {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: autoscaling/v2 -{{- else -}} + {{- else -}} apiVersion: autoscaling/v2beta2 -{{- end }} + {{- end }} kind: HorizontalPodAutoscaler metadata: name: {{ include "iggy.fullname" . }} @@ -33,28 +33,28 @@ spec: minReplicas: {{ .Values.autoscaling.minReplicas }} maxReplicas: {{ .Values.autoscaling.maxReplicas }} metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - type: Resource resource: name: cpu - {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion }} + {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion }} target: type: Utilization averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- else }} + {{- else }} targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory - {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion }} + {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion }} target: type: Utilization averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- else }} + {{- else }} targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} {{- end }} + {{- end }} {{- end }} diff --git a/helm/charts/iggy/templates/iggy-pvc.yaml b/helm/charts/iggy/templates/iggy-pvc.yaml index c1a5e8cb5d..64fbc20dc6 100644 --- a/helm/charts/iggy/templates/iggy-pvc.yaml +++ b/helm/charts/iggy/templates/iggy-pvc.yaml @@ -34,10 +34,10 @@ spec: requests: storage: {{ .Values.server.persistence.size | quote }} {{- with .Values.server.persistence.storageClass }} - {{- if (eq "-" .) }} + {{- if (eq "-" .) }} storageClassName: "" - {{- else }} + {{- else }} storageClassName: "{{ . }}" - {{- end }} + {{- end }} {{- end }} {{- end }} diff --git a/helm/charts/iggy/templates/ingress.yaml b/helm/charts/iggy/templates/ingress.yaml index b0339e5741..5996ca4196 100644 --- a/helm/charts/iggy/templates/ingress.yaml +++ b/helm/charts/iggy/templates/ingress.yaml @@ -15,20 +15,20 @@ # specific language governing permissions and limitations # under the License. {{ if .Values.server.ingress.enabled -}} -{{ $fullName := include "iggy.fullname" . -}} -{{ $svcPort := .Values.server.service.port -}} -{{- if and .Values.server.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.server.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.server.ingress.annotations "kubernetes.io/ingress.class" .Values.server.ingress.className}} + {{ $fullName := include "iggy.fullname" . -}} + {{ $svcPort := .Values.server.service.port -}} + {{- if and .Values.server.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.server.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.server.ingress.annotations "kubernetes.io/ingress.class" .Values.server.ingress.className}} + {{- end }} {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} + {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1beta1 -{{- else -}} + {{- else -}} apiVersion: extensions/v1beta1 -{{- end }} + {{- end }} kind: Ingress metadata: name: {{ $fullName }} @@ -46,51 +46,51 @@ spec: tls: {{- range .Values.server.ingress.tls }} - hosts: - {{- range .hosts }} + {{- range .hosts }} - {{ . | quote }} - {{- end }} + {{- end }} secretName: {{ .secretName }} {{- end }} {{- end }} rules: - {{- range .Values.server.ingress.hosts }} + {{- range .Values.server.ingress.hosts }} - host: {{ .host | quote }} http: paths: - {{- range .paths }} + {{- range .paths }} - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} pathType: {{ .pathType }} - {{- end }} + {{- end }} backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: name: {{ $fullName }} port: number: {{ $svcPort }} - {{- else }} + {{- else }} serviceName: {{ $fullName }} servicePort: {{ $svcPort }} - {{- end }} - {{- end }} + {{- end }} {{- end }} + {{- end }} {{- end }} {{ if .Values.ui.ingress.enabled -}} --- -{{ $fullName := include "iggy.fullname" . -}} -{{ $svcPort := .Values.ui.service.port -}} -{{- if and .Values.ui.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} - {{- if not (hasKey .Values.ui.ingress.annotations "kubernetes.io/ingress.class") }} - {{- $_ := set .Values.ui.ingress.annotations "kubernetes.io/ingress.class" .Values.ui.ingress.className}} + {{ $fullName := include "iggy.fullname" . -}} + {{ $svcPort := .Values.ui.service.port -}} + {{- if and .Values.ui.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ui.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ui.ingress.annotations "kubernetes.io/ingress.class" .Values.ui.ingress.className}} + {{- end }} {{- end }} -{{- end }} -{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} + {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1 -{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} + {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} apiVersion: networking.k8s.io/v1beta1 -{{- else -}} + {{- else -}} apiVersion: extensions/v1beta1 -{{- end }} + {{- end }} kind: Ingress metadata: name: {{ $fullName }}-ui @@ -108,32 +108,32 @@ spec: tls: {{- range .Values.ui.ingress.tls }} - hosts: - {{- range .hosts }} + {{- range .hosts }} - {{ . | quote }} - {{- end }} + {{- end }} secretName: {{ .secretName }} {{- end }} {{- end }} rules: - {{- range .Values.ui.ingress.hosts }} + {{- range .Values.ui.ingress.hosts }} - host: {{ .host | quote }} http: paths: - {{- range .paths }} + {{- range .paths }} - path: {{ .path }} - {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} pathType: {{ .pathType }} - {{- end }} + {{- end }} backend: - {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} service: name: {{ $fullName }}-ui port: number: {{ $svcPort }} - {{- else }} + {{- else }} serviceName: {{ $fullName }}-ui servicePort: {{ $svcPort }} - {{- end }} - {{- end }} + {{- end }} {{- end }} + {{- end }} {{- end }} diff --git a/helm/charts/iggy/templates/servicemonitor.yaml b/helm/charts/iggy/templates/servicemonitor.yaml index 5bd623f869..a7e799e967 100644 --- a/helm/charts/iggy/templates/servicemonitor.yaml +++ b/helm/charts/iggy/templates/servicemonitor.yaml @@ -22,9 +22,9 @@ kind: ServiceMonitor metadata: labels: {{- include "iggy.labels" . | nindent 4 }} - {{- if .Values.server.serviceMonitor.additionalLabels }} + {{- if .Values.server.serviceMonitor.additionalLabels }} {{ toYaml .Values.server.serviceMonitor.additionalLabels }} - {{- end }} + {{- end }} name: {{ template "iggy.fullname" . }} namespace: {{ .Release.Namespace }} spec: diff --git a/scripts/ci/test-helm.sh b/scripts/ci/test-helm.sh index 70ecb219b3..6bb1a41b7c 100755 --- a/scripts/ci/test-helm.sh +++ b/scripts/ci/test-helm.sh @@ -155,6 +155,19 @@ validate_yamllint() { yamllint -c "$CHART_DIR/.yamllint.yml" "$CHART_DIR" } +validate_helmfmt() { + if ! command -v helmfmt >/dev/null 2>&1; then + echo "Warning: helmfmt not found, skipping Helm template format check" >&2 + return 0 + fi + + echo "Checking Helm template formatting..." + if ! helmfmt --check "$CHART_DIR"; then + echo "Error: Helm templates are not formatted. Run 'helmfmt $CHART_DIR' locally and commit the changes." >&2 + exit 1 + fi +} + validate_helm_docs() { if ! command -v helm-docs >/dev/null 2>&1; then echo "Warning: helm-docs not found, skipping README drift check" >&2 @@ -249,6 +262,7 @@ validate() { grep -q 'name: supersecret' "$HELM_RENDER_DIR/existing-secret.yaml" validate_yamllint + validate_helmfmt validate_helm_docs } From c512d9a693eaa8f189fe317abda8f7ae82b2e1aa Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:37:41 +0530 Subject: [PATCH 06/11] feat: add pre-commit hooks for Helm and update README - Add helmfmt pre-commit hook for template formatting - Add yamllint pre-commit hook for values.yaml and Chart.yaml - Add helm-docs pre-commit hook for README generation - Update README.md.gotmpl with Development section documenting tools Made-with: Cursor --- .pre-commit-config.yaml | 24 ++++++++++++++++++ helm/charts/iggy/README.md | 41 +++++++++++++++++++++++++++++++ helm/charts/iggy/README.md.gotmpl | 41 +++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d47136dc23..3a7d20f66a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -268,3 +268,27 @@ repos: files: ^(foreign|examples)/csharp/.*\.cs$ pass_filenames: false stages: [pre-push] + + # Helm chart formatting and linting + - repo: local + hooks: + - id: helmfmt + name: helmfmt + entry: helmfmt + language: system + files: ^helm/charts/.*/templates/.*\.(yaml|tpl)$ + pass_filenames: true + + - id: yamllint-helm + name: yamllint (helm) + entry: yamllint -c helm/charts/iggy/.yamllint.yml + language: system + files: ^helm/charts/iggy/(values\.yaml|Chart\.yaml)$ + pass_filenames: true + + - id: helm-docs + name: helm-docs + entry: bash -c 'cd helm/charts/iggy && helm-docs' + language: system + files: ^helm/charts/iggy/(values\.yaml|README\.md\.gotmpl)$ + pass_filenames: false diff --git a/helm/charts/iggy/README.md b/helm/charts/iggy/README.md index b7d5e359ef..d3dc307929 100644 --- a/helm/charts/iggy/README.md +++ b/helm/charts/iggy/README.md @@ -115,6 +115,47 @@ ui: The chart is controller-neutral and works with any Ingress controller (nginx, Traefik, HAProxy, Contour, etc.). +## Development + +### Formatting and Linting + +This chart uses automated tools to maintain code quality: + +| Tool | Purpose | Files | +|------|---------|-------| +| [helm-docs](https://github.com/norwoodj/helm-docs) | Auto-generate this README | `values.yaml` → `README.md` | +| [yamllint](https://github.com/adrienverge/yamllint) | YAML formatting | `values.yaml`, `Chart.yaml` | +| [helmfmt](https://github.com/digitalstudium/helmfmt) | Helm template formatting | `templates/*.yaml`, `*.tpl` | + +### Local Development + +```bash +# Install tools (macOS) +brew install norwoodj/tap/helm-docs +pip install yamllint +go install github.com/digitalstudium/helmfmt@latest + +# Format templates +helmfmt helm/charts/iggy/ + +# Lint YAML files +yamllint -c helm/charts/iggy/.yamllint.yml helm/charts/iggy/ + +# Regenerate README after changing values.yaml +cd helm/charts/iggy && helm-docs + +# Run all validations +scripts/ci/test-helm.sh validate +``` + +### Pre-commit Hooks + +These tools are integrated with pre-commit. Install hooks with: + +```bash +pre-commit install +``` + ## Values | Key | Type | Default | Description | diff --git a/helm/charts/iggy/README.md.gotmpl b/helm/charts/iggy/README.md.gotmpl index 6d8b1d53c0..becaec8723 100644 --- a/helm/charts/iggy/README.md.gotmpl +++ b/helm/charts/iggy/README.md.gotmpl @@ -135,6 +135,47 @@ The chart is controller-neutral and works with any Ingress controller (nginx, Tr {{ template "chart.requirementsSection" . }} +## Development + +### Formatting and Linting + +This chart uses automated tools to maintain code quality: + +| Tool | Purpose | Files | +|------|---------|-------| +| [helm-docs](https://github.com/norwoodj/helm-docs) | Auto-generate this README | `values.yaml` → `README.md` | +| [yamllint](https://github.com/adrienverge/yamllint) | YAML formatting | `values.yaml`, `Chart.yaml` | +| [helmfmt](https://github.com/digitalstudium/helmfmt) | Helm template formatting | `templates/*.yaml`, `*.tpl` | + +### Local Development + +```bash +# Install tools (macOS) +brew install norwoodj/tap/helm-docs +pip install yamllint +go install github.com/digitalstudium/helmfmt@latest + +# Format templates +helmfmt helm/charts/iggy/ + +# Lint YAML files +yamllint -c helm/charts/iggy/.yamllint.yml helm/charts/iggy/ + +# Regenerate README after changing values.yaml +cd helm/charts/iggy && helm-docs + +# Run all validations +scripts/ci/test-helm.sh validate +``` + +### Pre-commit Hooks + +These tools are integrated with pre-commit. Install hooks with: + +```bash +pre-commit install +``` + ## Values {{ template "chart.valuesTable" . }} From 5254504d1133786031103a3acef06ce764a09169 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:39:15 +0530 Subject: [PATCH 07/11] fix: correct helmfmt download URL for Linux x86_64 Made-with: Cursor --- .github/actions/utils/setup-helm-tools/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index dfb3acc754..d6a11500d6 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -102,6 +102,6 @@ runs: run: | set -euo pipefail HELMFMT_VERSION="v0.5.0" - wget -qO /tmp/helmfmt.tar.gz "https://github.com/digitalstudium/helmfmt/releases/download/${HELMFMT_VERSION}/helmfmt_${HELMFMT_VERSION#v}_linux_amd64.tar.gz" + wget -qO /tmp/helmfmt.tar.gz "https://github.com/digitalstudium/helmfmt/releases/download/${HELMFMT_VERSION}/helmfmt_Linux_x86_64.tar.gz" tar -xzf /tmp/helmfmt.tar.gz -C /tmp helmfmt sudo install -m 0755 /tmp/helmfmt /usr/local/bin/helmfmt From b941e3ac2def7d5ced6cc7a1e5a72acc4cbe1418 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:45:02 +0530 Subject: [PATCH 08/11] fix: eliminate trailing whitespace in rendered Helm templates - Add missing `-` to template directives to properly trim whitespace - Fixes 14 trailing whitespace lines in rendered output - Re-run helmfmt to maintain consistent formatting Made-with: Cursor --- helm/charts/iggy/templates/deployment.yaml | 44 +++++++++---------- helm/charts/iggy/templates/service.yaml | 4 +- .../charts/iggy/templates/servicemonitor.yaml | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/helm/charts/iggy/templates/deployment.yaml b/helm/charts/iggy/templates/deployment.yaml index ba76362c8b..c07651d17d 100644 --- a/helm/charts/iggy/templates/deployment.yaml +++ b/helm/charts/iggy/templates/deployment.yaml @@ -24,34 +24,34 @@ kind: Deployment metadata: name: {{ include "iggy.fullname" . }} labels: - {{ include "iggy.labels" . | nindent 4 }} + {{- include "iggy.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.server.replicaCount }} {{- end }} selector: matchLabels: - {{ include "iggy.selectorLabels" . | nindent 6 }} + {{- include "iggy.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} labels: - {{ include "iggy.labels" . | nindent 8 }} + {{- include "iggy.labels" . | nindent 8 }} spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "iggy.serviceAccountName" . }} securityContext: - {{ toYaml .Values.podSecurityContext | nindent 8 }} + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - name: {{ .Chart.Name }} securityContext: - {{ toYaml .Values.securityContext | nindent 12 }} + {{- toYaml .Values.securityContext | nindent 12 }} image: "{{ .Values.server.image.repository }}:{{ .Values.server.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.server.image.pullPolicy }} ports: @@ -65,7 +65,7 @@ spec: containerPort: {{ .Values.server.ports.quic }} protocol: TCP env: - {{ if .Values.server.users.root.existingSecret.name }} + {{- if .Values.server.users.root.existingSecret.name }} - name: IGGY_ROOT_USERNAME valueFrom: secretKeyRef: @@ -76,7 +76,7 @@ spec: secretKeyRef: name: {{ .Values.server.users.root.existingSecret.name }} key: {{ .Values.server.users.root.existingSecret.passwordKey }} - {{ else }}{{ if .Values.server.users.root.createSecret }} + {{- else }}{{- if .Values.server.users.root.createSecret }} - name: IGGY_ROOT_USERNAME valueFrom: secretKeyRef: @@ -88,12 +88,12 @@ spec: name: {{ include "iggy.fullname" . }}-root-credentials key: password {{- end }}{{- end}} - {{ if .Values.server.env }} + {{- if .Values.server.env }} {{- range .Values.server.env }} - name: {{ .name }} value: {{ .value | quote }} {{- end }} - {{ end }} + {{- end }} volumeMounts: - name: iggy-server-data mountPath: /app/local_data @@ -143,35 +143,35 @@ kind: Deployment metadata: name: {{ include "iggy.fullname" . }}-ui labels: - {{ include "iggy-ui.labels" . | nindent 4 }} + {{- include "iggy-ui.labels" . | nindent 4 }} spec: replicas: {{ .Values.ui.replicaCount }} selector: matchLabels: - {{ include "iggy-ui.selectorLabels" . | nindent 6 }} + {{- include "iggy-ui.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} labels: - {{ include "iggy-ui.labels" . | nindent 8 }}-ui + {{- include "iggy-ui.labels" . | nindent 8 }}-ui spec: {{- with .Values.imagePullSecrets }} imagePullSecrets: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} serviceAccountName: {{ include "iggy.serviceAccountName" . }} {{- with .Values.ui.podSecurityContext }} securityContext: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} containers: - name: {{ .Chart.Name }} {{- with .Values.ui.securityContext }} securityContext: - {{ toYaml . | nindent 12 }} + {{- toYaml . | nindent 12 }} {{- end }} image: "{{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.ui.image.pullPolicy }} @@ -188,7 +188,7 @@ spec: path: /healthz port: http resources: - {{ toYaml .Values.ui.resources | nindent 12 }} + {{- toYaml .Values.ui.resources | nindent 12 }} env: - name: PUBLIC_IGGY_API_URL {{- if .Values.ui.server.endpoint }} @@ -200,14 +200,14 @@ spec: {{- end }} {{- with .Values.ui.nodeSelector }} nodeSelector: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.ui.affinity }} affinity: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- with .Values.ui.tolerations }} tolerations: - {{ toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} {{- end }} diff --git a/helm/charts/iggy/templates/service.yaml b/helm/charts/iggy/templates/service.yaml index 98ef767fac..b16c0bfd51 100644 --- a/helm/charts/iggy/templates/service.yaml +++ b/helm/charts/iggy/templates/service.yaml @@ -46,7 +46,7 @@ kind: Service metadata: name: {{ include "iggy.fullname" . }}-ui labels: - {{ include "iggy-ui.labels" . | nindent 4 }} + {{- include "iggy-ui.labels" . | nindent 4 }} spec: type: {{ .Values.ui.service.type }} ports: @@ -55,5 +55,5 @@ spec: targetPort: http protocol: TCP selector: - {{ include "iggy-ui.selectorLabels" . | nindent 4 }} + {{- include "iggy-ui.selectorLabels" . | nindent 4 }} {{- end }} \ No newline at end of file diff --git a/helm/charts/iggy/templates/servicemonitor.yaml b/helm/charts/iggy/templates/servicemonitor.yaml index a7e799e967..a3837f676f 100644 --- a/helm/charts/iggy/templates/servicemonitor.yaml +++ b/helm/charts/iggy/templates/servicemonitor.yaml @@ -23,7 +23,7 @@ metadata: labels: {{- include "iggy.labels" . | nindent 4 }} {{- if .Values.server.serviceMonitor.additionalLabels }} - {{ toYaml .Values.server.serviceMonitor.additionalLabels }} + {{- toYaml .Values.server.serviceMonitor.additionalLabels }} {{- end }} name: {{ template "iggy.fullname" . }} namespace: {{ .Release.Namespace }} From fbafca3f400e5e5924f6e8d93e2850a09533f91f Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Thu, 2 Apr 2026 05:49:28 +0530 Subject: [PATCH 09/11] fix: add trailing newline to service.yaml Made-with: Cursor --- helm/charts/iggy/templates/service.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/charts/iggy/templates/service.yaml b/helm/charts/iggy/templates/service.yaml index b16c0bfd51..86464d2833 100644 --- a/helm/charts/iggy/templates/service.yaml +++ b/helm/charts/iggy/templates/service.yaml @@ -56,4 +56,4 @@ spec: protocol: TCP selector: {{- include "iggy-ui.selectorLabels" . | nindent 4 }} -{{- end }} \ No newline at end of file +{{- end }} From fabbd7173269290240aa4216d4871d2777a759c3 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Sat, 11 Apr 2026 06:48:05 +0530 Subject: [PATCH 10/11] =?UTF-8?q?fix(helm):=20address=20PR=20review=20?= =?UTF-8?q?=E2=80=94=20checksum,=20ServiceMonitor=20labels,=20README=20sec?= =?UTF-8?q?tions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Verify helmfmt Linux tarball with sha256sum in setup-helm-tools action - Fix additionalLabels in ServiceMonitor using nindent (helmfmt-safe YAML) - Restore Testing, Troubleshooting, Port Forward, and Ingress in README gotmpl Made-with: Cursor --- .../actions/utils/setup-helm-tools/action.yml | 7 + helm/charts/iggy/README.md | 142 +++++++++++++++++- helm/charts/iggy/README.md.gotmpl | 142 +++++++++++++++++- .../charts/iggy/templates/servicemonitor.yaml | 2 +- 4 files changed, 290 insertions(+), 3 deletions(-) diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index d6a11500d6..2d7564c7d9 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -58,6 +58,10 @@ inputs: description: "SHA256 checksum for the helm-docs tarball" required: false default: "a8cf72ada34fad93285ba2a452b38bdc5bd52cc9a571236244ec31022928d6cc" + helmfmt-checksum: + description: "SHA256 checksum for the helmfmt Linux x86_64 tarball" + required: false + default: "17e6de3266b7bfeb50f4e425736d3362c3c7a01bf9756710b1d350f9ced78fb2" runs: using: "composite" @@ -99,9 +103,12 @@ runs: - name: Install helmfmt if: inputs.install-helmfmt == 'true' shell: bash + env: + HELMFMT_CHECKSUM: ${{ inputs.helmfmt-checksum }} run: | set -euo pipefail HELMFMT_VERSION="v0.5.0" wget -qO /tmp/helmfmt.tar.gz "https://github.com/digitalstudium/helmfmt/releases/download/${HELMFMT_VERSION}/helmfmt_Linux_x86_64.tar.gz" + echo "${HELMFMT_CHECKSUM} /tmp/helmfmt.tar.gz" | sha256sum -c - tar -xzf /tmp/helmfmt.tar.gz -C /tmp helmfmt sudo install -m 0755 /tmp/helmfmt /usr/local/bin/helmfmt diff --git a/helm/charts/iggy/README.md b/helm/charts/iggy/README.md index d3dc307929..07958aa39f 100644 --- a/helm/charts/iggy/README.md +++ b/helm/charts/iggy/README.md @@ -82,7 +82,147 @@ command line with `--set server.serviceMonitor.enabled=true`. helm uninstall iggy ``` -## Using Ingress +## Testing + +The chart CI paths are also available locally from the repository root. + +### Render Validation + +If `helm` is already installed locally: + +```bash +scripts/ci/test-helm.sh validate +``` + +If you want the pinned Linux CI tool version instead: + +```bash +scripts/ci/setup-helm-tools.sh +scripts/ci/test-helm.sh validate +``` + +This runs `helm lint --strict` plus the CI render scenarios, including: + +* default chart output +* all-features render +* legacy Kubernetes 1.18 API coverage +* server-only render +* UI-only render +* existing-secret render + +### Runtime Smoke Test + +The smoke path requires `helm`, `kind`, `kubectl`, and `curl`. + +Before running the local smoke path, keep these common gotchas in mind: + +* the Iggy server requires working `io_uring` support from the Kubernetes node/kernel/runtime +* the server also needs enough available memory and locked-memory headroom during startup +* `scripts/ci/test-helm.sh cleanup-smoke` removes the Helm release and smoke namespace, but it does not delete the reusable kind cluster created by `scripts/ci/setup-helm-smoke-cluster.sh` + +If `helm` and `kind` are already installed: + +```bash +scripts/ci/setup-helm-smoke-cluster.sh +scripts/ci/test-helm.sh smoke --cleanup +``` + +If you want the pinned Linux CI tool versions: + +```bash +scripts/ci/setup-helm-tools.sh --install-kind +scripts/ci/setup-helm-smoke-cluster.sh +scripts/ci/test-helm.sh smoke --cleanup +``` + +If a previous local smoke install failed and left resources behind, reset the smoke namespace with: + +```bash +scripts/ci/test-helm.sh cleanup-smoke +``` + +On Apple Silicon hosts, the released `apache/iggy:0.7.0` `arm64` image may still fail during the runtime smoke path in kind. If your Docker setup supports amd64 emulation well enough, you can try recreating the dedicated smoke cluster with: + +```bash +HELM_SMOKE_KIND_PLATFORM=linux/amd64 scripts/ci/setup-helm-smoke-cluster.sh +``` + +The smoke script defaults `IGGY_SYSTEM_SHARDING_CPU_ALLOCATION=1` for the server pod so the local kind path avoids the chart's `numa:auto` default and keeps the local runtime to a single shard, which has been more reliable on containerized local nodes. If you need a different local override, set `HELM_SMOKE_SERVER_CPU_ALLOCATION` before running `scripts/ci/test-helm.sh smoke`. Pass `--cleanup` to remove the smoke namespace after a successful run; omit it if you want to inspect the deployed resources. + +On smoke-test failures you can collect the same diagnostics as CI with: + +```bash +scripts/ci/test-helm.sh collect-smoke-diagnostics +``` + +> **Note:** `scripts/ci/setup-helm-tools.sh` currently supports Linux `x86_64` only. +> On other local platforms, install equivalent `helm` and `kind` binaries yourself and then use the same scripts above. +> The runtime smoke test may still fail on some local/containerized clusters if the node/kernel does not provide the `io_uring` support required by the server runtime even after the local sharding override, or if the local environment does not provide enough memory for the server to initialize cleanly. + +## Troubleshooting + +### Pod CrashLoopBackOff with "Out of memory" error + +If you see: + +```text +Cannot create runtime: Out of memory (os error 12) +``` + +This means io_uring cannot lock sufficient memory. Ensure: + +1. `securityContext.capabilities.add` includes `IPC_LOCK` +2. `podSecurityContext.seccompProfile.type` is `Unconfined` + +These server settings are set by default but may be overridden. + +### Pod CrashLoopBackOff with "Invalid argument" during server startup + +If the Iggy server exits with a panic similar to: + +```text +called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" } +``` + +the Kubernetes node may not support the `io_uring` runtime configuration required by the server. +This has been observed on local/container-based clusters even when `IPC_LOCK` and +`podSecurityContext.seccompProfile.type=Unconfined` are set. + +### ServiceMonitor CRD not found + +If you see: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Either install Prometheus Operator or disable ServiceMonitor: + +```bash +helm install iggy ./helm/charts/iggy --set server.serviceMonitor.enabled=false +``` + +### Server not accessible from other pods + +Ensure the server binds to `0.0.0.0` instead of `127.0.0.1`. This is configured by default via environment variables: + +* `IGGY_HTTP_ADDRESS=0.0.0.0:3000` +* `IGGY_TCP_ADDRESS=0.0.0.0:8090` +* `IGGY_QUIC_ADDRESS=0.0.0.0:8080` + +## Accessing the Server + +### Port Forward + +```bash +# HTTP API +kubectl port-forward svc/iggy 3000:3000 + +# Web UI +kubectl port-forward svc/iggy-ui 3050:3050 +``` + +### Using Ingress Enable ingress in values. Set `className` and any controller-specific annotations to match your ingress implementation: diff --git a/helm/charts/iggy/README.md.gotmpl b/helm/charts/iggy/README.md.gotmpl index becaec8723..08263efe3b 100644 --- a/helm/charts/iggy/README.md.gotmpl +++ b/helm/charts/iggy/README.md.gotmpl @@ -100,7 +100,147 @@ command line with `--set server.serviceMonitor.enabled=true`. helm uninstall iggy ``` -## Using Ingress +## Testing + +The chart CI paths are also available locally from the repository root. + +### Render Validation + +If `helm` is already installed locally: + +```bash +scripts/ci/test-helm.sh validate +``` + +If you want the pinned Linux CI tool version instead: + +```bash +scripts/ci/setup-helm-tools.sh +scripts/ci/test-helm.sh validate +``` + +This runs `helm lint --strict` plus the CI render scenarios, including: + +* default chart output +* all-features render +* legacy Kubernetes 1.18 API coverage +* server-only render +* UI-only render +* existing-secret render + +### Runtime Smoke Test + +The smoke path requires `helm`, `kind`, `kubectl`, and `curl`. + +Before running the local smoke path, keep these common gotchas in mind: + +* the Iggy server requires working `io_uring` support from the Kubernetes node/kernel/runtime +* the server also needs enough available memory and locked-memory headroom during startup +* `scripts/ci/test-helm.sh cleanup-smoke` removes the Helm release and smoke namespace, but it does not delete the reusable kind cluster created by `scripts/ci/setup-helm-smoke-cluster.sh` + +If `helm` and `kind` are already installed: + +```bash +scripts/ci/setup-helm-smoke-cluster.sh +scripts/ci/test-helm.sh smoke --cleanup +``` + +If you want the pinned Linux CI tool versions: + +```bash +scripts/ci/setup-helm-tools.sh --install-kind +scripts/ci/setup-helm-smoke-cluster.sh +scripts/ci/test-helm.sh smoke --cleanup +``` + +If a previous local smoke install failed and left resources behind, reset the smoke namespace with: + +```bash +scripts/ci/test-helm.sh cleanup-smoke +``` + +On Apple Silicon hosts, the released `apache/iggy:0.7.0` `arm64` image may still fail during the runtime smoke path in kind. If your Docker setup supports amd64 emulation well enough, you can try recreating the dedicated smoke cluster with: + +```bash +HELM_SMOKE_KIND_PLATFORM=linux/amd64 scripts/ci/setup-helm-smoke-cluster.sh +``` + +The smoke script defaults `IGGY_SYSTEM_SHARDING_CPU_ALLOCATION=1` for the server pod so the local kind path avoids the chart's `numa:auto` default and keeps the local runtime to a single shard, which has been more reliable on containerized local nodes. If you need a different local override, set `HELM_SMOKE_SERVER_CPU_ALLOCATION` before running `scripts/ci/test-helm.sh smoke`. Pass `--cleanup` to remove the smoke namespace after a successful run; omit it if you want to inspect the deployed resources. + +On smoke-test failures you can collect the same diagnostics as CI with: + +```bash +scripts/ci/test-helm.sh collect-smoke-diagnostics +``` + +> **Note:** `scripts/ci/setup-helm-tools.sh` currently supports Linux `x86_64` only. +> On other local platforms, install equivalent `helm` and `kind` binaries yourself and then use the same scripts above. +> The runtime smoke test may still fail on some local/containerized clusters if the node/kernel does not provide the `io_uring` support required by the server runtime even after the local sharding override, or if the local environment does not provide enough memory for the server to initialize cleanly. + +## Troubleshooting + +### Pod CrashLoopBackOff with "Out of memory" error + +If you see: + +```text +Cannot create runtime: Out of memory (os error 12) +``` + +This means io_uring cannot lock sufficient memory. Ensure: + +1. `securityContext.capabilities.add` includes `IPC_LOCK` +2. `podSecurityContext.seccompProfile.type` is `Unconfined` + +These server settings are set by default but may be overridden. + +### Pod CrashLoopBackOff with "Invalid argument" during server startup + +If the Iggy server exits with a panic similar to: + +```text +called `Result::unwrap()` on an `Err` value: Os { code: 22, kind: InvalidInput, message: "Invalid argument" } +``` + +the Kubernetes node may not support the `io_uring` runtime configuration required by the server. +This has been observed on local/container-based clusters even when `IPC_LOCK` and +`podSecurityContext.seccompProfile.type=Unconfined` are set. + +### ServiceMonitor CRD not found + +If you see: + +```text +no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1" +``` + +Either install Prometheus Operator or disable ServiceMonitor: + +```bash +helm install iggy ./helm/charts/iggy --set server.serviceMonitor.enabled=false +``` + +### Server not accessible from other pods + +Ensure the server binds to `0.0.0.0` instead of `127.0.0.1`. This is configured by default via environment variables: + +* `IGGY_HTTP_ADDRESS=0.0.0.0:3000` +* `IGGY_TCP_ADDRESS=0.0.0.0:8090` +* `IGGY_QUIC_ADDRESS=0.0.0.0:8080` + +## Accessing the Server + +### Port Forward + +```bash +# HTTP API +kubectl port-forward svc/iggy 3000:3000 + +# Web UI +kubectl port-forward svc/iggy-ui 3050:3050 +``` + +### Using Ingress Enable ingress in values. Set `className` and any controller-specific annotations to match your ingress implementation: diff --git a/helm/charts/iggy/templates/servicemonitor.yaml b/helm/charts/iggy/templates/servicemonitor.yaml index a3837f676f..ffff628b05 100644 --- a/helm/charts/iggy/templates/servicemonitor.yaml +++ b/helm/charts/iggy/templates/servicemonitor.yaml @@ -23,7 +23,7 @@ metadata: labels: {{- include "iggy.labels" . | nindent 4 }} {{- if .Values.server.serviceMonitor.additionalLabels }} - {{- toYaml .Values.server.serviceMonitor.additionalLabels }} + {{- toYaml .Values.server.serviceMonitor.additionalLabels | nindent 4 }} {{- end }} name: {{ template "iggy.fullname" . }} namespace: {{ .Release.Namespace }} From 05f37ac216a3b7730458c4425092b2c108253046 Mon Sep 17 00:00:00 2001 From: avirajkhare00 Date: Sat, 11 Apr 2026 14:56:38 +0530 Subject: [PATCH 11/11] ci(helm): pin yamllint to 1.38.0 in setup action and chart docs Made-with: Cursor --- .github/actions/utils/setup-helm-tools/action.yml | 2 +- helm/charts/iggy/README.md | 2 +- helm/charts/iggy/README.md.gotmpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/utils/setup-helm-tools/action.yml b/.github/actions/utils/setup-helm-tools/action.yml index 2d7564c7d9..7878dd308b 100644 --- a/.github/actions/utils/setup-helm-tools/action.yml +++ b/.github/actions/utils/setup-helm-tools/action.yml @@ -98,7 +98,7 @@ runs: - name: Install yamllint if: inputs.install-yamllint == 'true' shell: bash - run: pip install yamllint + run: pip install "yamllint==1.38.0" - name: Install helmfmt if: inputs.install-helmfmt == 'true' diff --git a/helm/charts/iggy/README.md b/helm/charts/iggy/README.md index 07958aa39f..4aba962b1b 100644 --- a/helm/charts/iggy/README.md +++ b/helm/charts/iggy/README.md @@ -272,7 +272,7 @@ This chart uses automated tools to maintain code quality: ```bash # Install tools (macOS) brew install norwoodj/tap/helm-docs -pip install yamllint +pip install "yamllint==1.38.0" go install github.com/digitalstudium/helmfmt@latest # Format templates diff --git a/helm/charts/iggy/README.md.gotmpl b/helm/charts/iggy/README.md.gotmpl index 08263efe3b..a30365fe6c 100644 --- a/helm/charts/iggy/README.md.gotmpl +++ b/helm/charts/iggy/README.md.gotmpl @@ -292,7 +292,7 @@ This chart uses automated tools to maintain code quality: ```bash # Install tools (macOS) brew install norwoodj/tap/helm-docs -pip install yamllint +pip install "yamllint==1.38.0" go install github.com/digitalstudium/helmfmt@latest # Format templates