Skip to content
Merged
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
157 changes: 157 additions & 0 deletions .github/workflows/helm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: Helm Chart

on:
push:
branches: [main, staging, dev]
paths:
- 'helm/sim/**'
- '.github/workflows/helm.yml'
pull_request:
branches: [main, staging, dev]
paths:
- 'helm/sim/**'
- '.github/workflows/helm.yml'

concurrency:
group: helm-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
chart:
name: Lint, test, and validate chart
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
timeout-minutes: 15
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.16.4

- name: Helm lint
run: helm lint helm/sim --values helm/sim/ci/default-values.yaml

- name: Helm unit tests
run: |
# Official helm-unittest image, pinned by immutable digest (tag 3.17.3-0.8.2).
# Run as the runner's UID so the container can write into the bind
# mount (it creates tests/__snapshot__), with a writable HOME for helm.
docker run --rm --user "$(id -u):$(id -g)" -e HOME=/tmp \
-v "$PWD/helm/sim:/apps" \
helmunittest/helm-unittest@sha256:b653db7d5665bc6cec677b15c5eaa1c0377c0de8ac4eb1df58b924478baa21e1 .

- name: Install kubeconform
run: |
Comment thread
waleedlatif1 marked this conversation as resolved.
curl -sSL -o /tmp/kubeconform.tar.gz \
https://github.com/yannh/kubeconform/releases/download/v0.6.7/kubeconform-linux-amd64.tar.gz
echo "95f14e87aa28c09d5941f11bd024c1d02fdc0303ccaa23f61cef67bc92619d73 /tmp/kubeconform.tar.gz" | sha256sum -c -
tar -xzf /tmp/kubeconform.tar.gz -C /tmp kubeconform

- name: Render and validate manifests (default configuration)
run: |
helm template sim helm/sim --namespace sim \
--values helm/sim/ci/default-values.yaml \
| /tmp/kubeconform -strict -summary \
-kubernetes-version 1.29.0 \
-schema-location default \
-schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json'

- name: Render and validate manifests (all components enabled)
run: |
helm template sim helm/sim --namespace sim \
--values helm/sim/ci/full-values.yaml \
| /tmp/kubeconform -strict -summary \
-kubernetes-version 1.29.0 \
-schema-location default \
-schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json'

- name: Render every example values file
run: |
set -euo pipefail
for f in helm/sim/examples/values-*.yaml; do
echo "--- $f"
# Examples intentionally omit secrets (their headers document the
# required --set flags), so supply the CI dummies alongside each.
helm template sim helm/sim --namespace sim \
--values "$f" \
--values helm/sim/ci/default-values.yaml \
--set copilot.postgresql.auth.password=ci-dummy-password \
--set copilot.server.env.AGENT_API_DB_ENCRYPTION_KEY=cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici \
--set copilot.server.env.INTERNAL_API_SECRET=cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici \
--set copilot.server.env.LICENSE_KEY=ci-dummy-license \
--set copilot.server.env.SIM_BASE_URL=https://ci.example.com \
--set copilot.server.env.SIM_AGENT_API_KEY=ci-dummy-agent-key \
--set copilot.server.env.REDIS_URL=redis://ci-redis:6379 \
--set copilot.server.env.OPENAI_API_KEY_1=ci-dummy-openai-key \
--set externalDatabase.password=ci-dummy-password > /dev/null
done

version-bump:
name: Chart version bumped
if: github.event_name == 'pull_request'
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
fetch-depth: 0
- name: Require a Chart.yaml version bump when chart content changes
run: |
set -euo pipefail
base="origin/${{ github.base_ref }}"
git fetch origin "${{ github.base_ref }}"
merge_base=$(git merge-base "$base" HEAD)
changed=$(git diff --name-only "$merge_base" HEAD)
if echo "$changed" | grep -q '^helm/sim/'; then
base_version=$(git show "$merge_base:helm/sim/Chart.yaml" | awk '/^version:/ {print $2}')
head_version=$(awk '/^version:/ {print $2}' helm/sim/Chart.yaml)
echo "base=$base_version head=$head_version"
if [ "$base_version" = "$head_version" ]; then
echo "::error::helm/sim/** changed but Chart.yaml version did not (still $head_version). Bump it per SemVer."
exit 1
fi
else
echo "No chart changes; skipping."
Comment thread
waleedlatif1 marked this conversation as resolved.
fi

install:
name: Install on kind and run helm test
needs: chart
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
timeout-minutes: 25
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4

