Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
19 changes: 19 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# EditorConfig is awesome: https://EditorConfig.org
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 120
trim_trailing_whitespace = true

[*.md]
max_line_length = 0
trim_trailing_whitespace = false

[*.{yaml,yml,json}]
indent_style = space
indent_size = 2
124 changes: 124 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Copilot Instructions — helm-engram

Helm chart repository for **Engram Cloud** — a Go-based AI persistent memory server backed by PostgreSQL.
The chart lives at `charts/engram/` and follows standard Helm chart conventions.

---

## Build, Test & Lint

```bash
# Install dependencies (run once or after Chart.yaml changes)
helm repo add bitnami https://charts.bitnami.com/bitnami
helm dependency update charts/engram/

# Lint
npm run lint # helm lint charts/engram
npm run lint:full # lint with full CI values

# Unit tests (helm-unittest plugin required)
npm run test # all tests
npm run test:verbose # with verbose output
npm run test:update-snapshot # regenerate __snapshot__ files after template changes

# Run a single test suite
helm unittest charts/engram/ -f tests/deployment_test.yaml

# Template smoke tests
npm run template # minimal values (bundled PG)
npm run template:full # HPA + PDB + Ingress + resources
npm run template:ingress # ingress-only values

# Regenerate README.md from README.md.gotmpl
npm run docs # requires helm-docs

# Bump chart patch version
npm run version:bump
```

Install `helm-unittest`:
```bash
helm plugin install https://github.com/helm-unittest/helm-unittest --verify=false
```

---

## Architecture

Single chart at `charts/engram/` with one subchart dependency (`bitnami/postgresql`).

```
charts/engram/
├── Chart.yaml # version mirrors upstream Engram appVersion
├── values.yaml # annotated defaults
├── values.schema.json # JSON Schema validation for values
├── templates/
│ ├── _helpers.tpl # shared named templates
│ ├── deployment.yaml
│ ├── configmap.yaml # non-secret env vars (port, host, allowedProjects)
│ ├── secret.yaml # ENGRAM_DATABASE_URL + ENGRAM_JWT_SECRET (rendered only if existingSecret is empty)
│ ├── extra-objects.yaml # renders .Values.extraObjects via tpl
│ └── ... # service, ingress, hpa, pdb, serviceaccount
├── tests/ # helm-unittest YAML test suites
│ └── __snapshot__/ # commit these when updating snapshot tests
└── ci/ # CI values files used by helm lint/template
├── minimal-values.yaml
├── full-values.yaml
└── ingress-values.yaml
```

**Config split — ConfigMap vs Secret:**
- `ConfigMap`: `ENGRAM_PORT`, `ENGRAM_CLOUD_HOST`, `ENGRAM_ALLOWED_PROJECTS`, `ENGRAM_INSECURE_NO_AUTH`
- `Secret`: `ENGRAM_DATABASE_URL`, `ENGRAM_JWT_SECRET`

**Secret resolution (`engram.secretName` helper):**
1. If `engram.existingSecret` is set, use that Secret and skip rendering `templates/secret.yaml` entirely.
2. If `engram.existingSecret` is not set, render `templates/secret.yaml` and create a Secret from `engram.databaseUrl` + `engram.jwtSecret`.

**DSN auto-build:** When `postgresql.enabled=true` and `engram.databaseUrl=""`, the `engram.databaseUrl` helper in `_helpers.tpl` assembles the DSN from `postgresql.auth.*` values. Explicit `engram.databaseUrl` always wins.

**Init container:** When `postgresql.enabled=true`, the deployment automatically injects a `wait-for-postgresql` busybox init container (unless `postgresql.waitForReady.disabled=true`).

---

## Key Conventions

### Versioning
- `Chart.yaml` `version` and `appVersion` are kept in sync with upstream Engram releases.
- UpdateCLI (`.github/updatecli/`) opens automated PRs to bump both fields + `image.tag` in `values.yaml`.
- Use `npm run version:bump` for manual patch bumps.

### Tests
- Test files live in `charts/engram/tests/` with the naming pattern `<resource>_test.yaml`.
- Each suite declares `templates:` listing which templates it covers.
- Snapshot files in `tests/__snapshot__/` must be committed after running `--update-snapshot`.
- CI values files in `ci/` are the canonical inputs for `helm lint` and `helm template` checks.

