Collection of common sub charts to bootstrap common applications
- Helm 4.2
- Node.js and
jq, only formake schemas
Chart versions are managed by release-please and must not be edited by hand. See CONTRIBUTING.md for the day-to-day workflow and docs/release-pipeline.md for how releases are produced.
- Choose the chart you wish to update, for example
common. Leave its version alone. - In the sre repo cd into the directory of the chart you wish to test. For example
notification-service - With your current directory of charts/notification-service/production update the Chart.yaml file to point to the local file system path. Use the chart's current version. Below shows an example
sre/charts/notification-service/production/Chart.yaml
apiVersion: v2
name: notification-service
version: 1.0.0
dependencies:
- name: common
version: 0.11.0 #<-- example only, copy the current value from charts/common/Chart.yaml
repository: "file://../charts/charts/common" #<--Note!
alias: notification-service
...
- Run
helm dependency update. This will copy over the chart into this repo. Make you you don't commit it. - Run
helm template .. This will render out the Kubernetes manifest objects with the variables replaced to thestdout. The output should be a valid yaml file that could be directly applied in a GKE cluster. If there are errors the templating engine will write it to thestderr
We use helm-unittest, a helm plugin that renders a chart's templates for a given set of values and asserts on the rendered output (e.g. a field's value, whether a key exists). No cluster is needed — it's checking what helm template would produce, not whether a live cluster accepts it.
Install the plugin once locally:
helm plugin install https://github.com/helm-unittest/helm-unittest --version v1.1.2Run every chart's tests from the repo root:
make testThis finds every chart with a tests/ directory (e.g. charts/common/tests) and runs helm unittest against it, so it picks up new charts automatically as they gain coverage. To run a single chart's tests directly:
cd charts/common
helm unittest .The Helm Unit Tests GitHub Actions workflow (.github/workflows/unit-test.yml) runs the same thing on every PR.
Tests live under charts/$chart_name/tests/, one suite file per template, named <template-basename>_test.yaml (e.g. charts/common/tests/pdb_test.yaml tests templates/pdb.yaml). A suite can have multiple it: cases, each setting different values and asserting on the result:
suite: PodDisruptionBudget
templates:
- pdb.yaml
values:
- ./fixtures/minimal-values.yaml
set:
podDisruptionBudget:
enabled: true
tests:
- it: defaults minAvailable to 15% when neither minAvailable nor maxUnavailable is set
asserts:
- isKind:
of: PodDisruptionBudget
- equal:
path: spec.minAvailable
value: "15%"If a template needs values that are required elsewhere in the chart (e.g. common.name) just to render at all, add them to the shared charts/$chart_name/tests/fixtures/minimal-values.yaml and load it via values: rather than repeating set: boilerplate in every suite.
Good candidates for a new test are anything that's easy to get subtly wrong without helm lint/helm template catching it — a .enabled toggle that's gated in some templates but not others, a label selector, a name derived from a helper. See the helm-unittest docs for the full list of available assertions.
Important
values.schema.json is generated but committed. On a branch in this
repository, a PR touching a chart's schemas/ directory gets the rebuilt file
committed automatically. Fork PRs cannot receive that push: run make schemas
and commit the result. Run it locally anyway if you want it sooner.
We use JSON schema to validate our custom charts. To enable that feature a values.schema.json file at the root directory for a given chart must be present. e.g. charts/common/values.schema.json.
Both helm template, helm lint are JSON schema aware. helm template in specific is what ArgoCD uses to render the kubernetes manifests.
For our use case, we have decided to have a means to bundle together the schema files that can be found under the root directory for any given chart (e.g. charts/common/schemas) into a resulting values.schema.json file. This file gets created by json-schema-bundler via make schemas. The main entrypoint for the schemas is charts/$chart_name/schemas/schema.yaml. That file should include references to other subschemas so we can leverage modularization.
The reason we don't use plain $refs pointing to a file path is because resolving those references becomes difficult since we have to account for absolute paths, relative paths, and helm being able to resolve them under all circumstances. The bundler takes care of that for us.
json-schema-bundler also has the benefit of allowing us to use yaml files as schemas improving readability. The bundler will convert them to json before rendering the final values.schema.json file.
If you want to introduce a new schema or update an existing one, you can do so by creating a new yaml file under charts/common/schemas and then referencing it in charts/common/schemas/schema.yaml. The bundler will take care of the rest.
Regenerate and lint locally. make schemas shells out to npx and jq, so it
needs Node.js installed:
make schemas
cd ${charts_repo}/charts/common
helm lint .That should be enough to get you started with JSON schema validations.
values.schema.json is generated, but it is committed, because Helm reads it at
install time. CI keeps it in sync for you, so the usual reason to run make schemas yourself is to lint locally before pushing.
Package the chart locally and consume it over file://. See
CONTRIBUTING.md. Nothing needs
to be published to test a branch.
- Merge your PR to master with a
feat:orfix:title. - release-please opens a PR titled
chore(master): releasecontaining the version bump and changelog. Get approvals from #sre-support on that PR. - Merge the release PR. release-please tags and creates the GitHub Release with
the changelog as its notes. The publish job pushes the chart to
oci://us-docker.pkg.dev/artifact-storage-5748/helm-charts. New versions are not written to GitHub Pages.