- name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4
with:
version: v3.16.4

- name: Create kind cluster
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1
with:
version: v0.24.0

- name: Install chart
run: |
helm install sim helm/sim \
--namespace sim --create-namespace \
--values helm/sim/ci/default-values.yaml \
--values helm/sim/ci/kind-values.yaml \
--wait --timeout 15m

- name: Diagnostics on failure
if: failure()
run: |
kubectl -n sim get pods -o wide || true
kubectl -n sim get events --sort-by=.lastTimestamp | tail -40 || true
kubectl -n sim describe pods | tail -100 || true
kubectl -n sim logs deploy/sim-app -c migrations --tail=50 || true
kubectl -n sim logs deploy/sim-app --tail=80 || true

- name: Run helm test
run: helm test sim --namespace sim --timeout 5m
4 changes: 2 additions & 2 deletions helm/sim/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: v2
name: sim
description: A Helm chart for Sim - the open-source AI workspace where teams build, deploy, and manage AI agents
type: application
version: 1.1.0
appVersion: "0.6.73"
version: 1.2.0
appVersion: "v0.7.44"
kubeVersion: ">=1.25.0-0"
home: https://sim.ai
icon: https://raw.githubusercontent.com/simstudioai/sim/main/apps/sim/public/logo/primary/primary.svg
Expand Down
7 changes: 7 additions & 0 deletions helm/sim/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,13 @@ kubectl --namespace sim logs deploy/sim-app -c migrations

---

## Upgrading to 1.2.0

* `appVersion` (the default image tag when `image.tag` is unset) is now `v0.7.44` — the previous `0.6.73` referenced a tag that does not exist on GHCR, so an unpinned default install could not pull images. Production installs should still pin `image.tag` explicitly.
* `externalSecrets.apiVersion` now defaults to `"v1"` — current External Secrets Operator releases no longer serve `v1beta1` (removed upstream in 2026). Set `externalSecrets.apiVersion: "v1beta1"` only if you still run ESO < 0.17.
* `values.schema.json` now declares every top-level key and rejects unknown top-level keys, so a typo like `networkPolciy:` fails fast at install time instead of being silently ignored. If an upgrade suddenly fails schema validation, check your values file for stray top-level keys.
* The opt-in telemetry collector no longer ships a Prometheus scrape config for the app/realtime services (they expose no `/metrics` endpoint); OTLP ingestion is unchanged.

## Upgrading to 1.1.0

No action is required for working configurations. Notes:
Expand Down
12 changes: 12 additions & 0 deletions helm/sim/ci/default-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# CI-only values: the minimum required secrets so `helm lint`/`helm template`
# render the DEFAULT configuration. Dummy values — never use in a deployment.
app:
env:
BETTER_AUTH_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
ENCRYPTION_KEY: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
INTERNAL_API_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
CRON_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"

postgresql:
auth:
password: "ci-dummy-password"
72 changes: 72 additions & 0 deletions helm/sim/ci/full-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# CI-only values: every optional component enabled so the full template surface
# renders and validates. Dummy values — never use in a deployment.
app:
env:
BETTER_AUTH_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
ENCRYPTION_KEY: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
INTERNAL_API_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
CRON_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
API_ENCRYPTION_KEY: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"

postgresql:
auth:
password: "ci-dummy-password"
tls:
enabled: true

certManager:
enabled: true

ingress:
enabled: true
app:
host: ci.example.com
paths: [{ path: /, pathType: Prefix }]
realtime:
host: ci-ws.example.com
paths: [{ path: /, pathType: Prefix }]
tls:
enabled: true

networkPolicy:
enabled: true

autoscaling:
enabled: true

monitoring:
serviceMonitor:
enabled: true

telemetry:
enabled: true
jaeger:
enabled: true
prometheus:
enabled: true
otlp:
enabled: true

sharedStorage:
enabled: true

ollama:
enabled: true

pii:
enabled: true

copilot:
enabled: true
postgresql:
auth:
password: "ci-dummy-password"
server:
env:
AGENT_API_DB_ENCRYPTION_KEY: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
INTERNAL_API_SECRET: "cicicicicicicicicicicicicicicicicicicicicicicicicicicicicicicici"
LICENSE_KEY: "ci-dummy-license"
SIM_BASE_URL: "https://ci.example.com"
SIM_AGENT_API_KEY: "ci-dummy-agent-key"
REDIS_URL: "redis://ci-redis:6379"
OPENAI_API_KEY_1: "ci-dummy-openai-key"
39 changes: 39 additions & 0 deletions helm/sim/ci/kind-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# CI-only overlay for the kind install test: shrink resource requests so the
# default configuration schedules on a small CI runner. Layered on top of
# ci/default-values.yaml. Dummy sizing — never use in a deployment.
app:
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 2Gi

