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
33 changes: 33 additions & 0 deletions .github/workflows/helm-fmt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: helm-fmt

on:
pull_request:
paths:
- "charts/**"
- "Makefile"
- ".github/workflows/helm-fmt.yaml"
push:
branches: [ main ]
paths:
- "charts/**"
- "Makefile"
- ".github/workflows/helm-fmt.yaml"

jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: "1.24"

- name: Install yamlfmt
run: |
go install github.com/google/yamlfmt/cmd/yamlfmt@latest
echo "$HOME/go/bin" >> $GITHUB_PATH

- name: Format check
run: make fmt-check
28 changes: 28 additions & 0 deletions .github/workflows/helm-lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: helm-lint

on:
pull_request:
paths:
- "charts/**"
- "Makefile"
- ".github/workflows/helm-lint.yaml"
push:
branches: [ main ]
paths:
- "charts/**"
- "Makefile"
- ".github/workflows/helm-lint.yaml"

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Helm
uses: azure/setup-helm@v4.3.0
with:
version: v3.19.3

- name: Helm lint
run: make lint
26 changes: 26 additions & 0 deletions .github/workflows/helm-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: helm-tests

on:
pull_request:
push:
branches: [ main ]

jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Helm
uses: azure/setup-helm@v4.3.0
with:
version: v3.19.3

- name: Build dependencies
run: helm dependency build charts/gvm-lite-stack

- name: Install helm-unittest
run: helm plugin install https://github.com/helm-unittest/helm-unittest

- name: Unit tests
run: make test
9 changes: 9 additions & 0 deletions .yamllint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
extends: default
rules:
line-length: disable
truthy: disable
comments-indentation: disable
ignore: |
charts/**/charts/
**/*.tgz
**/Chart.lock
37 changes: 37 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
CHART_DIR := charts/gvm-lite-stack

.PHONY: fmt fmt-check lint test render validate check cover

fmt:
@command -v yamlfmt >/dev/null 2>&1 || (echo "yamlfmt not installed" && exit 1)
yamlfmt -match_type doublestar \
"charts/**/Chart.yaml" \
"charts/**/values.yaml" \
"charts/**/values-*.yaml" \
"charts/**/tests/**/*.y*ml"

fmt-check:
@command -v yamlfmt >/dev/null 2>&1 || (echo "yamlfmt not installed" && exit 1)
yamlfmt -lint -match_type doublestar \
"charts/**/Chart.yaml" \
"charts/**/values.yaml" \
"charts/**/values-*.yaml" \
"charts/**/tests/**/*.y*ml"

lint:
helm lint $(CHART_DIR)

test:
helm unittest $(CHART_DIR)

render:
helm template $(CHART_DIR) > /tmp/gvm-lite-stack.rendered.yaml

validate:
@command -v kubeconform >/dev/null 2>&1 || (echo "kubeconform not installed" && exit 1)
helm template $(CHART_DIR) | kubeconform -strict -ignore-missing-schemas

check: fmt-check lint test validate

cover:
./scripts/helm_test_coverage.sh $(CHART_DIR)
60 changes: 57 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,63 @@ Helm chart that deploys a lightweight Greenbone stack on Kubernetes:

## Prerequisites

* Helm ≥ 3.10
* `kubectl` pointing at your cluster (e.g. Minikube)
* Docker (only required for building local images)
### Required
- **Helm** (v3.x)
- Verify: `helm version`
- **helm-unittest** plugin (for unit tests)
- Install: `helm plugin install https://github.com/helm-unittest/helm-unittest`
- Verify: `helm plugin list | grep unittest`

### Recommended
- **kubeconform** (validates rendered manifests against Kubernetes schemas)
- macOS (Homebrew): `brew install kubeconform`
- Linux: install from GitHub releases (see CI workflow or project docs)
- Verify: `kubeconform -v`
- **yamlfmt** (formats / checks YAML style)
- Install (Go): `go install github.com/google/yamlfmt/cmd/yamlfmt@latest`
- Ensure it’s on PATH: `export PATH="$PATH:$HOME/go/bin"`
- Verify: `yamlfmt -version` (or `yamlfmt --version`)

> Note: Helm templates under `charts/**/templates/` are **not valid YAML** until rendered, so formatting is applied only to `Chart.yaml`, `values*.yaml`, and `tests/**/*.yaml`.

---

## Development Commands (Makefile)

This repository uses a Makefile to keep common actions consistent locally and in CI.

> Chart location: `charts/gvm-lite-stack`

### Format (non-template YAML only)
- Format files in-place:
- `make fmt`
- Check formatting (CI-style; fails if formatting would change):
- `make fmt-check`

