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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,6 @@ jobs:

- name: Local mock worker smoke test
run: scripts/smoke-local.sh

- name: Chart contract tests
run: scripts/chart-contract-tests.sh
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: lint template template-local smoke-local
.PHONY: lint template template-local smoke-local test

lint:
helm lint charts/render-worker
Expand All @@ -11,3 +11,6 @@ template-local:

smoke-local:
scripts/smoke-local.sh

test:
scripts/chart-contract-tests.sh
38 changes: 38 additions & 0 deletions charts/render-worker/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@
}
}
}
},
"trigger": {
"type": "object",
"properties": {
"type": {
"type": "string",
"minLength": 1
},
"queueURLFromEnv": {
"type": "string",
"minLength": 1
},
"awsRegion": {
"type": "string",
"minLength": 1
}
}
}
}
},
Expand All @@ -105,6 +122,27 @@
"enabled": {
"type": "boolean"
},
"nameSuffix": {
"type": "string",
"minLength": 1
},
"image": {
"type": "object",
"properties": {
"repository": {
"type": "string",
"minLength": 1
},
"tag": {
"type": "string",
"minLength": 1
},
"pullPolicy": {
"type": "string",
"enum": ["Always", "IfNotPresent", "Never"]
}
}
},
"ttlSecondsAfterFinished": {
"type": "integer",
"minimum": 0
Expand Down
21 changes: 21 additions & 0 deletions docs/delivery-prompts.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,27 @@ Evidence update:
- Update docs/evidence-map.md for schema validation and CI hardening.
```

## Node: Chart Tests and Schema

```text
Repository: RayLi-Muye/renderfarm-k8s-toolkit
Issue: #3 Add chart unit tests and stronger values schema

This node has been implemented with local chart contract tests and additional values schema coverage. Continue only if the project needs a dedicated Helm test framework or deeper negative schema coverage.

Implemented files:
- scripts/chart-contract-tests.sh
- charts/render-worker/values.schema.json
- .github/workflows/ci.yml
- Makefile
- docs/development.md
- docs/evidence-map.md

Validation:
- `make test` checks GPU enabled/disabled rendering, KEDA enabled/disabled rendering, and schema rejection for invalid replica counts, GPU counts, and image pull policies.
- CI runs the chart contract tests on pull requests and main pushes.
```

## Node: Mock Render Worker

```text
Expand Down
3 changes: 3 additions & 0 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ make lint
make template
make template-local
make smoke-local
make test
```

`scripts/render-examples.sh` also validates rendered manifests with kubeconform when it is installed locally. CI installs Helm and kubeconform with pinned versions and SHA256 checksums, then validates built-in Kubernetes resources and KEDA CRDs through a pinned CRD schema catalog.

`make smoke-local` runs the public mock worker path from `workers/mock-render-worker/mock-render-worker.sh`. It consumes `examples/mock-queue.txt`, writes placeholder frame output, and creates a postprocess manifest without AWS credentials, a real renderer, or a Kubernetes cluster.

`make test` runs local chart contract tests for GPU enabled/disabled rendering, KEDA enabled/disabled rendering, and schema rejection for common invalid values.

## Branching

Use short feature branches:
Expand Down
3 changes: 2 additions & 1 deletion docs/evidence-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ This file maps resume claims to public repository evidence.
| Config and secret management | `charts/render-worker/templates/configmap.yaml`, `charts/render-worker/templates/secret.yaml` | Render values with string-like and numeric values; output remains string typed | Implemented | Secrets are injection points, not a production secret manager |
| Post-render batch processing | `charts/render-worker/templates/postprocess-job.yaml` | Render local or AWS examples and inspect the `Job` | Implemented | Upgrade semantics need hardening before production use |
| Public mock worker smoke path | `workers/mock-render-worker/mock-render-worker.sh`, `scripts/smoke-local.sh`, `examples/mock-queue.txt` | Run `make smoke-local` and inspect placeholder frame output plus the postprocess manifest | Implemented | Mock path validates the public worker contract only; it is not a real renderer, queue service, object store, or cluster test |
| CI/CD discipline | `.github/workflows/ci.yml` | Review GitHub Actions runs; CI executes Helm lint, template rendering, and kubeconform validation | Implemented | Static schema validation only; no live cluster, admission webhook, KEDA operator, AWS SQS, or GPU node behavior is exercised |
| Chart contract tests and values schema | `scripts/chart-contract-tests.sh`, `charts/render-worker/values.schema.json` | Run `make test`; CI also runs these tests on PRs and `main` pushes | Implemented | Contract tests inspect rendered manifests and schema failures only; no live Kubernetes, KEDA operator, AWS SQS, or GPU node behavior is exercised |
| CI/CD discipline | `.github/workflows/ci.yml` | Review GitHub Actions runs; CI executes Helm lint, template rendering, kubeconform validation, mock smoke, and chart contract tests | Implemented | Static and local validation only; no live cluster, admission webhook, KEDA operator, AWS SQS, or GPU node behavior is exercised |
| Tool install integrity | `.github/workflows/ci.yml` | Inspect CI install steps for Helm and kubeconform checksum verification | Implemented | Checksums verify downloaded release assets, not upstream maintainer identity |
| Engineering workflow | `.github/ISSUE_TEMPLATE/*`, `.github/pull_request_template.md`, `docs/roadmap.md` | Review merged PRs and open delivery issues | Active | Solo project, but PR discipline is preserved |

Expand Down
99 changes: 99 additions & 0 deletions scripts/chart-contract-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CHART_DIR="${ROOT_DIR}/charts/render-worker"
TMP_DIR="$(mktemp -d)"
HELM="${HELM:-helm}"
trap 'rm -rf "${TMP_DIR}"' EXIT

render_chart() {
local output_file="$1"
shift
"${HELM}" template render-worker "${CHART_DIR}" "$@" >"${output_file}"
}

assert_contains() {
local file="$1"
local pattern="$2"
local message="$3"

if ! grep -Fq "${pattern}" "${file}"; then
echo "missing expected output: ${message}" >&2
echo "pattern: ${pattern}" >&2
exit 1
fi
}

assert_not_contains() {
local file="$1"
local pattern="$2"
local message="$3"

if grep -Fq "${pattern}" "${file}"; then
echo "unexpected output: ${message}" >&2
echo "pattern: ${pattern}" >&2
exit 1
fi
}

expect_lint_failure() {
local name="$1"
local values_file="$2"
local log_file="${TMP_DIR}/${name}.log"

if "${HELM}" lint "${CHART_DIR}" -f "${values_file}" >"${log_file}" 2>&1; then
echo "expected Helm lint to fail for ${name}" >&2
cat "${log_file}" >&2
exit 1
fi
}

default_manifest="${TMP_DIR}/default.yaml"
local_manifest="${TMP_DIR}/local.yaml"
aws_manifest="${TMP_DIR}/aws-gpu-sqs.yaml"

render_chart "${default_manifest}"
assert_contains "${default_manifest}" "kind: Deployment" "default chart renders a worker Deployment"
assert_contains "${default_manifest}" "replicas: 0" "default chart keeps workers scaled to zero without KEDA"
assert_not_contains "${default_manifest}" "kind: ScaledObject" "default chart does not render KEDA"
assert_not_contains "${default_manifest}" "nvidia.com/gpu" "default chart does not request GPU resources"

render_chart "${local_manifest}" -f "${ROOT_DIR}/examples/values-local.yaml"
assert_contains "${local_manifest}" "replicas: 1" "local example renders one worker replica"
assert_not_contains "${local_manifest}" "kind: ScaledObject" "local example does not render KEDA"
assert_not_contains "${local_manifest}" "nvidia.com/gpu" "local example does not request GPU resources"

render_chart "${aws_manifest}" -f "${ROOT_DIR}/examples/values-aws-gpu-sqs.yaml"
assert_contains "${aws_manifest}" "kind: ScaledObject" "AWS example renders KEDA ScaledObject"
assert_contains "${aws_manifest}" "kind: TriggerAuthentication" "AWS example renders KEDA TriggerAuthentication"
assert_contains "${aws_manifest}" "nvidia.com/gpu: \"1\"" "AWS example requests one GPU"
assert_not_contains "${aws_manifest}" "replicas:" "AWS KEDA example leaves replica count to autoscaling"

cat >"${TMP_DIR}/invalid-replica.yaml" <<'YAML'
replicaCount: -1
YAML
expect_lint_failure "invalid-replica" "${TMP_DIR}/invalid-replica.yaml"

cat >"${TMP_DIR}/invalid-gpu-count.yaml" <<'YAML'
gpu:
enabled: true
count: 0
YAML
expect_lint_failure "invalid-gpu-count" "${TMP_DIR}/invalid-gpu-count.yaml"

cat >"${TMP_DIR}/invalid-image-pull-policy.yaml" <<'YAML'
image:
pullPolicy: Sometimes
YAML
expect_lint_failure "invalid-image-pull-policy" "${TMP_DIR}/invalid-image-pull-policy.yaml"

cat >"${TMP_DIR}/invalid-postprocess-pull-policy.yaml" <<'YAML'
postprocessJob:
enabled: true
image:
pullPolicy: Sometimes
YAML
expect_lint_failure "invalid-postprocess-pull-policy" "${TMP_DIR}/invalid-postprocess-pull-policy.yaml"

echo "Chart contract tests passed"