From 31bbf1ca94a3e030529c97c08bf68d69ab6f8d4f Mon Sep 17 00:00:00 2001
From: Romain Pluciennik
Date: Fri, 16 Aug 2024 01:09:32 +0200
Subject: [PATCH] feat(charts): Now using bjw-s's common library chart (#7)
---
.github/CODEOWNERS | 1 +
.github/renovate.json5 | 15 --
.github/workflows/renovate.yaml | 115 ++++++++++
.gitignore | 6 +-
README.md | 26 +--
charts/it-tools/Chart.lock | 6 +
charts/it-tools/Chart.yaml | 8 +-
charts/it-tools/README.md | 131 +++++------
charts/it-tools/README_CONFIG.md.gotmpl | 13 ++
charts/it-tools/templates/_helpers.tpl | 62 ------
charts/it-tools/templates/common.yaml | 93 ++++++++
charts/it-tools/templates/configmap.yaml | 29 ---
charts/it-tools/templates/deployment.yaml | 82 -------
charts/it-tools/templates/hpa.yaml | 32 ---
charts/it-tools/templates/ingress.yaml | 61 ------
charts/it-tools/templates/service.yaml | 15 --
charts/it-tools/templates/serviceaccount.yaml | 13 --
.../templates/tests/test-connection.yaml | 15 --
charts/it-tools/values.yaml | 205 ++++++++----------
hack/gen-chart-summary.sh | 39 ++++
hack/gen-helm-docs.sh | 59 +++++
hack/templates/README.md.gotmpl | 170 +++++++++++++++
hack/templates/README_CONFIG.md.gotmpl | 13 ++
hack/templates/icon.gotmpl | 5 +
hack/update-changelog.sh | 56 +++++
hack/update-version.sh | 53 +++++
26 files changed, 787 insertions(+), 536 deletions(-)
create mode 100644 .github/CODEOWNERS
create mode 100644 .github/workflows/renovate.yaml
create mode 100644 charts/it-tools/Chart.lock
create mode 100644 charts/it-tools/README_CONFIG.md.gotmpl
delete mode 100644 charts/it-tools/templates/_helpers.tpl
create mode 100644 charts/it-tools/templates/common.yaml
delete mode 100644 charts/it-tools/templates/configmap.yaml
delete mode 100644 charts/it-tools/templates/deployment.yaml
delete mode 100644 charts/it-tools/templates/hpa.yaml
delete mode 100644 charts/it-tools/templates/ingress.yaml
delete mode 100644 charts/it-tools/templates/service.yaml
delete mode 100644 charts/it-tools/templates/serviceaccount.yaml
delete mode 100644 charts/it-tools/templates/tests/test-connection.yaml
create mode 100755 hack/gen-chart-summary.sh
create mode 100755 hack/gen-helm-docs.sh
create mode 100644 hack/templates/README.md.gotmpl
create mode 100644 hack/templates/README_CONFIG.md.gotmpl
create mode 100644 hack/templates/icon.gotmpl
create mode 100755 hack/update-changelog.sh
create mode 100755 hack/update-version.sh
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..572afb1
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+* @plcnk
diff --git a/.github/renovate.json5 b/.github/renovate.json5
index d613436..cd02ddf 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -16,21 +16,6 @@
{
"matchDatasources": ["helm"],
"commitMessageTopic": "{{depName}} Helm release"
- },
- {
- "matchDatasources": ["docker"],
- "matchPackageNames": ["ghcr.io/dgtlmoon/changedetection.io"],
- "versioning": "loose"
- },
- {
- "matchDatasources": ["docker"],
- "matchPackageNames": ["ghcr.io/juanfont/headscale"],
- "allowedVersions": "!/^0.23.0$/"
- },
- {
- "matchDatasources": ["docker"],
- "matchPackageNames": ["eqalpha/keydb"],
- "versioning": "regex:^(?.+?)_v(?\\d+)\\.(?\\d+)\\.(?\\d+)$"
}
]
}
diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml
new file mode 100644
index 0000000..a7c6e5c
--- /dev/null
+++ b/.github/workflows/renovate.yaml
@@ -0,0 +1,115 @@
+name: Renovate
+
+on:
+ push:
+ branches:
+ - renovate/**
+
+env:
+ COMMIT_MESSAGE: "chore: Update chart metadata"
+
+jobs:
+ update-chart-metadata:
+ name: Update Chart Metadata
+ runs-on: ubuntu-latest
+ env:
+ AUTHOR_USER: chart-bot
+ AUTHOR_EMAIL: 160046936+charts-bot[bot]@users.noreply.github.com
+ steps:
+ - name: Generate Token
+ id: app-token
+ uses: actions/create-github-app-token@v1
+ with:
+ app-id: ${{ secrets.BOT_APP_ID }}
+ private-key: ${{ secrets.BOT_APP_PRIVATE_KEY }}
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ token: ${{ steps.app-token.outputs.token }}
+ fetch-depth: 0
+
+ - name: Detect Changes
+ uses: dorny/paths-filter@v3
+ id: changes
+ with:
+ list-files: shell
+ filters: |
+ charts:
+ - charts/**
+
+ - name: Fetch PR
+ id: pr
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ steps.app-token.outputs.token }}
+ script: |
+ const response = await github.rest.repos.listPullRequestsAssociatedWithCommit({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ commit_sha: context.sha,
+ });
+ const pr = response.data.shift();
+ core.setOutput("title", pr.title);
+ core.setOutput("base_ref", pr.base.ref);
+ core.setOutput("labels", pr.labels.map((e) => e.name).filter((e) => e));
+
+ - name: Update changelog
+ env:
+ TITLE: ${{ steps.pr.outputs.title }}
+ CHANGELOG_APPEND: ${{ contains(steps.pr.outputs.labels, 'changelog-append') }}
+ BREAKING_CHANGE: ${{ contains(steps.pr.outputs.labels, 'breaking-change') }}
+ run: |
+ set -eux
+ export DESCRIPTION="$(perl -pe 's/^.+?: (.)/\U$1/' <<<"$TITLE")"
+ if [[ "$BREAKING_CHANGE" == "true" ]]; then
+ DESCRIPTION="BREAKING - $DESCRIPTION"
+ fi
+ CHANGELOG="$(yq -o json '[{"kind": "changed", "description": strenv(DESCRIPTION)}]')"
+ UPDATE_TYPE=replace
+ if [[ "$CHANGELOG_APPEND" == "true" ]]; then
+ UPDATE_TYPE=append
+ fi
+ ./hack/update-changelog.sh "$UPDATE_TYPE" "$CHANGELOG" ${{ steps.changes.outputs.charts_files }}
+
+ - name: Set type to patch
+ if: contains(steps.pr.outputs.labels, 'patch') || contains(steps.pr.outputs.labels, 'digest')
+ run: echo TYPE=patch >>$GITHUB_ENV
+ - name: Set type to minor
+ if: contains(steps.pr.outputs.labels, 'major') || contains(steps.pr.outputs.labels, 'minor')
+ run: echo TYPE=minor >>$GITHUB_ENV
+ - name: Update chart version
+ if: "!contains(steps.pr.outputs.labels, 'skip-version-bump')"
+ run: |
+ set -eux
+ ./hack/update-version.sh "$TYPE" ${{ steps.changes.outputs.charts_files }}
+
+ - name: Install helm-docs
+ uses: gabe565/setup-helm-docs-action@v1
+ - name: Generate Helm docs
+ run: |
+ set -eu
+ ./hack/gen-helm-docs.sh
+
+ - name: Check if commit exists
+ id: commit_exists
+ env:
+ BASE_REF: ${{ steps.pr.outputs.base_ref }}
+ run: |
+ set -eu
+ IFS=$'\n\t'
+ commits="$(git rev-list --pretty=oneline "origin/$BASE_REF..HEAD" | cut -d' ' -f2-)"
+ if grep -F -e "$COMMIT_MESSAGE" <<<"$commits"; then
+ echo 'result=true' >>$GITHUB_OUTPUT
+ else
+ echo 'result=false' >>$GITHUB_OUTPUT
+ fi
+
+ - name: Commit chart version
+ uses: stefanzweifel/git-auto-commit-action@v5
+ if: steps.commit_exists.outputs.result == 'false' && !contains(steps.pr.outputs.labels, 'skip-chart-meta')
+ with:
+ commit_user_name: ${{ env.AUTHOR_USER }}
+ commit_user_email: ${{ env.AUTHOR_EMAIL }}
+ commit_author: ${{ env.AUTHOR_USER }} <${{ env.AUTHOR_EMAIL }}>
+ commit_message: ${{ env.COMMIT_MESSAGE }}
diff --git a/.gitignore b/.gitignore
index 51dfa0d..61de801 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,5 @@
-test_values/
\ No newline at end of file
+# Test values
+test_values/
+
+# Helm resources
+charts/**/charts
diff --git a/README.md b/README.md
index b0a2b30..ed95581 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-
+
@@ -12,28 +12,18 @@
A collection of [Helm](https://helm.sh) charts for [Kubernetes](https://kubernetes.io/).
+All charts are based on the [bjw-s common library chart](https://github.com/bjw-s/helm-charts/tree/main/charts/library/common).
+
+Also available on [Artifact Hub](https://artifacthub.io/packages/search?repo=plcnk).
+
The code in this repository is provided as-is with no warranties.
-## Usage
-
-[Helm](https://helm.sh) must be installed to use the charts.
-Please refer to Helm's [documentation](https://helm.sh/docs/) to get started.
-
-Once Helm is set up properly, add the repo as follows:
-
-```console
-helm repo add plcnk https://charts.plcnk.net
-helm repo update
-```
-
-You can then run `helm search repo plcnk` to see the charts.
-
-## Available charts
+## Chart Overview
| Chart | Description |
| ----- | ----------- |
-| [IT-Tools
](https://github.com/plcnk/charts/tree/master/charts/it-tools) | Collection of handy online tools for developers, with great UX. |
+| [# it-tools
](charts/it-tools/) | Collection of handy online tools for developers, with great UX. |
## License
-This project is licensed under the [MIT License](https://github.com/plcnk/charts/blob/master/LICENSE).
+This project is licensed under the [MIT License](./LICENSE).
diff --git a/charts/it-tools/Chart.lock b/charts/it-tools/Chart.lock
new file mode 100644
index 0000000..8764151
--- /dev/null
+++ b/charts/it-tools/Chart.lock
@@ -0,0 +1,6 @@
+dependencies:
+- name: common
+ repository: https://bjw-s.github.io/helm-charts
+ version: 3.3.2
+digest: sha256:5a0f9f06aa383b7cc3070899b879401bcd4ae48b021d0a2b7f9ba39827019e24
+generated: "2024-08-15T17:47:53.312594+02:00"
diff --git a/charts/it-tools/Chart.yaml b/charts/it-tools/Chart.yaml
index c8cf05e..cf4a3f9 100644
--- a/charts/it-tools/Chart.yaml
+++ b/charts/it-tools/Chart.yaml
@@ -4,7 +4,7 @@ description: Collection of handy online tools for developers, with great UX.
home: https://github.com/plcnk/charts/tree/master/charts/it-tools
icon: https://raw.githubusercontent.com/plcnk/charts/master/charts/it-tools/icon.svg
type: application
-version: 1.0.5
+version: 2.0.0
# renovate datasource=docker depName=ghcr.io/corentinth/it-tools
appVersion: "2024.5.13-a0bc346"
kubeVersion: ">=1.22.0-0"
@@ -12,12 +12,16 @@ keywords:
- it-tools
- it
- tools
+dependencies:
+ - name: common
+ repository: https://bjw-s.github.io/helm-charts
+ version: 3.3.2
sources:
- https://github.com/CorentinTh/it-tools
annotations:
artifacthub.io/changes: |-
- kind: changed
- description: Changed chart metadata
+ description: Major chart overhaul. Now using bjw-s's common library chart.
artifacthub.io/links: |-
- name: App Source
url: https://github.com/CorentinTh/it-tools
diff --git a/charts/it-tools/README.md b/charts/it-tools/README.md
index 69a4535..5c5e456 100644
--- a/charts/it-tools/README.md
+++ b/charts/it-tools/README.md
@@ -1,16 +1,32 @@
-# IT-Tools
+# # it-tools
-Helm chart for deploying [it-tools](https://it-tools.tech/).
+
-it-tools is a collection of handy online tools for developers, with great UX.
+
+
+
-> [!NOTE]
-> This chart is not maintained by the original author of it-tools and any problems with this chart should be submitted [here](https://github.com/plcnk/charts/issues/new).
+Collection of handy online tools for developers, with great UX.
-## Source code
+**Homepage:**
+
+**This chart is not maintained by the upstream project and any issues with the chart should be raised
+[here](https://github.com/plcnk/charts/issues/new?assignees=plcnk&labels=bug&template=bug_report.yaml&name=it-tools&version=2.0.0)**
+
+## Source Code
*
+## Requirements
+
+Kubernetes: `>=1.22.0-0`
+
+## Dependencies
+
+| Repository | Name | Version |
+|------------|------|---------|
+| | common | 3.3.2 |
+
## Installing the Chart
To install the chart with the release name `it-tools`
@@ -39,80 +55,51 @@ helm uninstall it-tools
The command removes all the Kubernetes components associated with the chart **including persistent volumes** and deletes the release.
-## Parameters
+## Configuration
-### Global parameters
+Read through the [values.yaml](./values.yaml) file. It has several commented out suggested values.
+Other values may be used from the [values.yaml](https://github.com/bjw-s/helm-charts/tree/main/charts/library/common/values.yaml) from the [bjw-s common library](https://github.com/bjw-s/helm-charts/tree/main/charts/library/common).
-| Name | Description | Value |
-| ------------------ | ---------------------------------------------- | ----- |
-| `replicaCount` | Number of replicas for the it-tools Deployment | `1` |
-| `imagePullSecrets` | Docker registry pull secrets | `[]` |
-| `nameOverride` | Name override | `""` |
-| `fullnameOverride` | Full name override | `""` |
-| `podAnnotations` | Additional annotations for the Pod resource | `{}` |
-| `podLabels` | Additional labels for the Pod resource | `{}` |
-| `nodeSelector` | Node labels for pod assignment | `{}` |
-| `tolerations` | Tolerations for pod assignment | `[]` |
-| `affinity` | Affinity for pod assignment | `{}` |
+Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`.
-### Image parameters
+```console
+helm install it-tools \
+ --set env.TZ="America/New York" \
+ plcnk/it-tools
+```
-| Name | Description | Value |
-| ------------------ | ------------------------------------------------------------- | ----------------------------- |
-| `image.repository` | Docker image repository | `ghcr.io/corentinth/it-tools` |
-| `image.pullPolicy` | Docker image pull policy | `IfNotPresent` |
-| `image.tag` | Overrides the image tag whose default is the chart appVersion | `""` |
+Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart.
-### Service account parameters
+```console
+helm install it-tools plcnk/it-tools -f values.yaml
+```
-| Name | Description | Value |
-| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------- |
-| `serviceAccount.create` | Specifies whether a service account should be created | `false` |
-| `serviceAccount.automount` | Automatically mount a ServiceAccount's API credentials? | `true` |
-| `serviceAccount.annotations` | Additional annotations for the ServiceAccount resource | `{}` |
-| `serviceAccount.name` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template | `""` |
+## Custom configuration
-### Security context parameters
+N/A
-| Name | Description | Value |
-| ------------------------------------------ | ----------------------------------------- | ---------------- |
-| `securityContext.capabilities.drop` | Capabilities to drop | `["ALL"]` |
-| `securityContext.readOnlyRootFilesystem` | If root filesystem should be read-only | `true` |
-| `securityContext.runAsNonRoot` | If pod should be run as non-root | `true` |
-| `securityContext.runAsUser` | User to run pod as | `10099` |
-| `securityContext.runAsGroup` | Group to run pod as | `10099` |
-| `securityContext.allowPrivilegeEscalation` | If privilege escalation should be allowed | `false` |
-| `securityContext.seccompProfile.type` | seccomp profile type | `RuntimeDefault` |
+## Values
-### Service parameters
+**Important**: When deploying an application Helm chart you can add more values from the bjw-s common library chart [here](https://github.com/bjw-s/helm-charts/tree/main/charts/library/common)
-| Name | Description | Value |
-| -------------- | ---------------------- | ----------- |
-| `service.type` | Service type to create | `ClusterIP` |
-| `service.port` | Service port to use | `80` |
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| controllers.main.containers.app.env | object | See [values.yaml](./values.yaml) | Environment variables |
+| controllers.main.containers.app.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| controllers.main.containers.app.image.repository | string | `"ghcr.io/corentinth/it-tools"` | Image repository |
+| controllers.main.containers.app.image.tag | string | `"2024.5.13-a0bc346"` | Image tag |
+| controllers.main.containers.app.securityContext.allowPrivilegeEscalation | bool | `false` | Disable privilege escalations |
+| controllers.main.containers.app.securityContext.capabilities | object | `{"drop":["ALL"]}` | Drop all capabilities |
+| controllers.main.containers.app.securityContext.readOnlyRootFilesystem | bool | `true` | Mount the container's root filesystem as read-only |
+| controllers.main.pod.securityContext.fsGroup | int | `65534` | Volume binds will be granted to `nobody` group |
+| controllers.main.pod.securityContext.runAsGroup | int | `65534` | Run as `nobody` group |
+| controllers.main.pod.securityContext.runAsNonRoot | bool | `true` | Run container as a non-root user |
+| controllers.main.pod.securityContext.runAsUser | int | `65534` | Run as `nobody` user |
+| controllers.main.resources | object | `{}` | Set the resource requests / limits for the container. |
+| controllers.main.type | string | `"deployment"` | Controller type |
+| ingress.main | object | See [values.yaml](./values.yaml) | Enable and configure ingress settings for the chart under this key. |
+| persistence | object | See [values.yaml](./values.yaml) | Configure persistence for the chart under this key. |
+| service | object | See [values.yaml](./values.yaml) | Configure the services for the chart here. |
-### Ingress parameters
-
-| Name | Description | Value |
-| --------------------- | ------------------------------------------------------------------------ | ------- |
-| `ingress.enabled` | Enable ingress record generation | `false` |
-| `ingress.className` | IngressClass that will be be used to implement the Ingress | `""` |
-| `ingress.annotations` | Additional annotations for the Ingress resource | `{}` |
-| `ingress.hosts` | An array with hostname(s) to be covered with the ingress record | `[]` |
-| `ingress.tls` | TLS configuration for hostname(s) to be covered with this ingress record | `[]` |
-
-### Resources parameters
-
-| Name | Description | Value |
-| ----------- | -------------------- | ----- |
-| `resources` | Kubernetes resources | `{}` |
-
-### Autoscaling parameters
-
-| Name | Description | Value |
-| ----------------------------------------------- | ------------------------------------ | ------- |
-| `autoscaling.enabled` | Enable Horizontal POD autoscaling | `false` |
-| `autoscaling.minReplicas` | Minimum number of replicas | `1` |
-| `autoscaling.maxReplicas` | Maximum number of replicas | `100` |
-| `autoscaling.targetCPUUtilizationPercentage` | Target CPU utilization percentage | `80` |
-| `autoscaling.targetMemoryUtilizationPercentage` | Target Memory utilization percentage | `80` |
+---
+Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs)
diff --git a/charts/it-tools/README_CONFIG.md.gotmpl b/charts/it-tools/README_CONFIG.md.gotmpl
new file mode 100644
index 0000000..2a8b9ec
--- /dev/null
+++ b/charts/it-tools/README_CONFIG.md.gotmpl
@@ -0,0 +1,13 @@
+{{- define "custom.chart.name" -}}
+# {{ .Name }}
+{{- end -}}
+
+{{- define "custom.custom.configuration.header" -}}
+## Custom configuration
+{{- end -}}
+
+{{- define "custom.custom.configuration" -}}
+{{ template "custom.custom.configuration.header" . }}
+
+N/A
+{{- end -}}
diff --git a/charts/it-tools/templates/_helpers.tpl b/charts/it-tools/templates/_helpers.tpl
deleted file mode 100644
index 2597e2b..0000000
--- a/charts/it-tools/templates/_helpers.tpl
+++ /dev/null
@@ -1,62 +0,0 @@
-{{/*
-Expand the name of the chart.
-*/}}
-{{- define "it-tools.name" -}}
-{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Create a default fully qualified app name.
-We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
-If release name contains chart name it will be used as a full name.
-*/}}
-{{- define "it-tools.fullname" -}}
-{{- if .Values.fullnameOverride }}
-{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- $name := default .Chart.Name .Values.nameOverride }}
-{{- if contains $name .Release.Name }}
-{{- .Release.Name | trunc 63 | trimSuffix "-" }}
-{{- else }}
-{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
-{{- end }}
-{{- end }}
-{{- end }}
-
-{{/*
-Create chart name and version as used by the chart label.
-*/}}
-{{- define "it-tools.chart" -}}
-{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
-{{- end }}
-
-{{/*
-Common labels
-*/}}
-{{- define "it-tools.labels" -}}
-helm.sh/chart: {{ include "it-tools.chart" . }}
-{{ include "it-tools.selectorLabels" . }}
-{{- if .Chart.AppVersion }}
-app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
-{{- end }}
-app.kubernetes.io/managed-by: {{ .Release.Service }}
-{{- end }}
-
-{{/*
-Selector labels
-*/}}
-{{- define "it-tools.selectorLabels" -}}
-app.kubernetes.io/name: {{ include "it-tools.name" . }}
-app.kubernetes.io/instance: {{ .Release.Name }}
-{{- end }}
-
-{{/*
-Create the name of the service account to use
-*/}}
-{{- define "it-tools.serviceAccountName" -}}
-{{- if .Values.serviceAccount.create }}
-{{- default (include "it-tools.fullname" .) .Values.serviceAccount.name }}
-{{- else }}
-{{- default "default" .Values.serviceAccount.name }}
-{{- end }}
-{{- end }}
diff --git a/charts/it-tools/templates/common.yaml b/charts/it-tools/templates/common.yaml
new file mode 100644
index 0000000..f9e315c
--- /dev/null
+++ b/charts/it-tools/templates/common.yaml
@@ -0,0 +1,93 @@
+{{/* Append the hardcoded settings */}}
+{{- define "it-tools.harcodedValues" -}}
+configMaps:
+ nginx-conf:
+ enabled: true
+ data:
+ nginx.conf: |
+ worker_processes auto;
+
+ error_log /tmp/nginx/error.log warn;
+ pid /tmp/nginx/nginx.pid;
+
+ events {
+ worker_connections 1024;
+ }
+
+ http {
+ include /etc/nginx/mime.types;
+
+ server {
+ listen 80;
+ server_name _;
+ root /usr/share/nginx/html;
+ index index.html;
+
+ location / {
+ try_files $uri $uri/ /index.html;
+ }
+ }
+ }
+
+persistence:
+ cache:
+ enabled: true
+ type: emptyDir
+ advancedMounts:
+ main:
+ app:
+ - path: /var/cache/nginx
+ tmp:
+ enabled: true
+ type: emptyDir
+ advancedMounts:
+ main:
+ app:
+ - path: /tmp/nginx
+ nginx-conf:
+ enabled: true
+ type: configMap
+ name: {{ include "bjw-s.common.lib.chart.names.fullname" . }}-nginx-conf
+ advancedMounts:
+ main:
+ app:
+ - path: /etc/nginx/nginx.conf
+ subPath: nginx.conf
+
+controllers:
+ main:
+ containers:
+ app:
+ ports:
+ - containerPort: 80
+ name: http
+ protocol: TCP
+ probes:
+ liveness:
+ enabled: true
+ custom: true
+ spec:
+ httpGet:
+ path: /
+ port: http
+ periodSeconds: 30
+ timeoutSeconds: 30
+ readiness:
+ enabled: true
+ custom: true
+ spec:
+ httpGet:
+ path: /
+ port: http
+ periodSeconds: 30
+ timeoutSeconds: 30
+{{- end -}}
+
+{{- $tmplVars := deepCopy . -}}
+{{ include "bjw-s.common.loader.init" $tmplVars }}
+{{- $defaultValues := include "it-tools.harcodedValues" $tmplVars | fromYaml -}}
+{{- $_ := mustMerge .Values $defaultValues -}}
+
+{{/* Render the templates */}}
+{{ include "bjw-s.common.loader.init" . }}
+{{ include "bjw-s.common.loader.generate" . }}
diff --git a/charts/it-tools/templates/configmap.yaml b/charts/it-tools/templates/configmap.yaml
deleted file mode 100644
index f239dfc..0000000
--- a/charts/it-tools/templates/configmap.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-apiVersion: v1
-kind: ConfigMap
-metadata:
- name: nginx-conf
-data:
- nginx.conf: |
- worker_processes auto;
-
- error_log /tmp/nginx/error.log warn;
- pid /tmp/nginx/nginx.pid;
-
- events {
- worker_connections 1024;
- }
-
- http {
- include /etc/nginx/mime.types;
-
- server {
- listen 80;
- server_name _;
- root /usr/share/nginx/html;
- index index.html;
-
- location / {
- try_files $uri $uri/ /index.html;
- }
- }
- }
diff --git a/charts/it-tools/templates/deployment.yaml b/charts/it-tools/templates/deployment.yaml
deleted file mode 100644
index 9bb2dd8..0000000
--- a/charts/it-tools/templates/deployment.yaml
+++ /dev/null
@@ -1,82 +0,0 @@
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: {{ include "it-tools.fullname" . }}
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
-spec:
- {{- if not .Values.autoscaling.enabled }}
- replicas: {{ .Values.replicaCount }}
- {{- end }}
- selector:
- matchLabels:
- {{- include "it-tools.selectorLabels" . | nindent 6 }}
- template:
- metadata:
- {{- with .Values.podAnnotations }}
- annotations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- labels:
- {{- include "it-tools.labels" . | nindent 8 }}
- {{- with .Values.podLabels }}
- {{- toYaml . | nindent 8 }}
- {{- end }}
- spec:
- {{- with .Values.imagePullSecrets }}
- imagePullSecrets:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- serviceAccountName: {{ include "it-tools.serviceAccountName" . }}
- containers:
- - name: {{ .Chart.Name }}
- securityContext:
- {{- toYaml .Values.securityContext | nindent 12 }}
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
- imagePullPolicy: {{ .Values.image.pullPolicy }}
- ports:
- - name: http
- containerPort: {{ .Values.service.port }}
- protocol: TCP
- livenessProbe:
- httpGet:
- path: /
- port: http
- periodSeconds: 30
- timeoutSeconds: 30
- readinessProbe:
- httpGet:
- path: /
- port: http
- periodSeconds: 30
- timeoutSeconds: 30
- resources:
- {{- toYaml .Values.resources | nindent 12 }}
- volumeMounts:
- - name: cache
- mountPath: "/var/cache/nginx"
- - name: tmp
- mountPath: "/tmp/nginx"
- - name: conf
- mountPath: /etc/nginx/nginx.conf
- subPath: nginx.conf
- volumes:
- - name: cache
- emptyDir: {}
- - name: tmp
- emptyDir: {}
- - name: conf
- configMap:
- name: nginx-conf
- {{- with .Values.nodeSelector }}
- nodeSelector:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.affinity }}
- affinity:
- {{- toYaml . | nindent 8 }}
- {{- end }}
- {{- with .Values.tolerations }}
- tolerations:
- {{- toYaml . | nindent 8 }}
- {{- end }}
diff --git a/charts/it-tools/templates/hpa.yaml b/charts/it-tools/templates/hpa.yaml
deleted file mode 100644
index 436e6a3..0000000
--- a/charts/it-tools/templates/hpa.yaml
+++ /dev/null
@@ -1,32 +0,0 @@
-{{- if .Values.autoscaling.enabled }}
-apiVersion: autoscaling/v2
-kind: HorizontalPodAutoscaler
-metadata:
- name: {{ include "it-tools.fullname" . }}
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
-spec:
- scaleTargetRef:
- apiVersion: apps/v1
- kind: Deployment
- name: {{ include "it-tools.fullname" . }}
- minReplicas: {{ .Values.autoscaling.minReplicas }}
- maxReplicas: {{ .Values.autoscaling.maxReplicas }}
- metrics:
- {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
- - type: Resource
- resource:
- name: cpu
- target:
- type: Utilization
- averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
- {{- end }}
- {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
- - type: Resource
- resource:
- name: memory
- target:
- type: Utilization
- averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
- {{- end }}
-{{- end }}
diff --git a/charts/it-tools/templates/ingress.yaml b/charts/it-tools/templates/ingress.yaml
deleted file mode 100644
index 5c47a29..0000000
--- a/charts/it-tools/templates/ingress.yaml
+++ /dev/null
@@ -1,61 +0,0 @@
-{{- if .Values.ingress.enabled -}}
-{{- $fullName := include "it-tools.fullname" . -}}
-{{- $svcPort := .Values.service.port -}}
-{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }}
- {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }}
- {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}}
- {{- end }}
-{{- end }}
-{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
-apiVersion: networking.k8s.io/v1
-{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
-apiVersion: networking.k8s.io/v1beta1
-{{- else -}}
-apiVersion: extensions/v1beta1
-{{- end }}
-kind: Ingress
-metadata:
- name: {{ $fullName }}
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
- {{- with .Values.ingress.annotations }}
- annotations:
- {{- toYaml . | nindent 4 }}
- {{- end }}
-spec:
- {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }}
- ingressClassName: {{ .Values.ingress.className }}
- {{- end }}
- {{- if .Values.ingress.tls }}
- tls:
- {{- range .Values.ingress.tls }}
- - hosts:
- {{- range .hosts }}
- - {{ . | quote }}
- {{- end }}
- secretName: {{ .secretName }}
- {{- end }}
- {{- end }}
- rules:
- {{- range .Values.ingress.hosts }}
- - host: {{ .host | quote }}
- http:
- paths:
- {{- range .paths }}
- - path: {{ .path }}
- {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }}
- pathType: {{ .pathType }}
- {{- end }}
- backend:
- {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }}
- service:
- name: {{ $fullName }}
- port:
- number: {{ $svcPort }}
- {{- else }}
- serviceName: {{ $fullName }}
- servicePort: {{ $svcPort }}
- {{- end }}
- {{- end }}
- {{- end }}
-{{- end }}
diff --git a/charts/it-tools/templates/service.yaml b/charts/it-tools/templates/service.yaml
deleted file mode 100644
index 81d1fb7..0000000
--- a/charts/it-tools/templates/service.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-apiVersion: v1
-kind: Service
-metadata:
- name: {{ include "it-tools.fullname" . }}
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
-spec:
- type: {{ .Values.service.type }}
- ports:
- - port: {{ .Values.service.port }}
- targetPort: http
- protocol: TCP
- name: http
- selector:
- {{- include "it-tools.selectorLabels" . | nindent 4 }}
diff --git a/charts/it-tools/templates/serviceaccount.yaml b/charts/it-tools/templates/serviceaccount.yaml
deleted file mode 100644
index 620dc4d..0000000
--- a/charts/it-tools/templates/serviceaccount.yaml
+++ /dev/null
@@ -1,13 +0,0 @@
-{{- if .Values.serviceAccount.create -}}
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- name: {{ include "it-tools.serviceAccountName" . }}
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
- {{- with .Values.serviceAccount.annotations }}
- annotations:
- {{- toYaml . | nindent 4 }}
- {{- end }}
-automountServiceAccountToken: {{ .Values.serviceAccount.automount }}
-{{- end }}
diff --git a/charts/it-tools/templates/tests/test-connection.yaml b/charts/it-tools/templates/tests/test-connection.yaml
deleted file mode 100644
index b5b3798..0000000
--- a/charts/it-tools/templates/tests/test-connection.yaml
+++ /dev/null
@@ -1,15 +0,0 @@
-apiVersion: v1
-kind: Pod
-metadata:
- name: "{{ include "it-tools.fullname" . }}-test-connection"
- labels:
- {{- include "it-tools.labels" . | nindent 4 }}
- annotations:
- "helm.sh/hook": test
-spec:
- containers:
- - name: wget
- image: busybox
- command: ['wget']
- args: ['{{ include "it-tools.fullname" . }}:{{ .Values.service.port }}']
- restartPolicy: Never
diff --git a/charts/it-tools/values.yaml b/charts/it-tools/values.yaml
index 892dc0e..d3be3f0 100644
--- a/charts/it-tools/values.yaml
+++ b/charts/it-tools/values.yaml
@@ -1,128 +1,95 @@
-# Default values for it-tools.
-# This is a YAML-formatted file.
-# Declare variables to be passed into your templates.
+---
+#
+# IMPORTANT NOTE
+#
+# This chart inherits from our common library chart. You can check the default values/options here:
+# https://github.com/bjw-s/helm-charts/blob/main/charts/library/common/values.yaml
+#
-## @section Global parameters
-## @param replicaCount Number of replicas for the it-tools Deployment
-replicaCount: 1
+controllers:
+ main:
+ # -- Controller type
+ type: deployment
+ containers:
+ app:
+ image:
+ # -- Image repository
+ repository: ghcr.io/corentinth/it-tools
+ # -- Image pull policy
+ pullPolicy: IfNotPresent
+ # -- Image tag
+ tag: 2024.5.13-a0bc346
-## @param imagePullSecrets Docker registry pull secrets
-## @param nameOverride Name override
-## @param fullnameOverride Full name override
-imagePullSecrets: []
-nameOverride: ""
-fullnameOverride: ""
+ # -- Environment variables
+ # @default -- See [values.yaml](./values.yaml)
+ env: {}
+ # TZ: UTC
-## @param podAnnotations Additional annotations for the Pod resource
-## @param podLabels Additional labels for the Pod resource
-podAnnotations: {}
-podLabels: {}
+ securityContext:
+ # -- Mount the container's root filesystem as read-only
+ readOnlyRootFilesystem: true
+ # -- Disable privilege escalations
+ allowPrivilegeEscalation: false
+ # -- Drop all capabilities
+ capabilities:
+ drop:
+ - ALL
-## @param nodeSelector Node labels for pod assignment
-## ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
-nodeSelector: {}
+ pod:
+ securityContext:
+ # -- Run container as a non-root user
+ runAsNonRoot: true
+ # -- Run as `nobody` user
+ runAsUser: 65534
+ # -- Run as `nobody` group
+ runAsGroup: 65534
+ # -- Volume binds will be granted to `nobody` group
+ fsGroup: 65534
-## @param tolerations Tolerations for pod assignment
-## ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
-tolerations: []
+ # -- Set the resource requests / limits for the container.
+ resources: {}
+ # limits:
+ # cpu: 100m
+ # memory: 128Mi
+ # requests:
+ # cpu: 100m
+ # memory: 128Mi
-## @param affinity Affinity for pod assignment
-## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
-affinity: {}
-
-## @section Image parameters
-## @param image.repository Docker image repository
-## @param image.pullPolicy Docker image pull policy
-## @param image.tag Overrides the image tag whose default is the chart appVersion
-image:
- repository: ghcr.io/corentinth/it-tools
- pullPolicy: IfNotPresent
- tag: ""
-
-## @section Service account parameters
-## @param serviceAccount.create Specifies whether a service account should be created
-## @param serviceAccount.automount Automatically mount a ServiceAccount's API credentials?
-## @param serviceAccount.annotations Additional annotations for the ServiceAccount resource
-## @param serviceAccount.name The name of the service account to use. If not set and create is true, a name is generated using the fullname template
-serviceAccount:
- create: false
- automount: true
- annotations: {}
- name: ""
-
-## @section Security context parameters
-## @param securityContext.capabilities.drop Capabilities to drop
-## @param securityContext.readOnlyRootFilesystem If root filesystem should be read-only
-## @param securityContext.runAsNonRoot If pod should be run as non-root
-## @param securityContext.runAsUser User to run pod as
-## @param securityContext.runAsGroup Group to run pod as
-## @param securityContext.allowPrivilegeEscalation If privilege escalation should be allowed
-## @param securityContext.seccompProfile.type seccomp profile type
-securityContext:
- capabilities:
- drop:
- - ALL
- readOnlyRootFilesystem: true
- runAsNonRoot: true
- runAsUser: 10099
- runAsGroup: 10099
- allowPrivilegeEscalation: false
- seccompProfile:
- type: RuntimeDefault
-
-## @section Service parameters
-## @param service.type Service type to create
-## @param service.port Service port to use
+# -- Configure the services for the chart here.
+# @default -- See [values.yaml](./values.yaml)
service:
- type: ClusterIP
- port: 80
+ main:
+ controller: main
+ ports:
+ http:
+ port: 80
+
+# -- Configure persistence for the chart under this key.
+# @default -- See [values.yaml](./values.yaml)
+persistence:
+ data:
+ enabled: false
+ retain: true
+ # storageClass: ""
+ # accessMode: ReadWriteOnce
+ # size: 1Gi
-## @section Ingress parameters
-## Configure the ingress resource that allows you to access the installation
-## ref: https://kubernetes.io/docs/concepts/services-networking/ingress/
-##
-## @param ingress.enabled Enable ingress record generation
-## @param ingress.className IngressClass that will be be used to implement the Ingress
-## @param ingress.annotations Additional annotations for the Ingress resource
-## @param ingress.hosts An array with hostname(s) to be covered with the ingress record
-## @param ingress.tls TLS configuration for hostname(s) to be covered with this ingress record
ingress:
- enabled: false
- className: ""
- annotations: {}
- # kubernetes.io/ingress.class: nginx
- # kubernetes.io/tls-acme: "true"
- hosts: []
- # - host: it-tools.example.local
- # paths:
- # - path: /
- # pathType: Prefix
- tls: []
- # - secretName: it-tools-tls
- # hosts:
- # - it-tools.example.local
-
-## @section Resources parameters
-## @param resources Kubernetes resources
-resources: {}
- # limits:
- # cpu: 100m
- # memory: 128Mi
- # requests:
- # cpu: 100m
- # memory: 128Mi
-
-## @section Autoscaling parameters
-## Autoscaling parameters
-## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
-## @param autoscaling.enabled Enable Horizontal POD autoscaling
-## @param autoscaling.minReplicas Minimum number of replicas
-## @param autoscaling.maxReplicas Maximum number of replicas
-## @param autoscaling.targetCPUUtilizationPercentage Target CPU utilization percentage
-## @param autoscaling.targetMemoryUtilizationPercentage Target Memory utilization percentage
-autoscaling:
- enabled: false
- minReplicas: 1
- maxReplicas: 100
- targetCPUUtilizationPercentage: 80
- targetMemoryUtilizationPercentage: 80
+ # -- Enable and configure ingress settings for the chart under this key.
+ # @default -- See [values.yaml](./values.yaml)
+ main:
+ enabled: false
+ # className: ""
+ # annotations: {}
+ # hosts:
+ # - host: &host-main "chart-example.local"
+ # paths:
+ # - path: /
+ # pathType: Prefix
+ # service:
+ # identifier: main
+ # port: http
+ # tls:
+ # - secretName: chart-example-tls
+ # hosts:
+ # - *host-main
diff --git a/hack/gen-chart-summary.sh b/hack/gen-chart-summary.sh
new file mode 100755
index 0000000..64d4896
--- /dev/null
+++ b/hack/gen-chart-summary.sh
@@ -0,0 +1,39 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# require yq
+command -v yq >/dev/null 2>&1 || {
+ echo >&2 'yq (https://github.com/mikefarah/yq) is not installed. Aborting.'
+ exit 1
+}
+
+# Absolute path of repository
+repository="$(git rev-parse --show-toplevel)"
+charts_folder="$repository/charts"
+charts_summary_file="$repository/README.md"
+charts_header='## Chart Overview'
+
+# Gather all charts
+stable_charts="$(find "$charts_folder" -name "Chart.yaml" | sort)"
+
+sed -i '' '/^'"$charts_header"'$/,$d' "$charts_summary_file"
+
+{
+ echo "$charts_header"
+ echo
+ echo "| Chart | Description |"
+ echo "| ----- | ----------- |"
+ for chart_yaml in ${stable_charts[@]}; do
+ if ! git ls-files --error-unmatch "$chart_yaml" &>/dev/null; then continue; fi
+ IFS=$'\t' read -r chart_name chart_description chart_icon < <(yq eval -o=tsv '[.name, .description, .icon // ""]' "$chart_yaml")
+ if [[ -n "$chart_icon" ]]; then
+ width=18
+ if [[ "$chart_name" == mnemonic-ninja ]]; then
+ width=12
+ fi
+ chart_icon="
"
+ fi
+ pretty_name="$(head -n1 "$(dirname "$chart_yaml")/README.md" | sed 's/^# //')"
+ echo "| [$pretty_name $chart_icon](charts/$chart_name/) | $chart_description |"
+ done
+} >> "$charts_summary_file"
diff --git a/hack/gen-helm-docs.sh b/hack/gen-helm-docs.sh
new file mode 100755
index 0000000..09a2d47
--- /dev/null
+++ b/hack/gen-helm-docs.sh
@@ -0,0 +1,59 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Generate helm-docs for Helm charts
+# Usage ./gen-helm-docs.sh [chart]
+
+# require helm-docs
+command -v helm-docs >/dev/null 2>&1 || {
+ echo >&2 'helm-docs (https://github.com/norwoodj/helm-docs) is not installed. Aborting.'
+ exit 1
+}
+
+# require yq
+command -v yq >/dev/null 2>&1 || {
+ echo >&2 'yq (https://github.com/mikefarah/yq) is not installed. Aborting.'
+ exit 1
+}
+
+# Absolute path of repository
+repository="$(git rev-parse --show-toplevel)"
+charts_folder="$repository/charts"
+
+# Templates to copy into each chart directory
+template_dir="$repository/hack/templates"
+readme_config_template="$template_dir/README_CONFIG.md.gotmpl"
+icon_template=$(<"$template_dir/icon.gotmpl")
+
+# Gather all charts using the common library, excluding common-test
+charts="$(find "$charts_folder" -name Chart.yaml)"
+
+# Allow for a specific chart to be passed in as a argument
+if [ $# -ge 1 ] && [ -n "$1" ]; then
+ root="$(find "$charts_folder" -name "$1")"
+ charts="$root/Chart.yaml"
+ if [ ! -f "$charts" ]; then
+ echo "Chart $1 does not exist."
+ exit 1
+ fi
+else
+ root="$charts_folder"
+fi
+
+for chart in $charts; do (
+ chart_directory="$(dirname "$chart")"
+ icon="$(yq eval '.icon // ""' "$chart" 2>/dev/null)"
+
+ # Copy CONFIG template to each Chart directory, do not overwrite if exists
+ cp -n "$readme_config_template" "$chart_directory" || true
+
+ # Run helm-docs for charts
+ helm-docs \
+ --log-level=warning \
+ --template-files="$template_dir/README.md.gotmpl" \
+ --template-files=<(echo "${icon_template/\$ICON/$icon}") \
+ --template-files="$(basename "$readme_config_template")" \
+ --badge-style=flat \
+ --chart-search-root="$root" \
+ --chart-to-generate="$chart_directory"
+) done
diff --git a/hack/templates/README.md.gotmpl b/hack/templates/README.md.gotmpl
new file mode 100644
index 0000000..da25614
--- /dev/null
+++ b/hack/templates/README.md.gotmpl
@@ -0,0 +1,170 @@
+{{- define "custom.repository.organization" -}}
+plcnk
+{{- end -}}
+
+{{- define "custom.repository.url" -}}
+https://github.com/plcnk/charts
+{{- end -}}
+
+{{- define "custom.helm.url" -}}
+https://charts.plcnk.net
+{{- end -}}
+
+{{- define "custom.helm.path" -}}
+{{ template "custom.repository.organization" . }}/{{ template "chart.name" . }}
+{{- end -}}
+
+{{- define "custom.helm.oci_url" -}}
+oci://ghcr.io/plcnk/charts
+{{- end -}}
+
+{{- define "custom.notes" -}}
+**This chart is not maintained by the upstream project and any issues with the chart should be raised
+[here]({{ template "custom.repository.url" . }}/issues/new?assignees=plcnk&labels=bug&template=bug_report.yaml&name={{ template "chart.name" . }}&version={{ template "chart.version" . }})**
+{{- end -}}
+
+{{- define "custom.requirements" -}}
+## Requirements
+
+{{ template "chart.kubeVersionLine" . }}
+{{- end -}}
+
+{{- define "custom.dependencies" -}}
+## Dependencies
+
+{{ if gt (len .Dependencies) 0 }}
+| Repository | Name | Version |
+|------------|------|---------|
+{{- range .Dependencies }}
+{{- if .Alias }}
+| <{{ .Repository }}> | {{ .Alias }}({{ .Name }}) | {{ .Version }} |
+{{- else }}
+| <{{ .Repository }}> | {{ .Name }} | {{ .Version }} |
+{{- end }}
+{{- end }}
+{{ else }}
+This chart has no dependencies.
+{{- end }}
+{{- end -}}
+
+{{- define "custom.install" -}}
+## Installing the Chart
+
+To install the chart with the release name `{{ template "chart.name" . }}`
+
+### OCI (Recommended)
+
+```console
+helm install {{ template "chart.name" . }} {{ template "custom.helm.oci_url" . }}/{{ template "chart.name" . }}
+```
+
+### Traditional
+
+```console
+helm repo add {{ template "custom.repository.organization" . }} {{ template "custom.helm.url" . }}
+helm repo update
+helm install {{ template "chart.name" . }} {{ template "custom.helm.path" . }}
+```
+{{- end -}}
+
+{{- define "custom.uninstall" -}}
+## Uninstalling the Chart
+
+To uninstall the `{{ template "chart.name" . }}` deployment
+
+```console
+helm uninstall {{ template "chart.name" . }}
+```
+
+The command removes all the Kubernetes components associated with the chart **including persistent volumes** and deletes the release.
+{{- end -}}
+
+{{- define "custom.configuration.header" -}}
+## Configuration
+{{- end -}}
+
+
+{{- define "custom.bjwsRef" -}}
+{{- $ref := "" -}}
+{{- range .Dependencies -}}
+{{- if and (eq .Repository "https://bjw-s.github.io/helm-charts") (eq .Name "common") (semverCompare "^1.x" .Version) -}}
+{{- $ref = "a081de5" -}}
+{{- end -}}
+{{- end -}}
+{{- default "main" $ref -}}
+{{- end -}}
+
+{{- define "custom.configuration.readValues" -}}
+Read through the [values.yaml](./values.yaml) file. It has several commented out suggested values.
+Other values may be used from the [values.yaml](https://github.com/bjw-s/helm-charts/tree/{{ template "custom.bjwsRef" . }}/charts/library/common/values.yaml) from the [bjw-s common library](https://github.com/bjw-s/helm-charts/tree/{{ template "custom.bjwsRef" . }}/charts/library/common).
+{{- end -}}
+
+{{- define "custom.configuration.example.set" -}}
+Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`.
+
+```console
+helm install {{ template "chart.name" . }} \
+ --set env.TZ="America/New York" \
+ {{ template "custom.helm.path" . }}
+```
+{{- end -}}
+
+{{- define "custom.configuration.example.file" -}}
+Alternatively, a YAML file that specifies the values for the above parameters can be provided while installing the chart.
+
+```console
+helm install {{ template "chart.name" . }} {{ template "custom.helm.path" . }} -f values.yaml
+```
+{{- end -}}
+
+{{- define "custom.valuesSection" -}}
+## Values
+
+**Important**: When deploying an application Helm chart you can add more values from the bjw-s common library chart [here](https://github.com/bjw-s/helm-charts/tree/{{ template "custom.bjwsRef" . }}/charts/library/common)
+
+{{ template "chart.valuesTable" . }}
+{{- end -}}
+
+{{- define "custom.helm-docs.versionFooter" -}}
+---
+Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs)
+{{- end -}}
+
+# {{ template "custom.chart.name" . }}
+
+{{ template "custom.chart.icon" . }}
+
+{{ template "chart.versionBadge" . }}
+{{ template "chart.typeBadge" . }}
+{{ template "chart.appVersionBadge" . }}
+
+{{ template "chart.description" . }}
+
+{{ template "chart.homepageLine" . }}
+
+{{ template "custom.notes" . }}
+
+{{ template "chart.sourcesSection" . }}
+
+{{ template "custom.requirements" . }}
+
+{{ template "custom.dependencies" . }}
+
+{{ template "custom.install" . }}
+
+{{ template "custom.uninstall" . }}
+
+{{ template "custom.configuration.header" . }}
+
+{{ template "custom.configuration.readValues" . }}
+
+{{ template "custom.configuration.example.set" . }}
+
+{{ template "custom.configuration.example.file" . }}
+
+{{ template "custom.custom.configuration" . }}
+
+{{ template "custom.valuesSection" . }}
+
+{{ template "custom.helm-docs.versionFooter" . }}
+{{ "" }}
diff --git a/hack/templates/README_CONFIG.md.gotmpl b/hack/templates/README_CONFIG.md.gotmpl
new file mode 100644
index 0000000..2a8b9ec
--- /dev/null
+++ b/hack/templates/README_CONFIG.md.gotmpl
@@ -0,0 +1,13 @@
+{{- define "custom.chart.name" -}}
+# {{ .Name }}
+{{- end -}}
+
+{{- define "custom.custom.configuration.header" -}}
+## Custom configuration
+{{- end -}}
+
+{{- define "custom.custom.configuration" -}}
+{{ template "custom.custom.configuration.header" . }}
+
+N/A
+{{- end -}}
diff --git a/hack/templates/icon.gotmpl b/hack/templates/icon.gotmpl
new file mode 100644
index 0000000..d51c604
--- /dev/null
+++ b/hack/templates/icon.gotmpl
@@ -0,0 +1,5 @@
+{{- define "custom.chart.icon" -}}
+ {{- with "$ICON" -}}
+
+ {{- end -}}
+{{- end -}}
diff --git a/hack/update-changelog.sh b/hack/update-changelog.sh
new file mode 100755
index 0000000..7bf3cde
--- /dev/null
+++ b/hack/update-changelog.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+set -euo pipefail
+IFS=$'\n\t'
+
+# require yq
+command -v yq >/dev/null 2>&1 || {
+ echo >&2 'yq (https://github.com/mikefarah/yq) is not installed. Aborting.'
+ exit 1
+}
+
+if [ "$#" -lt 2 ]; then
+ echo 'Usage: {append | replace} changelog [chart...]'
+ exit
+fi
+
+update_type="$1"
+shift
+
+changelog="$(yq -P <<<"$1")"
+export changelog
+shift
+
+CHARTS=()
+if [ "$#" -gt 0 ]; then
+ # Get changed dirs from params
+ for file in "$@"; do
+ CHARTS+=( "$(dirname "$file")" )
+ done
+else
+ # Get changed dirs from uncommitted changes
+ for file in $(git status --porcelain charts | grep '^M' | cut -c4-); do
+ CHARTS+=( "$(dirname "$file")" )
+ done
+fi
+CHARTS=( $(sort -u <<<"${CHARTS[*]}") )
+
+case "$update_type" in
+ append)
+ expression='.annotations."artifacthub.io/changes" |= (@yamld + (strenv(changelog) | @yamld) | @yaml | trim)'
+ ;;
+ replace)
+ expression='.annotations."artifacthub.io/changes" = (env(changelog) | @yaml | trim)'
+ ;;
+ *)
+ echo "Invalid update type: $update_type" >&2
+ exit 1
+ ;;
+esac
+
+for chart in "${CHARTS[@]}"; do (
+ meta_file="$chart/Chart.yaml"
+ if [ ! -f "$meta_file" ]; then echo >&2 "Invalid file: $meta_file"; exit; fi
+
+ yq --inplace "$expression" "$meta_file"
+ echo "Updated $(basename "$chart") changelog"
+) done
diff --git a/hack/update-version.sh b/hack/update-version.sh
new file mode 100755
index 0000000..12dc3e5
--- /dev/null
+++ b/hack/update-version.sh
@@ -0,0 +1,53 @@
+#!/usr/bin/env bash
+set -euo pipefail
+IFS=$'\n\t'
+
+# require yq
+command -v yq >/dev/null 2>&1 || {
+ echo >&2 'yq (https://github.com/mikefarah/yq) is not installed. Aborting.'
+ exit 1
+}
+
+function _print_usage() {
+ echo 'Usage: {major|minor|patch} [chart...]'
+ exit "${1:-0}"
+}
+
+if [ "$#" -eq 0 ]; then
+ _print_usage
+fi
+
+UPDATE_TYPE="$(tr '[:upper:]' '[:lower:]' <<<"$1")"
+shift
+case "$UPDATE_TYPE" in
+ major) SCRIPT='[(.0 | @yamld | . + 1), 0, 0]' ;;
+ minor) SCRIPT='[.0, (.1 | @yamld | . + 1), 0]' ;;
+ patch) SCRIPT='[.0, .1, (.2 | @yamld | . + 1)]' ;;
+ *) echo >&2 "Invalid update type: $UPDATE_TYPE"; _print_usage 1 ;;
+esac
+
+echo "Performing $UPDATE_TYPE version bump"
+
+CHARTS=()
+if [ "$#" -gt 0 ]; then
+ # Get changed dirs from params
+ for file in "$@"; do
+ CHARTS+=( "$(dirname "$file")" )
+ done
+else
+ # Get changed dirs from uncommitted changes
+ for file in $(git status --porcelain charts | grep '^M' | cut -c4-); do
+ CHARTS+=( "$(dirname "$file")" )
+ done
+fi
+CHARTS=( $(sort -u <<<"${CHARTS[*]}") )
+
+for chart in "${CHARTS[@]}"; do (
+ meta_file="$chart/Chart.yaml"
+ if [ ! -f "$meta_file" ]; then echo >&2 "Invalid file: $meta_file"; exit; fi
+
+ current="$(yq '.version' "$meta_file")"
+ yq -i '.version |= (split(".") | '"$SCRIPT"' | join("."))' "$meta_file"
+ new="$(yq '.version' "$meta_file")"
+ echo "Updated $(basename "$chart") from v$current to v$new"
+) done