Skip to content

feat(chart): add values.schema.json for Helm values validation - #2441

Closed
im-Toqeer-506 wants to merge 1 commit into
Project-HAMi:masterfrom
im-Toqeer-506:add-helm-values-schema
Closed

feat(chart): add values.schema.json for Helm values validation#2441
im-Toqeer-506 wants to merge 1 commit into
Project-HAMi:masterfrom
im-Toqeer-506:add-helm-values-schema

Conversation

@im-Toqeer-506

@im-Toqeer-506 im-Toqeer-506 commented Aug 7, 2026

Copy link
Copy Markdown

What this PR does

Adds charts/hami/values.schema.json — a JSON Schema (draft-07) that Helm 3.x
automatically validates the coalesced chart values against during helm lint,
helm template, and helm install/upgrade. Today the chart ships no schema, so
type errors in user-supplied values (a quoted integer, a bool where a string is
expected, a non-null value on a null-guarded field) surface only as a broken
render or a malformed generated config at install time.

Also bumps the chart version/appVersion 2.9.02.9.1 (patch: a
backward-compatible addition), keeping them equal as hack/verify-chart-version.sh
requires.

Fixes ##2419

Design

The schema is deliberately permissive. It constrains only load-bearing types,
each traced to how the templates actually consume the value:

  • String-typed booleans (scheduler.overwriteEnv, metaxsGPUTopologyAware,
    devicePlugin.disablecorelimit) — rendered as raw YAML scalars / CLI flags, so
    typed string, not boolean.
  • Null-unionsnvidiaHookPath / nvidiaDriverRoot["null","string"];
    gdrcopyEnabled / gdsEnabled / mofedEnabled["null","boolean"], matching
    the typeIs guards in daemonsetnvidia.yaml.
  • Strict integersdeviceSplitCount, preConfiguredDeviceMemory,
    scheduler.replicas, ports — quoted strings are correctly rejected.
  • Float scaling factorsdeviceMemoryScaling / deviceCoreScaling accept a
    number or a numeric string (^[0-9]+(\.[0-9]+)?$). They are Go *float64, so
    fractional values are first-class; the string branch preserves
    --set devicePlugin.deviceMemoryScaling=1.5 (Helm renders --set floats as
    strings) while still rejecting non-numeric input.
  • Open policy stringsnodeSchedulerPolicy / gpuSchedulerPolicy are not
    enum-constrained (topology-aware is valid).
  • devices.amd / devices.awsneuron carry no enabled key (their
    customresources are ranged unconditionally); other vendors keep enabled.

No additionalProperties: false and an empty top-level required, so undocumented
and forward-compatible keys and every documented install path keep working.

Testing

Validated with the CI-pinned Helm v3.7.1:

  • helm lint charts/hami → 0 failures; helm template renders all manifests.
  • Positive: fractional --set scaling (1.5/0.8/2), genuine floats via a
    values file, and every --set override used by hack/deploy-helm.sh
    (empty registries, leaderElect=false, passDeviceSpecsEnabled=false) all pass.
  • Negative: non-numeric scaling, quoted integer fields
    (deviceSplitCount, replicas) all correctly rejected.

No Go files changed; build/lint/test are unaffected.

Summary by CodeRabbit

  • New Features

    • Added schema validation for HAMi Helm chart configuration values, including image settings, custom resources, policies, and nested options.
    • Added support for nullable values and numeric strings where applicable.
  • Chores

    • Updated the Helm chart and application versions from 2.9.0 to 2.9.1.

Add JSON Schema (draft-07) to validate Helm chart values at lint/template/install time.
Constrains load-bearing types (null-or-string unions, string-typed booleans, integers,
float scaling factors) grounded in actual template usage. Permissive baseline: no
additionalProperties: false, empty required. Bumps chart version to 2.9.1.

Fixes #<issue-number>

Signed-off-by: M Toqeer Zia <muhammadtoqeerzia586694@gmail.com>
@hami-robot

hami-robot Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: im-Toqeer-506
Once this PR has been reviewed and has the lgtm label, please assign dsfans2014 for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions github-actions Bot added the kind/feature new function label Aug 7, 2026
@hami-robot hami-robot Bot added the size/L label Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The HAMi Helm chart adds a permissive values schema with typed nested settings and updates both chart and application versions from 2.9.0 to 2.9.1.

Changes

HAMi Helm chart

Layer / File(s) Summary
Helm values schema
charts/hami/values.schema.json
Adds reusable and nested validation rules for global settings, device plugins, scaling, metrics, nullable values, numeric strings, and free-form configuration fields.
Chart release metadata
charts/hami/Chart.yaml
Updates the chart version and application version to 2.9.1.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related issues

Poem

