diff --git a/kubernetes/chart/.helmignore b/kubernetes/chart/.helmignore new file mode 100644 index 00000000..0e8a0eb3 --- /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 00000000..67362bf6 --- /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 00000000..47861d5b --- /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 00000000..2adfa79c --- /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 00000000..7ff85c01 --- /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 00000000..43cbf16e --- /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 00000000..584f1fa7 --- /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 00000000..8079dc75 --- /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 00000000..e0f563e7 --- /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 00000000..307b98f7 --- /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 00000000..8c9c5bb0 --- /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 00000000..fcf0a219 --- /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 00000000..3a8b10cf --- /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 00000000..f9cb63af --- /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: ""