### `extraObjects`
- Rendered via `tpl`, so they support `{{ .Release.Name }}`, `{{ .Values.* }}`, etc.
- Typical uses: `ExternalSecret`, `NetworkPolicy`, `ServiceMonitor`.

### `_helpers.tpl` named templates
All chart-specific helpers are prefixed `engram.*`:
- `engram.name`, `engram.fullname`, `engram.chart`
- `engram.labels`, `engram.selectorLabels`
- `engram.serviceAccountName`
- `engram.secretName` — resolves existingSecret vs chart-managed secret
- `engram.databaseUrl` — auto-builds DSN from subchart values

### Security defaults (do not weaken without tests)
- `runAsUser: 10001`, `runAsGroup: 10001`, `fsGroup: 10001`
- `runAsNonRoot: true`, `readOnlyRootFilesystem: true`, `allowPrivilegeEscalation: false`
- `capabilities.drop: [ALL]`

### CI Workflows
| Workflow | Trigger | Purpose |
|----------|---------|---------|
| `helm-lint-test.yml` | PR | `helm lint` + `helm unittest` |
| `helm-release.yml` | push to main | Publishes chart to GitHub Pages via chart-releaser |
| `helm-check-engram-release.yml` | schedule | Checks for new upstream Engram releases |
| `github-auto-assign.yml` | PR | Auto-assigns reviewers |

### pre-commit hooks
Hooks run: `trailing-whitespace`, `end-of-file-fixer`, `check-yaml`, `check-json`, `mixed-line-ending`, `helmlint`.
Install with `pre-commit install`.
3 changes: 3 additions & 0 deletions .github/cr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
generate-release-notes: true
release-name-template: "v{{ .Version }}"
skip-existing: true
9 changes: 9 additions & 0 deletions .github/ct.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# See https://github.com/helm/chart-testing#configuration
chart-dirs:
- charts
check-version-increment: true
debug: false
remote: origin
target-branch: main
validate-maintainers: false
validate-yaml: true
33 changes: 33 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: 2
updates:
# Keep GitHub Actions up to date
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "08:00"
timezone: "Europe/Madrid"
groups:
github-actions:
patterns:
- "*"
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"

# Keep npm devDependencies up to date (helm-docs, etc.)
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "08:00"
timezone: "Europe/Madrid"
labels:
- "dependencies"
- "npm"
commit-message:
prefix: "chore"
33 changes: 33 additions & 0 deletions .github/updatecli/helm-appversion.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
sources:
engram:
kind: githubrelease
spec:
owner: "Gentleman-Programming"
repository: "engram"
token: {{ requiredEnv "GITHUB_TOKEN" }}
versionFilter:
kind: semver
pattern: ">=v1.0.0"
conditions: {}
targets:
imageTag:
name: bump engram image tag in values.yaml
kind: helmchart
spec:
name: charts/engram
file: values.yaml
key: $.image.tag
sourceid: engram
appVersion:
name: bump appVersion in Chart.yaml
kind: helmchart
spec:
name: charts/engram
file: Chart.yaml
key: $.appVersion
sourceid: engram
# NOTE: chart version ($.version) is NOT managed here.
# When a new Engram release is detected, the helm-check-engram-release.yml workflow
# resets the chart version to {major}.{minor}.0 (e.g., v1.16.0 → 1.16.0).
# For chart-only changes, bump the patch manually: 1.16.0 → 1.16.1 → 1.16.2
# using: npm run version:bump
19 changes: 19 additions & 0 deletions .github/workflows/github-auto-assign.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Auto-assign Issue

on:
issues:
types: [opened]
pull_request_target:
types: [opened, ready_for_review]

jobs:
auto-assign:
permissions:
contents: read
issues: write
pull-requests: write
uses: devops-ia/.github/.github/workflows/github-auto-assign.yml@main
with:
teams: devops-ia
secrets:
PAT_GITHUB: ${{ secrets.PAT_GITHUB }}
85 changes: 85 additions & 0 deletions .github/workflows/helm-check-engram-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Check Engram release