realtime:
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi

migrations:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi

postgresql:
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
memory: 1Gi
persistence:
size: 2Gi
6 changes: 3 additions & 3 deletions helm/sim/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ Your release is named {{ .Release.Name }} in namespace {{ .Release.Namespace }}.

5. Upgrade notes (read before upgrading from a chart version released before this one):

* externalSecrets.apiVersion default is "v1beta1" (was "v1"). v1beta1 is
supported by every ESO release from v0.7+ through current. If you're on
ESO v0.17+ and want the graduated v1 API, set externalSecrets.apiVersion: "v1".
* externalSecrets.apiVersion defaults to "v1". Current ESO releases no
longer serve v1beta1 (the compatibility path was removed in 2026) — set
externalSecrets.apiVersion: "v1beta1" only if you still run ESO < 0.17.
* networkPolicy.egress remains a list of custom egress rules (unchanged).
Cloud-metadata CIDR blocking is now configured via networkPolicy.egressExceptCidrs
(defaults to AWS/GCP/Azure IMDS + ECS task metadata).
Expand Down
2 changes: 1 addition & 1 deletion helm/sim/templates/external-secret-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# - a string: treated as the remoteRef.key (legacy form)
# - a map: passed through as the remoteRef block (e.g. {key, property,
# version, decodingStrategy, conversionStrategy, metadataPolicy})
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1beta1" }}
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1" }}
kind: ExternalSecret
metadata:
name: {{ include "sim.fullname" . }}-app-secrets
Expand Down
2 changes: 1 addition & 1 deletion helm/sim/templates/external-secret-copilot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# template rendering if a required key (or any non-empty copilot.server.env key) is
# missing a matching remoteRefs.copilot entry, so a misconfiguration surfaces at
# `helm template` time instead of a container starting with an empty value.
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1beta1" }}
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1" }}
kind: ExternalSecret
metadata:
name: {{ include "sim.copilot.envSecretName" . }}
Expand Down
2 changes: 1 addition & 1 deletion helm/sim/templates/external-secret-external-db.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{- if and .Values.externalSecrets.enabled .Values.externalDatabase.enabled .Values.externalSecrets.remoteRefs.externalDatabase.password }}
# ExternalSecret for external database password (syncs from external secret managers)
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1beta1" }}
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1" }}
kind: ExternalSecret
metadata:
name: {{ include "sim.fullname" . }}-external-db-secret
Expand Down
2 changes: 1 addition & 1 deletion helm/sim/templates/external-secret-postgresql.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{- if and .Values.externalSecrets.enabled .Values.postgresql.enabled .Values.externalSecrets.remoteRefs.postgresql.password }}
# ExternalSecret for PostgreSQL password (syncs from external secret managers)
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1beta1" }}
apiVersion: external-secrets.io/{{ .Values.externalSecrets.apiVersion | default "v1" }}
kind: ExternalSecret
metadata:
name: {{ include "sim.fullname" . }}-postgresql-secret
Expand Down
7 changes: 7 additions & 0 deletions helm/sim/templates/job-copilot-migrations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ spec:
sleep 2
done
echo "Copilot PostgreSQL is ready!"
resources:
requests:
cpu: 10m
memory: 16Mi
limits:
cpu: 100m
memory: 64Mi
envFrom:
- secretRef:
name: {{ include "sim.fullname" . }}-copilot-postgresql-secret
Expand Down
12 changes: 1 addition & 11 deletions helm/sim/templates/telemetry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,6 @@ data:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
prometheus:
config:
scrape_configs:
- job_name: 'sim-app'
static_configs:
- targets: ['{{ include "sim.fullname" . }}-app:{{ .Values.app.service.port }}']
- job_name: 'sim-realtime'
static_configs:
- targets: ['{{ include "sim.fullname" . }}-realtime:{{ .Values.realtime.service.port }}']

processors:
batch:
timeout: 1s
Expand Down Expand Up @@ -83,7 +73,7 @@ data:
- otlp
{{- end }}
metrics:
receivers: [otlp, prometheus]
receivers: [otlp]
processors: [memory_limiter, batch]
exporters:
- logging
Expand Down
Loading
Loading