Skip to content
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/test-wandb-base.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: Test wandb-base Chart

on:
pull_request:
paths:
- charts/operator-wandb/**
- test-configs/wandb-base/**

jobs:
snapshots:
name: Snapshot testing
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Helm
uses: azure/[email protected]
with:
version: v3.17.0
- name: Helm snapshot build and test
run: |
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stakater https://stakater.github.io/stakater-charts
helm repo add prometheus https://prometheus-community.github.io/helm-charts

helm plugin install https://github.com/origranot/helm-cascade
helm plugin install https://github.com/jlandowner/helm-chartsnap
./snapshots.sh build wandb-base
./snapshots.sh run wandb-base

test:
name: Test Chart
strategy:
fail-fast: false
matrix:
k8s-version: ["v1.32.2", "v1.31.6", "v1.30.10"]
configuration:
- env-values-example
- env-precedence-container
- env-precedence-sizing
- env-precedence-chart-env
- env-precedence-chart-legacy
- env-precedence-global-env
- env-precedence-global-legacy
runs-on: ubuntu-latest
environment: Helm Charts
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Helm
uses: azure/[email protected]
with:
version: v3.17.0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Set up chart-testing
uses: helm/[email protected]
with:
version: v3.12.0

- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed --config ct.yaml)
if [[ -n "$changed" ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Determine Kind Cluster Name
id: cluster
run: |
MATRIX_STRING="${{ matrix.k8s-version }}-${{ matrix.configuration }}"

HASH=$(python3 -c "
import zlib
data = '$MATRIX_STRING'.encode('utf-8')
crc = zlib.crc32(data) & 0xffffffff
print(f'{crc:08x}')
")

export NAME="ct-${HASH}"
echo "name=${NAME}" >> "$GITHUB_OUTPUT"
echo "Matrix: $MATRIX_STRING -> Hash: $HASH -> Name: $NAME"

- name: Create kind cluster
uses: helm/[email protected]
with:
version: v0.27.0
cluster_name: ${{ steps.cluster.outputs.name }}
node_image: kindest/node:${{ matrix.k8s-version }}
if: env.ACT || steps.list-changed.outputs.changed == 'true'

- name: Apply user defined secrets
run: |
if [[ -d test-configs/additional-resources/${{matrix.configuration}} ]]; then
kubectl --context kind-${{ steps.cluster.outputs.name }} apply -f test-configs/additional-resources/${{matrix.configuration}}
echo "Applied additional resources for ${{matrix.configuration}}"
sleep 5
else
echo "No additional resources to be applied for ${{matrix.configuration}}"
fi
if: env.ACT || steps.list-changed.outputs.changed == 'true'

- name: Run chart-testing (install)
if: env.ACT || steps.list-changed.outputs.changed == 'true'
run: |
ct install --namespace default \
--charts ./charts/wandb-base \
--config ct.yaml \
--helm-extra-args '--kube-context kind-${{ steps.cluster.outputs.name }} --timeout 600s' \
--helm-extra-set-args '--values test-configs/wandb-base/${{ matrix.configuration }}.yaml'
67 changes: 66 additions & 1 deletion charts/wandb-base/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Environment variables can be defined at multiple levels, with the following prec
5. Global environment variables (`global.env`)
6. Legacy global environment variables (`global.extraEnv`)

Example:
#### Examples Of `env` at different levels

```yaml
# Global environment variables (lowest precedence)
Expand All @@ -52,6 +52,71 @@ containers:

In this example, the `LOG_LEVEL` for the `app` container would be set to `trace`.

#### Examples of different `env` values:
At any of the difference env levels shown above the following patterns are allowed.

[k8s ref envvar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#envvar-v1-core)
[k8s ref valueFrom](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.34/#envvarsource-v1-core)

Basic Key/Value
```yaml
env:
EXAMPLE: "100"
```

```yaml
env:
EXAMPLE_ALT:
value: "200"
```

Reference a configmap
```yaml
env:
EXAMPLE_FROM_CONFIGMAP:
valueFrom:
configMapKeyRef:
name: "my-configmap"
key: "configmap-key"
```

Reference a secret
```yaml
env:
EXAMPLE_FROM_SECRET:
valueFrom:
secretKeyRef:
name: "my-secret"
key: "secret-key"
```

Reference k8s data (fieldRef)
Selects a field of the pod: supports `metadata.name`, `metadata.namespace`, `metadata.labels['<KEY>']`, `metadata.annotations['<KEY>']`, `spec.nodeName`, `spec.serviceAccountName`, `status.hostIP`, `status.podIP`, `status.podIPs`
```yaml
env:
EXAMPLE_FROM_FIELD_REF:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
# practical example
DD_AGENT_HOST:
valueFrom:
fieldRef:
fieldPath: status.hostIP
```

Reference k8s data (resourceFieldRef)
Selects a resource of the container: only resources limits and requests (`limits.cpu`, `limits.memory`, `limits.ephemeral-storage`, `requests.cpu`, `requests.memory` and `requests.ephemeral-storage`) are currently supported.
```yaml
env:
EXAMPLE_FROM_RESOURCE_FIELD_REF:
valueFrom:
resourceFieldRef:
resource: limits.memory
```

#### Examples of `envFrom` to set groups of env vars at once

Additionally, environment variables can be sourced from ConfigMaps and Secrets using the `envFrom` field:

```yaml
Expand Down
77 changes: 77 additions & 0 deletions charts/wandb-base/templates/tests/test-jobs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{{- if eq .Values.kind "Job" }}
{{- range $jobName, $job := .Values.jobs }}
{{- $job := mergeOverwrite (dict "enabled" true) $job}}
{{- $fullname := include "wandb-base.fullname" $ }}
{{- if $job.enabled }}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: "{{ $fullname }}-test-job-{{ $jobName }}-sa"
labels:
{{- include "wandb-base.labels" $ | nindent 4 }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: "{{ $fullname }}-test-job-{{ $jobName }}-role"
labels:
{{- include "wandb-base.labels" $ | nindent 4 }}
rules:
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: "{{ $fullname }}-test-job-{{ $jobName }}-binding"
labels:
{{- include "wandb-base.labels" $ | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: "{{ $fullname }}-test-job-{{ $jobName }}-role"
subjects:
- kind: ServiceAccount
name: "{{ $fullname }}-test-job-{{ $jobName }}-sa"
namespace: {{ $.Release.Namespace }}
---
apiVersion: v1
kind: Pod
metadata:
name: "{{ $fullname }}-test-job-{{ $jobName }}"
labels:
{{- include "wandb-base.labels" $ | nindent 4 }}
annotations:
"helm.sh/hook": test
"helm.sh/hook-weight": "1"
spec:
serviceAccountName: "{{ $fullname }}-test-job-{{ $jobName }}-sa"
containers:
- name: job-test
image: bitnami/kubectl:latest
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid floating tag for kubectl image; pin or parameterize.

latest is non-reproducible and risky. Pin to a version (ideally matching cluster) or expose via Values.

Apply (example pin; adjust as needed):

-      image: bitnami/kubectl:latest
+      image: bitnami/kubectl:1.31.6

Or parameterize:

-      image: bitnami/kubectl:latest
+      image: {{ default "bitnami/kubectl:1.31.6" .Values.test.kubectlImage }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
image: bitnami/kubectl:latest
image: {{ default "bitnami/kubectl:1.31.6" .Values.test.kubectlImage }}
🤖 Prompt for AI Agents
In charts/wandb-base/templates/tests/test-jobs.yaml around line 19, the
container image is using the floating tag "bitnami/kubectl:latest"; change this
to a fixed version or make it configurable via values. Replace
"bitnami/kubectl:latest" with a pinned tag (e.g., "bitnami/kubectl:<version>")
or use a Helm template reference that reads from values.yaml (e.g., {{
.Values.testJob.kubectlImage }}), then add an entry in values.yaml
(testJob.kubectlImage) with the chosen pinned image so deployments become
reproducible and configurable.

command: ['/bin/sh']
args:
- -c
- |
set -e
echo "Testing job: {{ printf "%s-%s" $fullname $jobName }}"
i=0
until kubectl logs job/{{ printf "%s-%s" $fullname $jobName }}; do
i=$((i+1))
if [ "$i" -ge 60 ]; then
echo "Timed out waiting for job logs."
exit 1
fi
sleep 5
done
restartPolicy: Never
{{- end }}
{{- end }}
{{- end }}
65 changes: 44 additions & 21 deletions snapshots.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ function usage() {
cat <<EOF
A helper script for the helm-chartsnap plugin https://github.com/jlandowner/helm-chartsnap

Usage: $0 [COMMAND]
Usage: $0 [COMMAND] [optional: CHART (ex: operator-wandb)]

Commands:
build, build the operator-wandb chart
Expand All @@ -29,34 +29,57 @@ Commands:
EOF
}

function build_chart() {
local chart="$1"
echo "Building $chart"
helm cascade build "./charts/$chart"
}

function update_chart() {
local chart="$1"
local values_file="$2"
echo "updating $chart snapshots"
helm chartsnap -c "./charts/$chart" -u -f "$values_file"
}

function run_chart() {
local chart="$1"
local values_file="$2"
echo "Checking $chart snapshot tests"
helm chartsnap -c "./charts/$chart" -f "$values_file"
}

function main() {
local chart="operator-wandb"
local func="$1"
local charts=("wandb-base" "operator-wandb")
local values_dir="test-configs"

if [ $# -eq 0 ]; then
usage
exit 1
fi

local func="$1"
case "$func" in
build)
echo "Building operator-wandb"
helm cascade build "./charts/$chart"
;;
update)
echo "Updating operator-wandb snapshots"
helm chartsnap -c "./charts/$chart" -u -f "./$values_dir/$chart"
;;
run)
echo "Checking snapshot tests"
helm chartsnap -c "./charts/$chart" -f "./$values_dir/$chart"
;;
*)
usage
exit 1
;;
esac
if [ -n "$2" ]; then
charts=("$2")
fi

Comment on lines +53 to +65
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix set -u unbound args ($1/$2) in main.

Referencing $1/$2 before validating args breaks under set -u.

Apply:

-function main() {
-  local func="$1"
-  local charts=("wandb-base" "operator-wandb")
-  local values_dir="test-configs"
+function main() {
+  # Ensure at least one argument before referencing $1 under set -u
+  if [ "$#" -lt 1 ]; then
+    usage
+    exit 1
+  fi
+  local func="$1"
+  shift
+  local charts=("wandb-base" "operator-wandb")
+  local values_dir="test-configs"
@@
-  if [ -n "$2"  ]; then
-    charts=("$2")
-  fi
+  if [ "$#" -ge 1 ]; then
+    charts=("$1")
+  fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
local func="$1"
local charts=("wandb-base" "operator-wandb")
local values_dir="test-configs"
if [ $# -eq 0 ]; then
usage
exit 1
fi
local func="$1"
case "$func" in
build)
echo "Building operator-wandb"
helm cascade build "./charts/$chart"
;;
update)
echo "Updating operator-wandb snapshots"
helm chartsnap -c "./charts/$chart" -u -f "./$values_dir/$chart"
;;
run)
echo "Checking snapshot tests"
helm chartsnap -c "./charts/$chart" -f "./$values_dir/$chart"
;;
*)
usage
exit 1
;;
esac
if [ -n "$2" ]; then
charts=("$2")
fi
function main() {
# Ensure at least one argument before referencing $1 under set -u
if [ "$#" -lt 1 ]; then
usage
exit 1
fi
local func="$1"
shift
local charts=("wandb-base" "operator-wandb")
local values_dir="test-configs"
if [ "$#" -ge 1 ]; then
charts=("$1")
fi
🤖 Prompt for AI Agents
In snapshots.sh around lines 53 to 65, the script assigns local func="$1" and
later checks $# which causes unbound variable errors when run with set -u; move
any direct references to positional parameters until after you validate
arguments (e.g., perform the if [ $# -eq 0 ] check and exit before assigning
local func and reading $2), or use safe parameter expansion like "${1:-}" and
"${2:-}" when you must reference them earlier; update the code so no plain $1/$2
is referenced before argument validation to avoid set -u failures.

for chart in "${charts[@]}"; do
case "$func" in
build)
build_chart "$chart"
;;
update)
update_chart "$chart" "./$values_dir/$chart"
;;
run)
run_chart "$chart" "./$values_dir/$chart"
;;
*)
usage
exit 1
;;
esac
done
}

main "$@"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
configmap-key: "test"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v1
kind: Secret
metadata:
name: my-secret
stringData:
secret-key: "test"
4 changes: 4 additions & 0 deletions test-configs/wandb-base/.chartsnap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
dynamicFields:
- jsonPath:
- /metadata/labels/helm.sh~1chart
value: '###CHART_VERSION###'
Loading
Loading