permissions:
contents: write
pull-requests: write

on:
workflow_dispatch:
schedule:
- cron: '0 8 * * 1' # every Monday at 08:00 UTC

jobs:
check-and-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0

- name: Get current release
id: current_release
run: |
current_release=$(grep appVersion charts/engram/Chart.yaml | awk '{ print $2 }' | tr -d '"')
echo "current_release=$current_release" >> $GITHUB_OUTPUT

- name: Install updatecli
uses: updatecli/updatecli-action@2c3221bc5f4499a99fec2c87d9de4a83cb30e990 # v3.1.3

- name: Update engram version
run: |
updatecli apply --config .github/updatecli/helm-appversion.yaml --commit=false
env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"

- name: Get latest release
id: latest_release
run: |
latest_release=$(grep appVersion charts/engram/Chart.yaml | awk '{ print $2 }' | tr -d '"')
echo "latest_release=$latest_release" >> $GITHUB_OUTPUT

- name: Check if release changed
id: check_changes
run: |
if [ "${{ steps.latest_release.outputs.latest_release }}" != "${{ steps.current_release.outputs.current_release }}" ]; then
echo "release_changed=true" >> $GITHUB_OUTPUT
fi

- name: Update README.md
if: steps.check_changes.outputs.release_changed == 'true'
uses: losisin/helm-docs-github-action@2ccf3e77eb70dc80d62f8cc26f15d0a96b75fef4 # v1.8.0
with:
chart-search-root: charts/engram

- name: Reset chart version for new Engram release
if: steps.check_changes.outputs.release_changed == 'true'
run: |
# Strip leading 'v' from the new appVersion and reset chart patch to 0
# e.g., v1.16.0 → 1.16.0 / v1.17.3 → 1.17.0
new_app="${{ steps.latest_release.outputs.latest_release }}"
new_app="${new_app#v}"
major=$(echo "$new_app" | cut -d. -f1)
minor=$(echo "$new_app" | cut -d. -f2)
chart_version="${major}.${minor}.0"
sed -i "s/^version:.*/version: ${chart_version}/" charts/engram/Chart.yaml
echo "Chart version reset to ${chart_version}"

- name: Create PR with changes
if: steps.check_changes.outputs.release_changed == 'true'
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.PAT_GITHUB }}
commit-message: "fix: update engram version to ${{ steps.latest_release.outputs.latest_release }}"
signoff: false
branch: chore/upgrade-engram-${{ steps.latest_release.outputs.latest_release }}
delete-branch: true
title: '[engram] new release: ${{ steps.latest_release.outputs.latest_release }}'
body: |
Engram Cloud version:
- :information_source: Current: `${{ steps.current_release.outputs.current_release }}`
- :up: Upgrade: `${{ steps.latest_release.outputs.latest_release }}`

Changelog: https://github.com/Gentleman-Programming/engram/releases/tag/${{ steps.latest_release.outputs.latest_release }}
labels: |
auto-pr-bump-version
54 changes: 54 additions & 0 deletions .github/workflows/helm-lint-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Lint and Test Helm Charts

on:
workflow_dispatch:
pull_request:

jobs:
lint-test:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0

- name: Set up Helm
uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1

- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.x
check-latest: true

- name: Set up chart-testing
uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0

- name: Run chart-testing (list-changed)
id: list-changed
run: |
changed=$(ct list-changed --config .github/ct.yaml)
if [[ -n "${changed}" ]]; then
echo "changed=true" >> "$GITHUB_OUTPUT"
fi

- name: Install helm-unittest plugin
run: helm plugin install https://github.com/helm-unittest/helm-unittest --version 0.8.2 --verify=false

- name: Run Helm unit tests
run: helm unittest charts/engram/

- name: Run chart-testing (lint)
if: steps.list-changed.outputs.changed == 'true'
run: ct lint --config .github/ct.yaml

- name: Create kind cluster
if: steps.list-changed.outputs.changed == 'true' || github.event_name == 'workflow_dispatch'
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1.14.0

- name: Run chart-testing (install)
if: steps.list-changed.outputs.changed == 'true'
run: ct install --config .github/ct.yaml --helm-extra-args "--timeout 900s --debug"
Loading
Loading