I hop through values, neat and clear,
With typed fields checked far and near.
The chart now wears a newer name,
Two point nine point one in frame.
Validation blooms—what a delight! 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding values.schema.json for Helm chart values validation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/hami/Chart.yaml`:
- Around line 20-24: Align the Chart.yaml appVersion with the released HAMi
image version used by VERSION, global.imageTag, README, and CHANGELOG; retain
v2.9.0 unless this change also introduces an available v2.9.1 release, and
ensure the corresponding imageTag default matches.

In `@charts/hami/values.schema.json`:
- Around line 227-230: Add a minimum constraint of 0 to both
devicePlugin.deviceMemoryScaling at charts/hami/values.schema.json lines 227-230
and devicePlugin.deviceCoreScaling at lines 232-235, preserving their existing
number/string types and numeric string patterns.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a8a0007-6ff8-4b2f-9929-0afbe9671bae

📥 Commits

Reviewing files that changed from the base of the PR and between c5e99b6 and fc76992.

📒 Files selected for processing (2)
  • charts/hami/Chart.yaml
  • charts/hami/values.schema.json

Comment thread charts/hami/Chart.yaml
Comment on lines 20 to +24
# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "2.9.0"
appVersion: "2.9.1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 3 'Chart\.AppVersion|appVersion|image:|repository:|tag:' charts/hami
rg -n '2\.9\.[01]' charts/hami

Repository: Project-HAMi/HAMi

Length of output: 13398


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- Chart.yaml ---'
cat -n charts/hami/Chart.yaml | sed -n '1,80p'

printf '%s\n' '--- helpers image definitions ---'
cat -n charts/hami/templates/_helpers.tpl | sed -n '1,180p'

printf '%s\n' '--- version/imageTag references in repo ---'
rg -n 'v2\.9\.[01]|2\.9\.[01]|global\.imageTag|imageTag:' .

Repository: Project-HAMi/HAMi

Length of output: 10655


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- Helm chart metadata references ---'
rg -n 'hami\.imageTagOrGlobal|hami\.image\(|Chart\.AppVersion|global\.imageTag|appVersion|v2\.9\.0|v2\.9\.1|imageTag' charts/hami hack docs CHANGELOG.md VERSION README.md

printf '%s\n' '--- Chart values defaults ---'
python3 - <<'PY'
from pathlib import Path
p=Path('charts/hami/values.yaml')
text=p.read_text()
for i,line in enumerate(text.splitlines(),1):
    if 'imageTag:' in line:
        print(f'{i}: {line}')
PY

Repository: Project-HAMi/HAMi

Length of output: 1860


Align appVersion with the released HAMi image tag.

VERSION, global.imageTag, README, and the CHANGELOG still point to HAMi v2.9.0, while appVersion is bumped to 2.9.1 without an explicit v2.9.1 default. Set appVersion/imageTag to an available HAMi release, or keep them at v2.9.0 unless this PR also introduces that release.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/hami/Chart.yaml` around lines 20 - 24, Align the Chart.yaml appVersion
with the released HAMi image version used by VERSION, global.imageTag, README,
and CHANGELOG; retain v2.9.0 unless this change also introduces an available
v2.9.1 release, and ensure the corresponding imageTag default matches.

