From 4439beed3d401f4ff3d4337427fb76a72eac4bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nogueira?= Date: Tue, 1 Jul 2025 17:16:01 +0100 Subject: [PATCH 1/2] feat: add helm chart Signed-off-by: Andre Nogueira --- kubernetes/chart/.helmignore | 23 + kubernetes/chart/Chart.yaml | 15 + kubernetes/chart/README.md | 92 ++++ kubernetes/chart/templates/NOTES.txt | 22 + kubernetes/chart/templates/_helpers.tpl | 78 +++ kubernetes/chart/templates/config.yaml | 10 + kubernetes/chart/templates/deployment.yaml | 136 +++++ kubernetes/chart/templates/hpa.yaml | 33 ++ kubernetes/chart/templates/ingress.yaml | 44 ++ kubernetes/chart/templates/pdb.yaml | 18 + kubernetes/chart/templates/service.yaml | 16 + .../chart/templates/serviceaccount.yaml | 14 + kubernetes/chart/values.schema.json | 469 ++++++++++++++++++ kubernetes/chart/values.yaml | 265 ++++++++++ 14 files changed, 1235 insertions(+) create mode 100644 kubernetes/chart/.helmignore create mode 100644 kubernetes/chart/Chart.yaml create mode 100644 kubernetes/chart/README.md create mode 100644 kubernetes/chart/templates/NOTES.txt create mode 100644 kubernetes/chart/templates/_helpers.tpl create mode 100644 kubernetes/chart/templates/config.yaml create mode 100644 kubernetes/chart/templates/deployment.yaml create mode 100644 kubernetes/chart/templates/hpa.yaml create mode 100644 kubernetes/chart/templates/ingress.yaml create mode 100644 kubernetes/chart/templates/pdb.yaml create mode 100644 kubernetes/chart/templates/service.yaml create mode 100644 kubernetes/chart/templates/serviceaccount.yaml create mode 100644 kubernetes/chart/values.schema.json create mode 100644 kubernetes/chart/values.yaml diff --git a/kubernetes/chart/.helmignore b/kubernetes/chart/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/kubernetes/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/kubernetes/chart/Chart.yaml b/kubernetes/chart/Chart.yaml new file mode 100644 index 000000000..67362bf61 --- /dev/null +++ b/kubernetes/chart/Chart.yaml @@ -0,0 +1,15 @@ +apiVersion: v2 +type: application +name: sourcebot +version: 0.1.0 +appVersion: "" +description: The open source Sourcegraph alternative. Sourcebot gives you a powerful interface to search though all your repos and branches across multiple code hosts. +icon: https://raw.githubusercontent.com/sourcebot-dev/sourcebot/ebf6721836b8f878d42bb8c1e844bdc7867a74fe/packages/web/public/logo_512.png +keywords: + - code-search + - code-intelligence + - sourcebot +home: https://sourcebot.dev/ +sources: + - https://github.com/sourcebot-dev/sourcebot + - https://github.com/sourcebot-dev/sourcebot/kubernetes/chart diff --git a/kubernetes/chart/README.md b/kubernetes/chart/README.md new file mode 100644 index 000000000..47861d5b7 --- /dev/null +++ b/kubernetes/chart/README.md @@ -0,0 +1,92 @@ +# sourcebot + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) + +The open source Sourcegraph alternative. Sourcebot gives you a powerful interface to search though all your repos and branches across multiple code hosts. + +**Homepage:** + +## Source Code + +* +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| additionalLabels | object | `{}` | Add extra labels to all resources. | +| affinity | object | `{}` | Set affinity rules for pod scheduling. Defaults to soft anti-affinity if not set. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ | +| args | list | `[]` | Override the default arguments of the container. | +| autoscaling | object | `{"enabled":false,"maxReplicas":3,"minReplicas":1,"targetCPUUtilizationPercentage":80,"targetMemoryUtilizationPercentage":80}` | Configure Horizontal Pod Autoscaler. | +| autoscaling.enabled | bool | `false` | Enable or disable Horizontal Pod Autoscaler. | +| autoscaling.maxReplicas | int | `3` | Maximum number of replicas. | +| autoscaling.minReplicas | int | `1` | Minimum number of replicas. | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | Target CPU utilization percentage for autoscaling. | +| autoscaling.targetMemoryUtilizationPercentage | int | `80` | Target memory utilization percentage for autoscaling. | +| command | list | `[]` | Override the default command of the container. | +| config | object | `{"$schema":"https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json","connections":{},"settings":{}}` | Configure Sourcebot-specific application settings. | +| containerSecurityContext | object | `{}` | Set the container-level security context. | +| database | object | `{}` | Configure the database secret. | +| envSecrets | list | `[]` | Set environment variables from Kubernetes secrets. | +| envs | list | `[]` | Set additional environment variables. | +| fullnameOverride | string | `""` | Override the full name of the chart. | +| image | object | `{"pullPolicy":"Always","repository":"ghcr.io/sourcebot-dev/sourcebot","tag":"latest"}` | Configure the container image. | +| image.pullPolicy | string | `"Always"` | Image pull policy. | +| image.repository | string | `"ghcr.io/sourcebot-dev/sourcebot"` | Container image repository. | +| image.tag | string | `"latest"` | Container image tag. | +| imagePullSecrets | list | `[]` | Configure image pull secrets for private registries. | +| ingress | object | `{"annotations":{},"className":"","enabled":false,"hosts":[],"tls":[]}` | Configure ingress for Sourcebot. | +| ingress.annotations | object | `{}` | Ingress annotations. | +| ingress.className | string | `""` | Ingress class name. | +| ingress.enabled | bool | `false` | Enable or disable ingress. | +| ingress.hosts | list | `[]` | List of hostnames and paths for ingress rules. | +| ingress.tls | list | `[]` | TLS settings for ingress. | +| initContainers | list | `[]` | Configure init containers to run before the main container. | +| license | object | `{}` | Configure the enterprise license key secret. | +| livenessProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/","port":"http"},"initialDelaySeconds":10,"periodSeconds":10}` | Liveness probe to check if the container is alive. | +| livenessProbe.failureThreshold | int | `5` | Number of consecutive failures before marking the container as unhealthy. | +| livenessProbe.httpGet | object | `{"path":"/","port":"http"}` | Http GET request to check if the container is alive. | +| livenessProbe.httpGet.path | string | `"/"` | Path to check. | +| livenessProbe.httpGet.port | string | `"http"` | Port to check. | +| livenessProbe.initialDelaySeconds | int | `10` | Initial delay before the first probe. | +| livenessProbe.periodSeconds | int | `10` | Frequency of the probe. | +| nameOverride | string | `""` | Override the name of the chart. | +| nodeSelector | object | `{}` | Set node selector constraints. See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector | +| podAnnotations | object | `{}` | Add annotations to the pod metadata. | +| podDisruptionBudget | object | `{"enabled":true,"maxUnavailable":1,"minAvailable":1}` | Configure Pod Disruption Budget. | +| podDisruptionBudget.enabled | bool | `true` | Enable Pod Disruption Budget. | +| podDisruptionBudget.maxUnavailable | int | `1` | Maximum number of pods that can be unavailable. | +| podDisruptionBudget.minAvailable | int | `1` | Minimum number of pods that must be available. | +| podSecurityContext | object | `{}` | Set the pod-level security context. | +| priorityClassName | string | `""` | Set the priority class name for pods. See: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ | +| readinessProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/","port":"http"},"initialDelaySeconds":10,"periodSeconds":10}` | Readiness probe to check if the container is ready to serve traffic. | +| readinessProbe.failureThreshold | int | `5` | Number of consecutive failures before marking the container as not ready. | +| readinessProbe.httpGet | object | `{"path":"/","port":"http"}` | Http GET request to check if the container is ready. | +| readinessProbe.httpGet.path | string | `"/"` | Path to check. | +| readinessProbe.httpGet.port | string | `"http"` | Port to check. | +| readinessProbe.initialDelaySeconds | int | `10` | Initial delay before the first probe. | +| readinessProbe.periodSeconds | int | `10` | Frequency of the probe. | +| redis | object | `{}` | Configure the Redis secret. | +| replicaCount | int | `1` | Set the number of replicas for the deployment. | +| resources | object | `{}` | Configure resource requests and limits for the container. | +| service | object | `{"annotations":{},"containerPort":3000,"port":3000,"type":"ClusterIP"}` | Configure the Sourcebot Kubernetes service. | +| service.annotations | object | `{}` | Service annotations. | +| service.containerPort | int | `3000` | Internal container port. | +| service.port | int | `3000` | External service port. | +| service.type | string | `"ClusterIP"` | Type of the Kubernetes service (e.g., ClusterIP, NodePort, LoadBalancer). | +| serviceAccount | object | `{"annotations":{},"automount":false,"create":true,"name":""}` | Configure the ServiceAccount. | +| serviceAccount.annotations | object | `{}` | Add annotations to the ServiceAccount. | +| serviceAccount.automount | bool | `false` | Enable or disable automatic ServiceAccount mounting. | +| serviceAccount.create | bool | `true` | Create a new ServiceAccount. | +| serviceAccount.name | string | `""` | Use an existing ServiceAccount (if set). | +| startupProbe | object | `{"failureThreshold":30,"httpGet":{"path":"/","port":"http"},"periodSeconds":30}` | Startup probe to check if the container has started successfully. | +| startupProbe.failureThreshold | int | `30` | Number of seconds to wait before starting the probe. | +| startupProbe.httpGet | object | `{"path":"/","port":"http"}` | Http GET request to check if the container has started. | +| startupProbe.httpGet.path | string | `"/"` | Path to check. | +| startupProbe.httpGet.port | string | `"http"` | Port to check. | +| startupProbe.periodSeconds | int | `30` | Initial delay before the first probe. | +| tolerations | list | `[]` | Set tolerations for pod scheduling. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | +| volumeMounts | list | `[]` | Define volume mounts for the container. | +| volumes | list | `[]` | Define additional volumes. | + diff --git a/kubernetes/chart/templates/NOTES.txt b/kubernetes/chart/templates/NOTES.txt new file mode 100644 index 000000000..2adfa79c2 --- /dev/null +++ b/kubernetes/chart/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if $.Values.ingress.enabled }} +{{- range $host := $.Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" $.Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ $.Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "sourcebot.fullname" $ }}) + export NODE_IP=$(kubectl get nodes --namespace {{ $.Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" $.Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch its status by running 'kubectl get --namespace {{ $.Release.Namespace }} svc -w {{ include "sourcebot.fullname" $ }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ $.Release.Namespace }} {{ include "sourcebot.fullname" $ }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ $.Values.service.port }} +{{- else if contains "ClusterIP" $.Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ $.Release.Namespace }} -l "app.kubernetes.io/name={{ include "sourcebot.name" $ }},app.kubernetes.io/instance={{ $.Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ $.Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:3000 to use Sourcebot after forwarding" + kubectl --namespace {{ $.Release.Namespace }} port-forward $POD_NAME 3000:$CONTAINER_PORT +{{- end }} diff --git a/kubernetes/chart/templates/_helpers.tpl b/kubernetes/chart/templates/_helpers.tpl new file mode 100644 index 000000000..7ff85c01a --- /dev/null +++ b/kubernetes/chart/templates/_helpers.tpl @@ -0,0 +1,78 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "sourcebot.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 "sourcebot.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 "sourcebot.chart" -}} +{{- printf "%s-%s" $.Chart.Name $.Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "sourcebot.labels" -}} +helm.sh/chart: {{ include "sourcebot.chart" $ }} +{{ include "sourcebot.selectorLabels" $ }} +{{- if $.Chart.AppVersion }} +app.kubernetes.io/version: {{ $.Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ $.Release.Service }} +{{- with $.Values.additionalLabels }} +{{ toYaml . }} +{{- end }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "sourcebot.selectorLabels" -}} +app.kubernetes.io/name: {{ include "sourcebot.name" $ }} +app.kubernetes.io/instance: {{ $.Release.Name }} +{{- end }} + +{{/* +Create the image to use for the container. +*/}} +{{- define "sourcebot.image" -}} +{{- if $.Values.image.digest -}} +"{{ $.Values.image.repository }}@{{ $.Values.image.digest }}" +{{- else if $.Values.image.tag -}} +"{{ $.Values.image.repository }}:{{ $.Values.image.tag }}" +{{- else -}} +"{{ $.Values.image.repository }}:{{ $.Chart.AppVersion }}" +{{- end -}} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "sourcebot.serviceAccountName" -}} +{{- if $.Values.serviceAccount.create }} +{{- default (include "sourcebot.fullname" $) $.Values.serviceAccount.name }} +{{- else }} +{{- default "default" $.Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/kubernetes/chart/templates/config.yaml b/kubernetes/chart/templates/config.yaml new file mode 100644 index 000000000..43cbf16e6 --- /dev/null +++ b/kubernetes/chart/templates/config.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} +data: + config.json: | + {{- toJson $.Values.config | nindent 4 }} diff --git a/kubernetes/chart/templates/deployment.yaml b/kubernetes/chart/templates/deployment.yaml new file mode 100644 index 000000000..584f1fa73 --- /dev/null +++ b/kubernetes/chart/templates/deployment.yaml @@ -0,0 +1,136 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} +spec: + {{- if not $.Values.autoscaling.enabled }} + replicas: {{ $.Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "sourcebot.selectorLabels" $ | nindent 6 }} + template: + metadata: + {{- with $.Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "sourcebot.labels" $ | nindent 8 }} + {{- with $.Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with $.Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "sourcebot.serviceAccountName" $ }} + {{- with $.Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with $.Values.containerSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ include "sourcebot.image" $ }} + imagePullPolicy: {{ $.Values.image.pullPolicy }} + {{- with $.Values.command }} + command: {{ toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.args }} + args: {{ toYaml . | nindent 12 }} + {{- end }} + env: + - name: CONFIG_PATH + value: /etc/sourcebot/config.json + {{- if $.Values.license }} + - name: SOURCEBOT_EE_LICENSE_KEY + valueFrom: + secretKeyRef: + name: {{ $.Values.license.secretName }} + key: {{ $.Values.license.secretKey }} + {{- end }} + {{- if $.Values.database }} + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: {{ $.Values.database.secretName }} + key: {{ $.Values.database.secretKey }} + {{- end }} + {{- if $.Values.redis }} + - name: REDIS_URL + valueFrom: + secretKeyRef: + name: {{ $.Values.redis.secretName }} + key: {{ $.Values.redis.secretKey }} + {{- end }} + {{- range $.Values.envSecrets }} + - name: {{ .envName }} + valueFrom: + secretKeyRef: + name: {{ .secretName }} + key: {{ .secretKey }} + {{- end }} + {{- with $.Values.envs }} + {{- toYaml . | nindent 12 }} + {{- end }} + ports: + - name: http + containerPort: {{ $.Values.service.containerPort }} + protocol: TCP + {{- with $.Values.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.startupProbe }} + startupProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: sourcebot-config + mountPath: /etc/sourcebot/config.json + subPath: config.json + readOnly: true + {{- with $.Values.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with $.Values.priorityClassName }} + priorityClassName: {{ . }} + {{- end }} + volumes: + - name: sourcebot-config + configMap: + name: {{ include "sourcebot.fullname" $ }} + items: + - key: config.json + path: config.json + {{- with $.Values.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- 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/kubernetes/chart/templates/hpa.yaml b/kubernetes/chart/templates/hpa.yaml new file mode 100644 index 000000000..8079dc75b --- /dev/null +++ b/kubernetes/chart/templates/hpa.yaml @@ -0,0 +1,33 @@ +{{- if $.Values.autoscaling.enabled }} +--- +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "sourcebot.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/kubernetes/chart/templates/ingress.yaml b/kubernetes/chart/templates/ingress.yaml new file mode 100644 index 000000000..e0f563e78 --- /dev/null +++ b/kubernetes/chart/templates/ingress.yaml @@ -0,0 +1,44 @@ +{{- if $.Values.ingress.enabled -}} +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} + {{- with $.Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with $.Values.ingress.className }} + ingressClassName: {{ . }} + {{- 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 }} + {{- with .pathType }} + pathType: {{ . }} + {{- end }} + backend: + service: + name: {{ include "sourcebot.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} diff --git a/kubernetes/chart/templates/pdb.yaml b/kubernetes/chart/templates/pdb.yaml new file mode 100644 index 000000000..307b98f7a --- /dev/null +++ b/kubernetes/chart/templates/pdb.yaml @@ -0,0 +1,18 @@ +{{- if and $.Values.podDisruptionBudget.enabled (gt (int $.Values.replicaCount) 1) }} +apiVersion: {{ include "common.capabilities.policy.apiVersion" . }} +kind: PodDisruptionBudget +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} +spec: + {{- if $.Values.podDisruptionBudget.minAvailable }} + minAvailable: {{ $.Values.podDisruptionBudget.minAvailable }} + {{- end }} + {{- if $.Values.podDisruptionBudget.maxUnavailable }} + maxUnavailable: {{ $.Values.podDisruptionBudget.maxUnavailable }} + {{- end }} + selector: + matchLabels: + {{- include "sourcebot.selectorLabels" $ | nindent 6 }} +{{- end }} diff --git a/kubernetes/chart/templates/service.yaml b/kubernetes/chart/templates/service.yaml new file mode 100644 index 000000000..8c9c5bb0d --- /dev/null +++ b/kubernetes/chart/templates/service.yaml @@ -0,0 +1,16 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "sourcebot.fullname" $ }} + labels: + {{- include "sourcebot.labels" $ | nindent 4 }} +spec: + type: {{ $.Values.service.type }} + ports: + - port: {{ $.Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "sourcebot.selectorLabels" $ | nindent 4 }} diff --git a/kubernetes/chart/templates/serviceaccount.yaml b/kubernetes/chart/templates/serviceaccount.yaml new file mode 100644 index 000000000..fcf0a219b --- /dev/null +++ b/kubernetes/chart/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if $.Values.serviceAccount.create -}} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "sourcebot.serviceAccountName" . }} + labels: + {{- include "sourcebot.labels" . | nindent 4 }} + {{- with $.Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ $.Values.serviceAccount.automount }} +{{- end }} diff --git a/kubernetes/chart/values.schema.json b/kubernetes/chart/values.schema.json new file mode 100644 index 000000000..3a8b10cf7 --- /dev/null +++ b/kubernetes/chart/values.schema.json @@ -0,0 +1,469 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Sourcebot Helm Chart Values Schema", + "additionalProperties": false, + "type": "object", + "properties": { + "nameOverride": { + "type": "string" + }, + "fullnameOverride": { + "type": "string" + }, + "replicaCount": { + "type": "integer", + "minimum": 1 + }, + "image": { + "type": "object", + "properties": { + "repository": { + "type": "string" + }, + "tag": { + "type": "string" + }, + "digest": { + "type": "string" + }, + "pullPolicy": { + "type": "string", + "enum": [ + "Always", + "IfNotPresent", + "Never" + ] + } + }, + "required": [ + "repository" + ] + }, + "imagePullSecrets": { + "type": "array", + "items": { + "type": "string" + } + }, + "command": { + "type": "array", + "items": { + "type": "string" + } + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + }, + "database": { + "type": "object" + }, + "redis": { + "type": "object" + }, + "license": { + "type": "object" + }, + "envSecrets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "secretKey": { + "type": "string" + }, + "envName": { + "type": "string" + } + }, + "required": [ + "secretName", + "secretKey", + "envName" + ] + } + }, + "envs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "name", + "value" + ] + } + }, + "config": { + "type": "object", + "properties": { + "connections": { + "type": "object" + }, + "settings": { + "type": "object" + } + } + }, + "serviceAccount": { + "type": "object", + "properties": { + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "annotations": { + "type": "object" + }, + "automount": { + "type": "boolean" + } + } + }, + "podSecurityContext": { + "type": "object", + "properties": { + "runAsUser": { + "type": "integer" + }, + "runAsGroup": { + "type": "integer" + }, + "runAsNonRoot": { + "type": "boolean" + }, + "fsGroup": { + "type": "integer" + } + } + }, + "containerSecurityContext": { + "type": "object", + "properties": { + "allowPrivilegeEscalation": { + "type": "boolean" + }, + "privileged": { + "type": "boolean" + }, + "readOnlyRootFilesystem": { + "type": "boolean" + }, + "runAsUser": { + "type": "integer" + }, + "runAsGroup": { + "type": "integer" + }, + "capabilities": { + "type": "object", + "properties": { + "drop": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "seccompProfile": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "RuntimeDefault", + "Unconfined", + "Localhost" + ] + } + } + } + } + }, + "service": { + "type": "object", + "properties": { + "type": { + "type": "string", + "enum": [ + "ClusterIP", + "NodePort", + "LoadBalancer", + "ExternalName" + ] + }, + "containerPort": { + "type": "integer" + }, + "port": { + "type": "integer" + }, + "annotations": { + "type": "object" + } + } + }, + "ingress": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "className": { + "type": "string" + }, + "annotations": { + "type": "object" + }, + "hosts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "host": { + "type": "string" + }, + "paths": { + "type": "array", + "items": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "pathType": { + "type": "string", + "enum": [ + "ImplementationSpecific", + "Exact", + "Prefix" + ] + } + } + } + } + } + }, + "tls": { + "type": "object", + "properties": { + "secretName": { + "type": "string" + }, + "hosts": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "secretName", + "hosts" + ] + } + } + } + }, + "initContainers": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "string" + }, + "args": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "resources": { + "type": "object", + "properties": { + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + }, + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "string" + }, + "memory": { + "type": "string" + } + } + } + } + }, + "livenessProbe": { + "$ref": "#/definitions/probe" + }, + "readinessProbe": { + "$ref": "#/definitions/probe" + }, + "startupProbe": { + "$ref": "#/definitions/probe" + }, + "autoscaling": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "minReplicas": { + "type": "integer" + }, + "maxReplicas": { + "type": "integer" + }, + "targetCPUUtilizationPercentage": { + "type": "integer" + }, + "targetMemoryUtilizationPercentage": { + "type": "integer" + } + } + }, + "volumes": { + "type": "array", + "items": { + "type": "object" + } + }, + "volumeMounts": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "mountPath": { + "type": "string" + }, + "readOnly": { + "type": "boolean" + } + } + } + }, + "podDisruptionBudget": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "minAvailable": { + "type": [ + "integer", + "string" + ] + }, + "maxUnavailable": { + "type": [ + "integer", + "string" + ] + } + } + }, + "podAnnotations": { + "type": "object" + }, + "additionalLabels": { + "type": "object" + }, + "nodeSelector": { + "type": "object" + }, + "tolerations": { + "type": "array", + "items": { + "type": "object" + } + }, + "affinity": { + "type": "object" + }, + "priorityClassName": { + "type": "string" + } + }, + "definitions": { + "probe": { + "type": "object", + "properties": { + "httpGet": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "port": { + "type": [ + "string", + "integer" + ] + } + }, + "required": [ + "path", + "port" + ] + }, + "initialDelaySeconds": { + "type": "integer", + "minimum": 0 + }, + "periodSeconds": { + "type": "integer", + "minimum": 1 + }, + "timeoutSeconds": { + "type": "integer", + "minimum": 1 + }, + "successThreshold": { + "type": "integer", + "minimum": 1 + }, + "failureThreshold": { + "type": "integer", + "minimum": 1 + } + } + } + } +} \ No newline at end of file diff --git a/kubernetes/chart/values.yaml b/kubernetes/chart/values.yaml new file mode 100644 index 000000000..f9cb63af8 --- /dev/null +++ b/kubernetes/chart/values.yaml @@ -0,0 +1,265 @@ +# -- Sourcebot Helm Chart Values + +# -- Override the name of the chart. +nameOverride: "" + +# -- Override the full name of the chart. +fullnameOverride: "" + +# -- Set the number of replicas for the deployment. +replicaCount: 1 + +# -- Configure the container image. +image: + # -- Container image repository. + repository: ghcr.io/sourcebot-dev/sourcebot + # -- Container image tag. + tag: latest + # -- Container image digest (used instead of tag if set). + # digest: "" + # -- Image pull policy. + pullPolicy: Always + +# -- Configure image pull secrets for private registries. +imagePullSecrets: [] + +# -- Override the default command of the container. +command: [] + +# -- Override the default arguments of the container. +args: [] + +# -- Configure the database secret. +database: {} +# secretName: sourcebot-database-url +# secretKey: url + +# -- Configure the Redis secret. +redis: {} +# secretName: sourcebot-redis-url +# secretKey: url + +# -- Configure the enterprise license key secret. +license: {} +# secretName: sourcebot-ee-license-key +# secretKey: key + +# -- Set environment variables from Kubernetes secrets. +envSecrets: [] +# - secretName: sourcebot-github-token +# secretKey: token +# envName: GITHUB_TOKEN + +# -- Set additional environment variables. +envs: [] +# - name: FOO +# value: bar + +# -- Configure Sourcebot-specific application settings. +config: + # Schema version of the Sourcebot configuration. + $schema: https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json + connections: {} + # github-repos: + # type: github + # token: + # env: GITHUB_TOKEN + # repos: + # - sourcebot/sourcebot + # - sourcebot/sourcebot-plugins + settings: {} + # reindexIntervalMs: 86400000 + # enablePublicAccess: true + +# -- Configure the ServiceAccount. +serviceAccount: + # -- Create a new ServiceAccount. + create: true + # -- Use an existing ServiceAccount (if set). + name: "" + # -- Add annotations to the ServiceAccount. + annotations: {} + # -- Enable or disable automatic ServiceAccount mounting. + automount: false + +# -- Set the pod-level security context. +podSecurityContext: {} +# runAsUser: 1000 +# runAsGroup: 1000 +# runAsNonRoot: true +# fsGroup: 1000 + +# -- Set the container-level security context. +containerSecurityContext: {} +# allowPrivilegeEscalation: false +# privileged: false +# readOnlyRootFilesystem: true +# runAsUser: 1000 +# runAsGroup: 1000 +# capabilities: +# drop: +# - ALL +# seccompProfile: +# type: RuntimeDefault + +# -- Configure the Sourcebot Kubernetes service. +service: + # -- Type of the Kubernetes service (e.g., ClusterIP, NodePort, LoadBalancer). + type: ClusterIP + # -- Internal container port. + containerPort: 3000 + # -- External service port. + port: 3000 + # -- Service annotations. + annotations: {} + +# -- Configure ingress for Sourcebot. +ingress: + # -- Enable or disable ingress. + enabled: false + # -- Ingress class name. + className: "" + # -- Ingress annotations. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + # -- List of hostnames and paths for ingress rules. + hosts: [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific + + # -- TLS settings for ingress. + tls: [] + # - hosts: + # - chart-example.local + # secretName: chart-example-tls + +# -- Configure init containers to run before the main container. +initContainers: [] +# - name: sleeper +# image: busybox +# args: +# - sleep +# - "10" + +# -- Configure resource requests and limits for the container. +resources: {} +## It is recommended to set resources explicitly in production environments. +# limits: +# cpu: 100m +# memory: 128Mi +# requests: +# cpu: 100m +# memory: 128Mi + +# -- Liveness probe to check if the container is alive. +livenessProbe: + # -- Http GET request to check if the container is alive. + httpGet: + # -- Path to check. + path: / + # -- Port to check. + port: http + # -- Initial delay before the first probe. + initialDelaySeconds: 10 + # -- Frequency of the probe. + periodSeconds: 10 + # -- Number of consecutive failures before marking the container as unhealthy. + failureThreshold: 5 + +# -- Readiness probe to check if the container is ready to serve traffic. +readinessProbe: + # -- Http GET request to check if the container is ready. + httpGet: + # -- Path to check. + path: / + # -- Port to check. + port: http + # -- Initial delay before the first probe. + initialDelaySeconds: 10 + # -- Frequency of the probe. + periodSeconds: 10 + # -- Number of consecutive failures before marking the container as not ready. + failureThreshold: 5 + +# -- Startup probe to check if the container has started successfully. +startupProbe: + # -- Http GET request to check if the container has started. + httpGet: + # -- Path to check. + path: / + # -- Port to check. + port: http + # -- Number of seconds to wait before starting the probe. + failureThreshold: 30 + # -- Initial delay before the first probe. + periodSeconds: 30 + +# -- Configure Horizontal Pod Autoscaler. +autoscaling: + # -- Enable or disable Horizontal Pod Autoscaler. + enabled: false + # -- Minimum number of replicas. + minReplicas: 1 + # -- Maximum number of replicas. + maxReplicas: 3 + # -- Target CPU utilization percentage for autoscaling. + targetCPUUtilizationPercentage: 80 + # -- Target memory utilization percentage for autoscaling. + targetMemoryUtilizationPercentage: 80 + +# -- Define additional volumes. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# -- Define volume mounts for the container. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +# -- Configure Pod Disruption Budget. +podDisruptionBudget: + # -- Enable Pod Disruption Budget. + enabled: true + # -- Minimum number of pods that must be available. + minAvailable: 1 + # -- Maximum number of pods that can be unavailable. + maxUnavailable: 1 + +# -- Add annotations to the pod metadata. +podAnnotations: {} +# prometheus.io/scrape: "true" +# prometheus.io/path: "/metrics" +# prometheus.io/port: "9102" + +# -- Add extra labels to all resources. +additionalLabels: {} +# team: sourcebot + +# -- Set node selector constraints. +# See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector +nodeSelector: {} + +# -- Set tolerations for pod scheduling. +# See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ +tolerations: [] +# - effect: NoSchedule +# key: "key" +# operator: Equal +# value: "value" + +# -- Set affinity rules for pod scheduling. +# Defaults to soft anti-affinity if not set. +# See: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ +affinity: {} + +# -- Set the priority class name for pods. +# See: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ +priorityClassName: "" From 198cdf3e09c8644cb7ca29a238c072aff725061b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Nogueira?= Date: Sat, 19 Jul 2025 19:52:22 +0100 Subject: [PATCH 2/2] feat: add sts support to use internal DB and improve values docs Signed-off-by: Andre Nogueira --- kubernetes/chart/Chart.yaml | 2 +- kubernetes/chart/README.md | 22 ++++++++------- .../{deployment.yaml => deloyable.yaml} | 23 ++++++++++++++++ kubernetes/chart/values.schema.json | 27 +++++++++++++++++++ kubernetes/chart/values.yaml | 24 +++++++++++++---- 5 files changed, 83 insertions(+), 15 deletions(-) rename kubernetes/chart/templates/{deployment.yaml => deloyable.yaml} (87%) diff --git a/kubernetes/chart/Chart.yaml b/kubernetes/chart/Chart.yaml index 67362bf61..ab7ff2b2d 100644 --- a/kubernetes/chart/Chart.yaml +++ b/kubernetes/chart/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 type: application name: sourcebot version: 0.1.0 -appVersion: "" +appVersion: v4.5.1 description: The open source Sourcegraph alternative. Sourcebot gives you a powerful interface to search though all your repos and branches across multiple code hosts. icon: https://raw.githubusercontent.com/sourcebot-dev/sourcebot/ebf6721836b8f878d42bb8c1e844bdc7867a74fe/packages/web/public/logo_512.png keywords: diff --git a/kubernetes/chart/README.md b/kubernetes/chart/README.md index 47861d5b7..3fccf22de 100644 --- a/kubernetes/chart/README.md +++ b/kubernetes/chart/README.md @@ -1,6 +1,6 @@ # sourcebot -![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v4.5.1](https://img.shields.io/badge/AppVersion-v4.5.1-informational?style=flat-square) The open source Sourcegraph alternative. Sourcebot gives you a powerful interface to search though all your repos and branches across multiple code hosts. @@ -27,14 +27,13 @@ The open source Sourcegraph alternative. Sourcebot gives you a powerful interfac | command | list | `[]` | Override the default command of the container. | | config | object | `{"$schema":"https://raw.githubusercontent.com/sourcebot-dev/sourcebot/main/schemas/v3/index.json","connections":{},"settings":{}}` | Configure Sourcebot-specific application settings. | | containerSecurityContext | object | `{}` | Set the container-level security context. | -| database | object | `{}` | Configure the database secret. | +| database | object | `{}` | Configure the database secret by providing database.secretName and database.secretKey to use a Kubernetes secret. | | envSecrets | list | `[]` | Set environment variables from Kubernetes secrets. | | envs | list | `[]` | Set additional environment variables. | | fullnameOverride | string | `""` | Override the full name of the chart. | -| image | object | `{"pullPolicy":"Always","repository":"ghcr.io/sourcebot-dev/sourcebot","tag":"latest"}` | Configure the container image. | -| image.pullPolicy | string | `"Always"` | Image pull policy. | +| image | object | `{"pullPolicy":"IfNotPresent","repository":"ghcr.io/sourcebot-dev/sourcebot"}` | Configure the container image. | +| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy. | | image.repository | string | `"ghcr.io/sourcebot-dev/sourcebot"` | Container image repository. | -| image.tag | string | `"latest"` | Container image tag. | | imagePullSecrets | list | `[]` | Configure image pull secrets for private registries. | | ingress | object | `{"annotations":{},"className":"","enabled":false,"hosts":[],"tls":[]}` | Configure ingress for Sourcebot. | | ingress.annotations | object | `{}` | Ingress annotations. | @@ -43,7 +42,7 @@ The open source Sourcegraph alternative. Sourcebot gives you a powerful interfac | ingress.hosts | list | `[]` | List of hostnames and paths for ingress rules. | | ingress.tls | list | `[]` | TLS settings for ingress. | | initContainers | list | `[]` | Configure init containers to run before the main container. | -| license | object | `{}` | Configure the enterprise license key secret. | +| license | object | `{}` | Configure the enterprise license key secret by providing license.secretName and license.secretKey to use a Kubernetes secret. | | livenessProbe | object | `{"failureThreshold":5,"httpGet":{"path":"/","port":"http"},"initialDelaySeconds":10,"periodSeconds":10}` | Liveness probe to check if the container is alive. | | livenessProbe.failureThreshold | int | `5` | Number of consecutive failures before marking the container as unhealthy. | | livenessProbe.httpGet | object | `{"path":"/","port":"http"}` | Http GET request to check if the container is alive. | @@ -67,7 +66,7 @@ The open source Sourcegraph alternative. Sourcebot gives you a powerful interfac | readinessProbe.httpGet.port | string | `"http"` | Port to check. | | readinessProbe.initialDelaySeconds | int | `10` | Initial delay before the first probe. | | readinessProbe.periodSeconds | int | `10` | Frequency of the probe. | -| redis | object | `{}` | Configure the Redis secret. | +| redis | object | `{}` | Configure the Redis secret by providing redis.secretName and redis.secretKey to use a Kubernetes secret. | | replicaCount | int | `1` | Set the number of replicas for the deployment. | | resources | object | `{}` | Configure resource requests and limits for the container. | | service | object | `{"annotations":{},"containerPort":3000,"port":3000,"type":"ClusterIP"}` | Configure the Sourcebot Kubernetes service. | @@ -86,7 +85,12 @@ The open source Sourcegraph alternative. Sourcebot gives you a powerful interfac | startupProbe.httpGet.path | string | `"/"` | Path to check. | | startupProbe.httpGet.port | string | `"http"` | Port to check. | | startupProbe.periodSeconds | int | `30` | Initial delay before the first probe. | +| storage | object | `{"accessModes":["ReadWriteOnce"],"className":"","enabled":true,"size":"10Gi"}` | Configure persistent storage for the application (volume is mounted at /data) to use the internal database. | +| storage.accessModes | list | `["ReadWriteOnce"]` | Access modes for the persistent volume. | +| storage.className | string | `""` | Storage class name for the persistent volume. | +| storage.enabled | bool | `true` | Enable or disable persistent storage. | +| storage.size | string | `"10Gi"` | Size of the persistent volume. | | tolerations | list | `[]` | Set tolerations for pod scheduling. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ | -| volumeMounts | list | `[]` | Define volume mounts for the container. | -| volumes | list | `[]` | Define additional volumes. | +| volumeMounts | list | `[]` | Define volume mounts for the container. See: https://kubernetes.io/docs/concepts/storage/volumes/ | +| volumes | list | `[]` | Define additional volumes. See: https://kubernetes.io/docs/concepts/storage/volumes/ | diff --git a/kubernetes/chart/templates/deployment.yaml b/kubernetes/chart/templates/deloyable.yaml similarity index 87% rename from kubernetes/chart/templates/deployment.yaml rename to kubernetes/chart/templates/deloyable.yaml index 584f1fa73..744ef0e15 100644 --- a/kubernetes/chart/templates/deployment.yaml +++ b/kubernetes/chart/templates/deloyable.yaml @@ -1,11 +1,18 @@ --- apiVersion: apps/v1 +{{- if $.Values.storage }} +kind: StatefulSet +{{- else }} kind: Deployment +{{- end }} metadata: name: {{ include "sourcebot.fullname" $ }} labels: {{- include "sourcebot.labels" $ | nindent 4 }} spec: + {{- if $.Values.storage }} + serviceName: {{ include "sourcebot.fullname" $ }} + {{- end }} {{- if not $.Values.autoscaling.enabled }} replicas: {{ $.Values.replicaCount }} {{- end }} @@ -106,6 +113,10 @@ spec: mountPath: /etc/sourcebot/config.json subPath: config.json readOnly: true + {{- if $.Values.storage }} + - name: sourcebot-data + mountPath: /data + {{- end }} {{- with $.Values.volumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} @@ -134,3 +145,15 @@ spec: tolerations: {{- toYaml . | nindent 8 }} {{- end }} + {{- if $.Values.storage }} + volumeClaimTemplates: + - metadata: + name: sourcebot-data + spec: + accessModes: + {{- $.Values.storage.accessModes | toYaml | nindent 10 }} + storageClassName: {{ $.Values.storage.className }} + resources: + requests: + storage: {{ $.Values.storage.size }} + {{- end }} diff --git a/kubernetes/chart/values.schema.json b/kubernetes/chart/values.schema.json index 3a8b10cf7..01fddfb37 100644 --- a/kubernetes/chart/values.schema.json +++ b/kubernetes/chart/values.schema.json @@ -419,6 +419,33 @@ }, "priorityClassName": { "type": "string" + }, + "storage": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+Gi$" + }, + "accessModes": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ReadWriteOnce", + "ReadOnlyMany", + "ReadWriteMany" + ] + }, + "minItems": 1 + }, + "className": { + "type": "string" + } + } } }, "definitions": { diff --git a/kubernetes/chart/values.yaml b/kubernetes/chart/values.yaml index f9cb63af8..67cbc2451 100644 --- a/kubernetes/chart/values.yaml +++ b/kubernetes/chart/values.yaml @@ -14,11 +14,11 @@ image: # -- Container image repository. repository: ghcr.io/sourcebot-dev/sourcebot # -- Container image tag. - tag: latest + # tag: "" # -- Container image digest (used instead of tag if set). # digest: "" # -- Image pull policy. - pullPolicy: Always + pullPolicy: IfNotPresent # -- Configure image pull secrets for private registries. imagePullSecrets: [] @@ -29,17 +29,17 @@ command: [] # -- Override the default arguments of the container. args: [] -# -- Configure the database secret. +# -- Configure the database secret by providing database.secretName and database.secretKey to use a Kubernetes secret. database: {} # secretName: sourcebot-database-url # secretKey: url -# -- Configure the Redis secret. +# -- Configure the Redis secret by providing redis.secretName and redis.secretKey to use a Kubernetes secret. redis: {} # secretName: sourcebot-redis-url # secretKey: url -# -- Configure the enterprise license key secret. +# -- Configure the enterprise license key secret by providing license.secretName and license.secretKey to use a Kubernetes secret. license: {} # secretName: sourcebot-ee-license-key # secretKey: key @@ -212,6 +212,7 @@ autoscaling: targetMemoryUtilizationPercentage: 80 # -- Define additional volumes. +# See: https://kubernetes.io/docs/concepts/storage/volumes/ volumes: [] # - name: foo # secret: @@ -219,6 +220,7 @@ volumes: [] # optional: false # -- Define volume mounts for the container. +# See: https://kubernetes.io/docs/concepts/storage/volumes/ volumeMounts: [] # - name: foo # mountPath: "/etc/foo" @@ -263,3 +265,15 @@ affinity: {} # -- Set the priority class name for pods. # See: https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/ priorityClassName: "" + +# -- Configure persistent storage for the application (volume is mounted at /data) to use the internal database. +storage: + # -- Enable or disable persistent storage. + enabled: true + # -- Access modes for the persistent volume. + accessModes: + - ReadWriteOnce + # -- Storage class name for the persistent volume. + className: "" + # -- Size of the persistent volume. + size: "10Gi"