### Lint
- Run Helm lint:
- `make lint`

### Unit tests
- Run Helm unit tests:
- `make test`

### Render manifests
- Render the chart to a local file:
- `make render`
- Output: `/tmp/gvm-lite-stack.rendered.yaml`

### Schema validation (rendered output)
- Validate rendered manifests with kubeconform:
- `make validate`

### Coverage gate (Helm template coverage)
- Ensure every template has at least one unit test referencing it:
- `make coverage`

### Full local check (recommended before pushing)
- Run everything CI expects:
- `make check`

---

Expand Down
6 changes: 1 addition & 5 deletions charts/gvm-lite-stack/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
apiVersion: v2
name: gvm-lite-stack
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
Expand All @@ -11,20 +10,17 @@ description: A Helm chart for Kubernetes
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# 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: "1.16.0"

dependencies:
- name: postgresql
version: 16.3.0
repository: oci://registry-1.docker.io/bitnamicharts
condition: postgresql.enabled
condition: postgresql.enabled
95 changes: 95 additions & 0 deletions charts/gvm-lite-stack/tests/feed-deploy_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
suite: feed-service deployment
templates:
- templates/feed-deploy.yaml
tests:
- it: renders a Deployment named feed-service
asserts:
- isKind:
of: Deployment
- equal:
path: metadata.name
value: feed-service
- it: uses app=feed-service for selector and pod labels
asserts:
- equal:
path: spec.selector.matchLabels.app
value: feed-service
- equal:
path: spec.template.metadata.labels.app
value: feed-service
- it: sets securityContext defaults (fsGroup and fsGroupChangePolicy)
asserts:
- equal:
path: spec.template.spec.securityContext.fsGroup
value: 1000
- equal:
path: spec.template.spec.securityContext.fsGroupChangePolicy
value: OnRootMismatch
- it: includes initContainer prep-volumes with default image and root user
asserts:
- equal:
path: spec.template.spec.initContainers[0].name
value: prep-volumes
- equal:
path: spec.template.spec.initContainers[0].securityContext.runAsUser
value: 0
- equal:
path: spec.template.spec.initContainers[0].image
value: "busybox:1.36"
- it: includes main container feed with readiness and liveness probes
asserts:
- equal:
path: spec.template.spec.containers[0].name
value: feed
- exists:
path: spec.template.spec.containers[0].readinessProbe.exec.command
- exists:
path: spec.template.spec.containers[0].livenessProbe.exec.command
- it: mounts expected volumes in the main container
asserts:
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: plugins
mountPath: /var/lib/openvas/plugins
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: notus
mountPath: /var/lib/notus
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: logs
mountPath: /var/log/feedsync
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: report-formats
mountPath: /var/lib/gvm
- it: defines PVC-backed volumes with claimNames
asserts:
- contains:
path: spec.template.spec.volumes
content:
name: plugins
persistentVolumeClaim:
claimName: gvm-plugins-pvc
- contains:
path: spec.template.spec.volumes
content:
name: notus
persistentVolumeClaim:
claimName: gvm-notus-pvc
- contains:
path: spec.template.spec.volumes
content:
name: logs
persistentVolumeClaim:
claimName: gvm-log-pvc
- contains:
path: spec.template.spec.volumes
content:
name: report-formats
persistentVolumeClaim:
claimName: gvm-report-formats-pvc
48 changes: 48 additions & 0 deletions charts/gvm-lite-stack/tests/gsa-lite-configmap_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
suite: gsa-lite configmap
templates:
- templates/gsa-lite-configmap.yaml
tests:
- it: renders ConfigMap with the correct name
asserts:
- isKind:
of: ConfigMap
- equal:
path: metadata.name
value: gsa-lite-config
- it: sets defaults when values are empty
set:
gsaLite:
config:
backendOrigin: ""
backendHost: ""
authBasePath: ""
apiBasePath: ""
defaultLanguage: ""
supportedLanguages: null
tokenKey: ""
refreshTokenKey: ""
asserts:
- equal:
path: data.BACKEND_ORIGIN
value: ""
- equal:
path: data.BACKEND_HOST
value: ""
- equal:
path: data.AUTH_BASE_PATH
value: "/auth"
- equal:
path: data.API_BASE_PATH
value: "/api/v1"
- equal:
path: data.DEFAULT_LANGUAGE
value: "en"
- equal:
path: data.SUPPORTED_LANGUAGES
value: "[\"en\",\"de\"]"
- equal:
path: data.TOKEN_STORAGE_KEY
value: "gsa-lite-access-token"
- equal:
path: data.REFRESH_TOKEN_STORAGE_KEY
value: "gsa-lite-refresh-token"
Loading
Loading