diff --git a/.github/linters/.yaml-lint.yml b/.github/linters/.yaml-lint.yml new file mode 100644 index 0000000..e707dce --- /dev/null +++ b/.github/linters/.yaml-lint.yml @@ -0,0 +1,8 @@ +extends: default + +ignore-from-file: [.gitignore, .github/linters/.yamlignore] + +rules: + comments: disable + document-start: disable + line-length: disable diff --git a/.github/linters/.yamlignore b/.github/linters/.yamlignore new file mode 100644 index 0000000..00c3b2d --- /dev/null +++ b/.github/linters/.yamlignore @@ -0,0 +1 @@ +**/templates diff --git a/.github/linters/chart-testing.yaml b/.github/linters/chart-testing.yaml new file mode 100644 index 0000000..92476dc --- /dev/null +++ b/.github/linters/chart-testing.yaml @@ -0,0 +1,8 @@ +chart-dirs: + - . + +chart-repos: + - bitnami=https://charts.bitnami.com/bitnami + +# The default branch name will be 'main' soon +target-branch: main diff --git a/.github/workflows/chart-releaser.yaml b/.github/workflows/chart-releaser.yaml new file mode 100644 index 0000000..699e4b8 --- /dev/null +++ b/.github/workflows/chart-releaser.yaml @@ -0,0 +1,34 @@ +name: Release Charts + +on: # yamllint disable-line rule:truthy + push: + branches: + - main + +jobs: + release: + # depending on default permission settings for your org (contents being read-only or read-write for workloads), you will have to add permissions + # see: https://docs.github.com/en/actions/security-guides/automatic-token-authentication#modifying-the-permissions-for-the-github_token + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Install Helm + uses: azure/setup-helm@v3 + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1.6.0 + with: + charts_dir: . + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/lint-helm-chart.yaml b/.github/workflows/lint-helm-chart.yaml new file mode 100644 index 0000000..9f37824 --- /dev/null +++ b/.github/workflows/lint-helm-chart.yaml @@ -0,0 +1,80 @@ +name: Test Helm Charts + +on: # yamllint disable-line rule:truthy + push: {} + +jobs: + lint-with-kubeconform: + runs-on: ubuntu-latest + steps: + - name: Add necessary repos + run: | + helm repo add bitnami https://charts.bitnami.com/bitnami + + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Prepare a charts folder + run: | + mkdir -p charts + for dir in */; do + if [[ $dir != charts/ && $dir != .* ]] ; then + helm dependency build "$dir" + mv "$dir" charts/ + fi + done + + - name: Login to GitHub Container Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Generate and validate releases + uses: docker://ghcr.io/shivjm/helm-kubeconform-action:v0.2.0 + env: + CHARTS_DIRECTORY: charts + HELM_UPDATE_DEPENDENCIES: false + LOG_LEVEL: trace + LOG_JSON: false + + lint-test-with-ct: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v3 + + # Python is required because `ct lint` runs Yamale (https://github.com/23andMe/Yamale) and + # yamllint (https://github.com/adrienverge/yamllint) which require Python + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.11 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.1 + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --config .github/linters/chart-testing.yaml) + if [[ -n "$changed" ]]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + fi + + - name: Run chart-testing (lint) + run: ct lint --config .github/linters/chart-testing.yaml + + - name: Create kind cluster + uses: helm/kind-action@v1.8.0 + if: steps.list-changed.outputs.changed == 'true' + + - name: Run chart-testing (install) + run: ct install --config .github/linters/chart-testing.yaml diff --git a/.github/workflows/super-linter.yml b/.github/workflows/super-linter.yml new file mode 100644 index 0000000..700928e --- /dev/null +++ b/.github/workflows/super-linter.yml @@ -0,0 +1,20 @@ +name: Lint Code Base + +on: # yamllint disable-line rule:truthy + push: {} + +jobs: + lint-code: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Lint Code Base + uses: github/super-linter@v5 + env: + DEFAULT_BRANCH: "main" + VALIDATE_ALL_CODEBASE: true + VALIDATE_KUBERNETES_KUBECONFORM: false diff --git a/README.md b/README.md index d7270ab..726aee8 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ +# Charts + - [Experimental Langfuse chart](langfuse/) diff --git a/langfuse/Chart.lock b/langfuse/Chart.lock index 2ca103c..7902e8c 100644 --- a/langfuse/Chart.lock +++ b/langfuse/Chart.lock @@ -2,5 +2,5 @@ dependencies: - name: postgresql repository: https://charts.bitnami.com/bitnami version: 13.2.27 -digest: sha256:e258f9c0089b58bc36a25ef1eeec96f6f3a674f687dc0b23ec6699173211223d -generated: "2024-01-02T20:49:32.367192173+01:00" +digest: sha256:c2272865ffe4c805153440d8fc6af84945d4ce566b14d0fa8698d75382ada06c +generated: "2024-01-06T01:28:34.164996418+01:00" diff --git a/langfuse/Chart.yaml b/langfuse/Chart.yaml index b3b711b..4196779 100644 --- a/langfuse/Chart.yaml +++ b/langfuse/Chart.yaml @@ -1,6 +1,8 @@ apiVersion: v2 name: langfuse description: An experimental Helm chart for Langfuse +maintainers: + - name: ilyannn # A chart can be either an 'application' or a 'library' chart. # @@ -15,7 +17,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.0 +version: 0.2.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to @@ -24,7 +26,7 @@ version: 0.2.0 appVersion: "1.28.0" dependencies: - - name: postgresql - repository: https://charts.bitnami.com/bitnami - version: 13.2.27 - condition: postgresql.enabled + - name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 13.2.27 + condition: postgresql.enabled diff --git a/langfuse/README.md b/langfuse/README.md index 283441e..253a925 100644 --- a/langfuse/README.md +++ b/langfuse/README.md @@ -4,32 +4,28 @@ See [values.yaml](values.yaml) for the chart values. They are subject to change! ## Installation -Example installation: - ```shell -helm install langfuse-demo https://github.com/ilyannn/charts/releases/download/langfuse-v0.2.0/langfuse-0.2.0.tgz -f langfuse-values.yaml +helm install langfuse-demo https://ilyannn.github.io/charts/langfuse -f langfuse-values.yaml ``` -### Default Installation - -By default, Langfuse will be installed with the bundled Postgres. +### Config-Free Installation -The password will be generated and saved in a `Secret` (in this case, `langfuse-demo-postgres-secret`). +The default values set up the bundled Postgres, and the chart takes care of and setting up +the authentication between the database and the service. +The Postgres password will be generated and saved in a `Secret` (in the example above, named +`langfuse-demo-postgres-secret`). -### OAuth +### Connecting to an Existing Database -### Using Existing Database Connection - -Disable the bundled database and pass an exising connection URL instead. +If the bundled chart is disabled, one can authenticate to an existing database. ```yaml -databaseURL: "postgresql://some-existing-url" - postgresql: enabled: false -``` +databaseURL: "postgresql://some-existing-url" +``` ### Accessing the installation @@ -41,18 +37,32 @@ ingress: hosts: ... ``` +### Additional options -### Uninstalling +Any options not present in the [values file](values.yaml) can be put into a `Secret` to be passed to Langfuse: +```yaml +additionalConfigurationSecret: langfuse-additional-options +``` + +You can create and update the secret at any time as it will not be managed by Helm. + +```shell +kubectl create secret generic langfuse-additional-options \ + --from-literal=AUTH_GITHUB_CLIENT_ID=... \ + --from-literal=AUTH_GITHUB_CLIENT_SECRET=... +``` + +## Uninstalling The usual `helm uninstall RELEASE_NAME` should work, but note that the following objects are not deleted automatically: - the data PVC of the `postgres` subchart (if the subchart was enabled) - the `-postgres-secret` secret (unless `postgresql.secret.alwaysKeepWhenUninstalled` is unset) +- the `-internal-secret` secret -This means that you can reinstall the chart and continue accessing the same data. - +This means that you can reinstall the chart and continue accessing the same data. -### Example values +## Example values See [megaver.se demo](https://docs.cluster.megaver.se/cluster/langfuse-demo-values.yaml) diff --git a/langfuse/templates/_helpers.tpl b/langfuse/templates/_helpers.tpl index be14886..6f9fcaa 100644 --- a/langfuse/templates/_helpers.tpl +++ b/langfuse/templates/_helpers.tpl @@ -41,12 +41,18 @@ If release name contains chart name it will be used as a full name. {{- end }} {{- end }} +{{- define "langfuse.internalSecret.annotations" -}} + "helm.sh/resource-policy": "keep" +{{- end }} + {{- define "langfuse.databaseHost" -}} +{{- if .Values.postgresql.enabled -}} {{- printf "%s.%s.%s" (include "postgresql.v1.primary.fullname" .Subcharts.postgresql) .Release.Namespace "svc.cluster.local" -}} {{- end }} +{{- end }} {{- define "langfuse.configMap" -}} {{- printf "%s-%s" (include "langfuse.fullname" .) "config-map" -}} diff --git a/langfuse/templates/connection-secret.yaml b/langfuse/templates/connection-secret.yaml index efa4474..e5c4703 100644 --- a/langfuse/templates/connection-secret.yaml +++ b/langfuse/templates/connection-secret.yaml @@ -1,16 +1,16 @@ -{{- if (or .Values.databaseURL .Values.directURL) -}} +{{- if (or (and (not .Values.postgresql.enabled) .Values.databaseURL) .Values.directURL) -}} apiVersion: v1 kind: Secret metadata: - name: {{ include "langfuse.connectionSecret.name" . }} + name: {{ include "langfuse.connectionSecret" . }} type: Opaque -data: +stringData: {{- if .Values.databaseURL }} - database-url: {{ .Values.databaseURL }} + database-url: {{ .Values.databaseURL | quote}} {{- end }} {{- if .Values.directURL }} - direct-url: {{ .Values.directURL }} + direct-url: {{ .Values.directURL | quote }} {{- end }} {{- end -}} diff --git a/langfuse/templates/deployment.yaml b/langfuse/templates/deployment.yaml index 87d83ad..d079972 100644 --- a/langfuse/templates/deployment.yaml +++ b/langfuse/templates/deployment.yaml @@ -38,13 +38,7 @@ spec: containerPort: 3000 protocol: TCP env: - {{- if .Values.databaseURL }} - - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: {{- include "langfuse.connectionSecret" . }} - key: database-url - {{- else }} + {{- if .Values.postgresql.enabled }} - name: DATABASE_USERNAME value: {{ .Values.postgresql.auth.username }} - name: DATABASE_NAME @@ -56,6 +50,12 @@ spec: secretKeyRef: name: {{ include "langfuse.postgresqlSecret" . }} key: {{ .Values.postgresql.auth.secretKeys.userPasswordKey }} + {{- else }} + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: {{ include "langfuse.connectionSecret" . }} + key: database-url {{- end }} {{- if .Values.directURL }} - name: DIRECT_URL @@ -78,7 +78,11 @@ spec: key: salt envFrom: - configMapRef: - name: {{ include "langfuse.configMap" . }} + name: {{ include "langfuse.configMap" . }} + {{- if .Values.additionalConfigurationSecret }} + - secretRef: + name: {{ .Values.additionalConfigurationSecret }} + {{- end }} livenessProbe: httpGet: path: /api/public/health diff --git a/langfuse/templates/internal-secret.yaml b/langfuse/templates/internal-secret.yaml index 0788847..ba07612 100644 --- a/langfuse/templates/internal-secret.yaml +++ b/langfuse/templates/internal-secret.yaml @@ -1,7 +1,8 @@ {{- $secretName := (include "langfuse.internalSecret" .) -}} {{- include "langfuse.mergeSecretWithRandomForKeys" (dict - "keys" (list "salt" "auth-secret") "name" $secretName + "annotations" (include "langfuse.internalSecret.annotations" .) + "keys" (list "salt" "auth-secret") "context" . ) -}} diff --git a/langfuse/tests/bundled_postgresql.yaml b/langfuse/tests/bundled_postgresql.yaml new file mode 100644 index 0000000..e69de29 diff --git a/langfuse/tests/existing_connection.yaml b/langfuse/tests/existing_connection.yaml new file mode 100644 index 0000000..6464c8f --- /dev/null +++ b/langfuse/tests/existing_connection.yaml @@ -0,0 +1,4 @@ +postgresql: + enabled: false + +databaseURL: "postgresql://user:password@example.com:1234/database" diff --git a/langfuse/tests/localhost_connection.yaml b/langfuse/tests/localhost_connection.yaml new file mode 100644 index 0000000..8460071 --- /dev/null +++ b/langfuse/tests/localhost_connection.yaml @@ -0,0 +1,2 @@ +postgresql: + enabled: false diff --git a/langfuse/tests/megaver-se-demo.yaml b/langfuse/tests/megaver-se-demo.yaml new file mode 100644 index 0000000..3d60577 --- /dev/null +++ b/langfuse/tests/megaver-se-demo.yaml @@ -0,0 +1,25 @@ +image: + repository: registry.cluster.megaver.se/ilyannn/langfuse + tag: main + +nextauthURL: https://langfuse-demo.cluster.megaver.se + +additionalConfigurationSecret: langfuse-additional-options + +postgresql: + enabled: true + +ingress: + enabled: true + annotations: + cert-manager.io/cluster-issuer: letsencrypt + traefik.ingress.kubernetes.io/router.middlewares: traefik-httpsonly@kubernetescrd + hosts: + - host: langfuse-demo.cluster.megaver.se + paths: + - path: / + pathType: ImplementationSpecific + tls: + - secretName: langfuse-demo-tls + hosts: + - langfuse-demo.cluster.megaver.se diff --git a/langfuse/values.yaml b/langfuse/values.yaml index c5be7f6..c0a70d5 100644 --- a/langfuse/values.yaml +++ b/langfuse/values.yaml @@ -1,15 +1,14 @@ # ------------ Core options -# By default, the postgres subchart will be installed and the connection set up. -# Specify postgresql.enabled: false and provide this value to use an existing Postgres -# installation or to set it up manually. -databaseURL: "" +# This URL must agree with the app's URL for OAuth to work +nextauthURL: http://localhost:3000 -# Used for migrations -directURL: "" +# By default, the postgres subchart will be installed and the connection value overridden. +# Disable the bundled subchart using postgresql.enabled if you want to use this setting. +databaseURL: "postgresql://postgres:postgres@localhost:5432/postgres" -# This one must agree with the app's URL for OAuth to work -nextauthURL: http://localhost:3000 +# This URL is used for migrations +directURL: "" # Several toggles for Langfuse functionality toggles: @@ -17,11 +16,13 @@ toggles: experimentalFeatures: false telemetry: true +# This secret's fields (in the ENV_VAR: value format) are added to the Langfuse config +additionalConfigurationSecret: # ------------ Postgres subchart postgresql: - # Setting this to false will prevent automatic installation of the Postgresql subchart + # Setting this to false will not install the bundled Postgres subchart enabled: true auth: @@ -38,11 +39,9 @@ postgresql: createIfMissing: true # Set this to false if you want the secret to be deleted with `helm delete` # This has no effect unless createIfMissing is also true. - # Warning: reinstalling the chart will generate a new password, but Postgres will + # Warning: reinstalling the chart will generate a new password, but Postgres will # continue to use an old password since it's stored on the PVC. alwaysKeepWhenUninstalled: true - - # ------------ Standard values generated by helm create @@ -69,10 +68,12 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +podSecurityContext: + {} # fsGroup: 2000 -securityContext: {} +securityContext: + {} # capabilities: # drop: # - ALL @@ -87,7 +88,8 @@ service: ingress: enabled: false className: "" - annotations: {} + annotations: + {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" hosts: @@ -100,7 +102,8 @@ ingress: # hosts: # - chart-example.local -resources: {} +resources: + {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following