Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- `sourcebot.httpRoute` values for exposing Sourcebot through a Gateway API `HTTPRoute`. `AUTH_URL` is now also derived from `sourcebot.httpRoute.hostnames` when ingress is disabled.

### Fixed
- `AUTH_URL` derivation no longer picks a wildcard hostname, which produced an unusable URL.

## [0.1.102] - 2026-08-19

### Changed
Expand Down
5 changes: 5 additions & 0 deletions charts/sourcebot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ Sourcebot is a self-hosted tool that helps you understand your codebase.
| sourcebot.extraVolumeMounts | list | `[]` | Define volume mounts for the container See: https://kubernetes.io/docs/concepts/storage/volumes/ |
| sourcebot.extraVolumes | list | `[]` | Define additional volumes See: https://kubernetes.io/docs/concepts/storage/volumes/ |
| sourcebot.hostAliases | list | `[]` | Set host aliases to inject entries into the pod's /etc/hosts file See: https://kubernetes.io/docs/tasks/network/customize-hosts-file-for-pods/ |
| sourcebot.httpRoute.annotations | object | `{}` | HTTPRoute annotations |
| sourcebot.httpRoute.enabled | bool | `false` | Enable or disable the HTTPRoute. Requires the Gateway API CRDs (`gateway.networking.k8s.io/v1`) to be installed in the cluster. |
| sourcebot.httpRoute.hostnames | list | `[]` | Hostnames to match. When ingress is disabled, the first non-wildcard hostname is used to derive `AUTH_URL`. If every hostname is a wildcard, set `AUTH_URL` explicitly via `sourcebot.additionalEnv`. |
| sourcebot.httpRoute.parentRefs | list | `[]` | Gateways to attach this route to. Required when the HTTPRoute is enabled. |
| sourcebot.httpRoute.rules | list | `[]` | Routing rules. When empty, a single rule forwarding all traffic to the Sourcebot service is generated. |
| sourcebot.image.digest | string | `""` | Container image digest (used instead of tag if set) |
| sourcebot.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
| sourcebot.image.pullSecrets | list | `[]` | Configure image pull secrets for private registries |
Expand Down
22 changes: 22 additions & 0 deletions charts/sourcebot/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,28 @@ Return Redis hostname
{{- end }}
{{- end }}

{{/*
Return the public URL Sourcebot is served on, used for AUTH_URL.
Derived from the first ingress host, or from the first non-wildcard HTTPRoute
hostname when ingress is disabled. Wildcard hostnames are skipped because they
are not a usable URL. Returns an empty string when no host can be determined.
*/}}
{{- define "sourcebot.authUrl" -}}
{{- if and .Values.sourcebot.ingress.enabled (gt (len .Values.sourcebot.ingress.hosts) 0) -}}
{{- printf "https://%s" (index .Values.sourcebot.ingress.hosts 0).host -}}
{{- else if .Values.sourcebot.httpRoute.enabled -}}
{{- $hostnames := list -}}
{{- range .Values.sourcebot.httpRoute.hostnames -}}
{{- if not (hasPrefix "*" .) -}}
{{- $hostnames = append $hostnames . -}}
{{- end -}}
{{- end -}}
{{- with $hostnames -}}
{{- printf "https://%s" (first .) -}}
{{- end -}}
{{- end -}}
{{- end }}

{{/*
Helper to get value or secret reference
Returns either a direct value or a valueFrom secretKeyRef
Expand Down
4 changes: 2 additions & 2 deletions charts/sourcebot/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ spec:
{{- toYaml . | nindent 12 }}
{{- end }}
env:
{{- if and $.Values.sourcebot.ingress.enabled (gt (len $.Values.sourcebot.ingress.hosts) 0) }}
{{- with (include "sourcebot.authUrl" $) }}
- name: AUTH_URL
value: {{ (index $.Values.sourcebot.ingress.hosts 0).host | printf "https://%s" }}
value: {{ . }}
{{- end }}
- name: CONFIG_PATH
value: /etc/sourcebot/config.json
Expand Down
38 changes: 38 additions & 0 deletions charts/sourcebot/templates/httproute.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{{- if $.Values.sourcebot.httpRoute.enabled -}}
{{- if not $.Values.sourcebot.httpRoute.parentRefs -}}
{{- fail "sourcebot.httpRoute.parentRefs is required when sourcebot.httpRoute.enabled is true. An HTTPRoute without parentRefs is not attached to any Gateway and silently receives no traffic." -}}
{{- end -}}
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: {{ include "sourcebot.fullname" $ }}
namespace: {{ $.Release.Namespace }}
labels:
{{- include "sourcebot.labels" $ | nindent 4 }}
{{- with $.Values.sourcebot.httpRoute.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with $.Values.sourcebot.httpRoute.parentRefs }}
parentRefs:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with $.Values.sourcebot.httpRoute.hostnames }}
hostnames:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
{{- with $.Values.sourcebot.httpRoute.rules }}
{{- toYaml . | nindent 4 }}
{{- else }}
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: {{ include "sourcebot.fullname" $ }}
port: {{ $.Values.sourcebot.service.port }}
{{- end }}
{{- end }}
214 changes: 214 additions & 0 deletions charts/sourcebot/tests/httproute_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
suite: test Gateway API HTTPRoute
templates:
- httproute.yaml
- deployment.yaml
- config.yaml
tests:
- it: should not render an HTTPRoute by default
values:
- ../values.lint.yaml
asserts:
- hasDocuments:
count: 0
template: httproute.yaml

- it: should render an HTTPRoute when enabled
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
namespace: gateway-system
sectionName: https
sourcebot.httpRoute.hostnames:
- chart-example.local
asserts:
- hasDocuments:
count: 1
template: httproute.yaml
- isKind:
of: HTTPRoute
template: httproute.yaml
- isAPIVersion:
of: gateway.networking.k8s.io/v1
template: httproute.yaml
- equal:
path: spec.parentRefs[0]
value:
name: my-gateway
namespace: gateway-system
sectionName: https
template: httproute.yaml
- equal:
path: spec.hostnames[0]
value: chart-example.local
template: httproute.yaml

- it: should generate a default rule pointing at the Sourcebot service
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
asserts:
- lengthEqual:
path: spec.rules
count: 1
template: httproute.yaml
- equal:
path: spec.rules[0].matches[0].path
value:
type: PathPrefix
value: /
template: httproute.yaml
- equal:
path: spec.rules[0].backendRefs[0]
value:
name: RELEASE-NAME-sourcebot
port: 3000
template: httproute.yaml

- it: should use custom rules when provided
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: custom-backend
port: 8080
asserts:
- lengthEqual:
path: spec.rules
count: 1
template: httproute.yaml
- equal:
path: spec.rules[0].backendRefs[0].name
value: custom-backend
template: httproute.yaml

- it: should set HTTPRoute annotations
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.annotations:
custom.io/annotation: my-value
asserts:
- equal:
path: metadata.annotations["custom.io/annotation"]
value: my-value
template: httproute.yaml

- it: should fail when enabled without parentRefs
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
asserts:
- failedTemplate:
errorMessage: sourcebot.httpRoute.parentRefs is required when sourcebot.httpRoute.enabled is true. An HTTPRoute without parentRefs is not attached to any Gateway and silently receives no traffic.
template: httproute.yaml

- it: should derive AUTH_URL from the HTTPRoute hostname when ingress is disabled
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.hostnames:
- chart-example.local
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
value: https://chart-example.local
count: 1
template: deployment.yaml

- it: should skip wildcard hostnames when deriving AUTH_URL
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.hostnames:
- "*.chart-example.local"
- sourcebot.chart-example.local
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
value: https://sourcebot.chart-example.local
count: 1
template: deployment.yaml

- it: should not set AUTH_URL when every hostname is a wildcard
values:
- ../values.lint.yaml
set:
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.hostnames:
- "*.chart-example.local"
asserts:
- notContains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
template: deployment.yaml

- it: should prefer the ingress host for AUTH_URL when both are enabled
values:
- ../values.lint.yaml
set:
sourcebot.ingress.enabled: true
sourcebot.ingress.hosts:
- host: ingress.chart-example.local
paths:
- path: /
pathType: Prefix
sourcebot.httpRoute.enabled: true
sourcebot.httpRoute.parentRefs:
- name: my-gateway
sourcebot.httpRoute.hostnames:
- route.chart-example.local
asserts:
- contains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
value: https://ingress.chart-example.local
count: 1
template: deployment.yaml
- notContains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
value: https://route.chart-example.local
template: deployment.yaml

- it: should not set AUTH_URL when neither ingress nor httpRoute is enabled
values:
- ../values.lint.yaml
asserts:
- notContains:
path: spec.template.spec.containers[0].env
content:
name: AUTH_URL
template: deployment.yaml
19 changes: 19 additions & 0 deletions charts/sourcebot/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@
"ingress": {
"type": "object"
},
"httpRoute": {
"type": "object",
"properties": {
"enabled": { "type": "boolean" },
"annotations": { "type": "object" },
"parentRefs": {
"type": "array",
"items": { "type": "object" }
},
"hostnames": {
"type": "array",
"items": { "type": "string" }
},
"rules": {
"type": "array",
"items": { "type": "object" }
}
}
},
"initContainers": {
"type": "array"
},
Expand Down
25 changes: 25 additions & 0 deletions charts/sourcebot/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,31 @@ sourcebot:
# - chart-example.local
# secretName: chart-example-tls

# Gateway API HTTPRoute configuration. TLS is terminated by the Gateway
# listener, so there is no TLS section here.
httpRoute:
# -- Enable or disable the HTTPRoute. Requires the Gateway API CRDs (`gateway.networking.k8s.io/v1`) to be installed in the cluster.
enabled: false
# -- HTTPRoute annotations
annotations: {}
# -- Gateways to attach this route to. Required when the HTTPRoute is enabled.
parentRefs: []
# - name: my-gateway
# namespace: gateway-system
# sectionName: https
# -- Hostnames to match. When ingress is disabled, the first non-wildcard hostname is used to derive `AUTH_URL`. If every hostname is a wildcard, set `AUTH_URL` explicitly via `sourcebot.additionalEnv`.
hostnames: []
# - chart-example.local
# -- Routing rules. When empty, a single rule forwarding all traffic to the Sourcebot service is generated.
rules: []
# - matches:
# - path:
# type: PathPrefix
# value: /
# backendRefs:
# - name: sourcebot
# port: 3000

# -- Configure init containers to run before the main container
initContainers: []
# - name: sleeper
Expand Down