Comment on lines +227 to +230
"deviceMemoryScaling": {
"type": ["number", "string"],
"pattern": "^[0-9]+(\\.[0-9]+)?$",
"description": "Memory over-subscription ratio, parsed as a float64 (fractional values such as 0.8 or 1.5 are valid). Accepts a number from a values file, or a numeric string because Helm renders floats passed via --set as strings; the numeric pattern still rejects non-numeric input."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== schema excerpt =="
sed -n '220,240p' charts/hami/values.schema.json

echo
echo "== schema draft/version hints =="
python3 - <<'PY'
import json
from pathlib import Path
p=Path("charts/hami/values.schema.json")
try:
    data=json.loads(p.read_text())
    print("$schema:", data.get("$schema"))
    print("additionalProperties:", data.get("additionalProperties"))
except Exception as e:
    print("error:", e)
PY

echo
echo "== relevant schema snippets using field names =="
rg -n '"deviceMemoryScaling"|"deviceCoreScaling"|minimum|pattern' charts/hami/values.schema.json

Repository: Project-HAMi/HAMi

Length of output: 1923


🌐 Web query:

JSON Schema Draft 07 validation keywords for strings pattern does not apply to non string instances additionalProperties true

💡 Result:

In JSON Schema Draft 07, the "pattern" keyword is a string validation keyword [1][2]. By definition, this keyword applies only to instances that are JSON strings [1][3]. If an instance is of a different type (such as a number, boolean, object, or array), the "pattern" keyword is ignored, and the instance is considered valid against that keyword [4][3]. This behavior is consistent with the design of JSON Schema as a constraint-driven language [4]. Validation keywords generally only perform checks if the instance matches the expected type; otherwise, they treat the instance as valid [3]. If you intend to restrict an instance to a string that must also match a specific pattern, you must explicitly use the "type" keyword in your schema [4]: { "type": "string", "pattern": "^[a-z]+$" } In this example, the "type": "string" constraint ensures that only strings are accepted, while the "pattern" constraint further restricts those strings to the specified regular expression [4][3]. If you omit the "type": "string" constraint, the "pattern" keyword will allow any non-string instance to pass validation [4][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
import json

schema = json.loads(Path("charts/hami/values.schema.json").read_text())

def path_of(name):
    p = []
    obj = schema
    for part in name.split("."):
        if isinstance(part, int):
            p.append(part); obj = obj[part]
        else:
            p.append(part); obj = obj["properties"][part]
    return p

fields = ["deviceMemoryScaling", "deviceCoreScaling"]
for name in fields:
    s = schema
    parts = name.split(".")
    for part in parts:
        s = s["properties"][part]
    print(name, "type=", s.get("type"), "pattern=", s.get("pattern"), "minimum=", "minimum" in s, "allOf=", "allOf" in s)
PY

Repository: Project-HAMi/HAMi

Length of output: 261


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import json

schema = json.loads(Path("charts/hami/values.schema.json").read_text())
found = False
def walk(obj, prefix=""):
    global found
    if isinstance(obj, dict):
        if $schema := obj.get("$schema"):
            print("$schema:", $schema)
        for k, v in obj.items():
            path = f"{prefix}.{k}" if prefix else k
            if isinstance(v, dict):
                types = v.get("type")
                patterns = v.get("pattern")
                mins = "minimum" in v
                if "deviceMemoryScaling" in k or "deviceCoreScaling" in k:
                    print("FOUND", path, "type=", types, "pattern=", patterns, "minimum_exists=", mins)
                    found = True
            walk(v, path)
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            path = f"{prefix}[{i}]"
            walk(v, path)

walk(schema)
print("seen_found_at_top_level_properties:", "deviceMemoryScaling" in schema.get("properties", {}), "deviceCoreScaling" in schema.get("properties", {}))
PY

echo
echo "== deterministic negative-number evidence using JSON-schema examples from docs =="
python3 - <<'PY'
import json
from pathlib import Path
schema = {"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"field":{"type":["number","string"],"pattern":"^[0-9]+(\\.[0-9]+)?$"}, "schema": schema}}
# Print the minimal schema shape for the fields in question with context.
PY

Repository: Project-HAMi/HAMi

Length of output: 255


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
import json

schema = json.loads(Path("charts/hami/values.schema.json").read_text())
schema_ref = schema.get("$schema")
print("$schema:", schema_ref)
print("top-level properties contain deviceMemoryScaling:", schema.get("properties", {}).get("deviceMemoryScaling", _ := _).__class__.__name__ if False else ("deviceMemoryScaling" in schema.get("properties", {})))
print("top-level properties contain deviceCoreScaling:", "deviceCoreScaling" in schema.get("properties", {}))

def walk(obj, prefix=""):
    if isinstance(obj, dict):
        for k, v in obj.items():
            path = (prefix + "." + k) if prefix else k
            if isinstance(v, dict):
                if "deviceMemoryScaling" in k or "deviceCoreScaling" in k:
                    print("FOUND", path, "type=", v.get("type"), "pattern=", v.get("pattern"), "has_minimum=", "minimum" in v)
            walk(v, path)
    elif isinstance(obj, list):
        for i, v in enumerate(obj):
            walk(v, prefix + f"[{i}]")

walk(schema)

with open("/tmp/negative_scaling_inputs.json", "w") as f:
    json.dump({
        "deviceMemoryScaling": -1.0,
        "deviceCoreScaling": -0.5,
    }, f)
PY

echo
echo "== values near these fields in repo files =="
rg -n -C 2 'deviceMemoryScaling|deviceCoreScaling' charts/hami . --glob '*.yaml' --glob '*.yml' --glob '*.json' 2>/dev/null || true

Repository: Project-HAMi/HAMi

Length of output: 5463


Apply a numeric lower bound to both scaling fields.

This schema uses Draft-07, and pattern only validates string values. With type: ["number", "string"], negative numeric values such as -1.5 pass these fields. Add "minimum": 0 to both devicePlugin.deviceMemoryScaling and devicePlugin.deviceCoreScaling.

📍 Affects 1 file
  • charts/hami/values.schema.json#L227-L230 (this comment)
  • charts/hami/values.schema.json#L232-L235
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/hami/values.schema.json` around lines 227 - 230, Add a minimum
constraint of 0 to both devicePlugin.deviceMemoryScaling at
charts/hami/values.schema.json lines 227-230 and devicePlugin.deviceCoreScaling
at lines 232-235, preserving their existing number/string types and numeric
string patterns.

@mesutoezdil

Copy link
Copy Markdown
Contributor

Pls read the rules first.
You can view the relevant rule here.
https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
"4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants