Skip to content

Rework Helm chart and add local dev support - #558

Draft
kowtom wants to merge 5 commits into
ENTERPILOT:mainfrom
kowtom:feature/helm-refactor
Draft

Rework Helm chart and add local dev support#558
kowtom wants to merge 5 commits into
ENTERPILOT:mainfrom
kowtom:feature/helm-refactor

Conversation

@kowtom

@kowtom kowtom commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces a comprehensive Helm chart for GoModel, along with a local Kubernetes development workflow using kind and Skaffold. It adds all necessary Helm templates, CI/CD automation for chart linting and publishing, and Makefile targets for local cluster management. The changes enable streamlined deployment, testing, and packaging of GoModel on Kubernetes, supporting both stateless (multi-replica) and persistent (SQLite) modes.

The most important changes are:

Helm Chart Introduction and Structure:

  • Added a full-featured Helm chart for GoModel in deploy/helm/gomodel, including templates, example values, documentation, and helper templates to support flexible, production-grade Kubernetes deployments. (deploy/helm/gomodel/Chart.yaml, README.md, templates/, ci/, etc.) [1] [2] [3] [4] [5] [6] [7] [8]

CI/CD Automation for Helm:

  • Added GitHub Actions workflows for Helm chart linting and schema validation on PRs and pushes (.github/workflows/helm-ci.yml), and for packaging and publishing the chart to Docker Hub as an OCI artifact on tagged releases (.github/workflows/helm-release.yml). [1] [2]

Local Kubernetes Development Workflow:

  • Introduced a local development workflow using kind and Skaffold, including a development-optimized Dockerfile.dev, Makefile targets for cluster management (kind-up, kind-down, dev-k8s, etc.), and configuration for local dependencies and manifests. [1] [2] [3] [4]

Configuration and Pre-commit Updates:

  • Updated .pre-commit-config.yaml to match the new Helm chart directory structure for YAML checks.

Repository Structure Adjustments:

  • Moved and renamed directories and files to support the new deployment and development workflows, including replacing helm/ with deploy/helm/, adding .dockerignore entries, and updating deployment-related files.

These changes provide a robust foundation for deploying, testing, and maintaining GoModel on Kubernetes in both development and production environments.

Summary by CodeRabbit

  • New Features

    • Added a production-ready Helm chart supporting stateless and persistent deployments, configurable secrets, ingress, autoscaling, health checks, metrics, and network policies.
    • Added local Kubernetes development with kind, Skaffold, PostgreSQL, Redis, MongoDB, and a mock LLM service.
    • Added a secure development container image with non-root execution and read-only runtime settings.
  • Documentation

    • Added installation, configuration, local Kubernetes, troubleshooting, and API usage guidance.
  • Chores

    • Added automated chart validation and release workflows.

kowtom added 4 commits July 19, 2026 22:16
Rework the Helm chart around external datastores with two deployment
modes: a stateless Deployment (default) and a SQLite StatefulSet+PVC
mode gated by persistence.enabled, with guardrails preventing unsafe
multi-replica/autoscaling combinations.

Add HTTP /health and /health/ready probes, ConfigMap-rendered
config.yaml with ${VAR} expansion, chart or existing Secret via
envFrom, distroless-matched securityContext, plus Ingress, HPA, PDB,
NetworkPolicy, ServiceMonitor and config/secret checksum auto-reload.

Add CI workflows to lint, template, and kubeconform-validate the chart
and to publish it to the Docker Hub OCI registry on helm-v* tags.

Drop the previous Bitnami redis subchart and Gateway API HTTPRoute in
favor of external-only dependencies and Ingress-based routing.
Deploy a stdlib-only OpenAI-compatible mock upstream (ConfigMap-mounted
Python server) via `make kind-up`, and point the dev OpenAI provider at
it (OPENAI_BASE_URL) so /v1/models and /v1/chat/completions work
end-to-end in kind without real provider credentials. Extends CI
kubeconform validation and dev docs accordingly.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces the legacy Helm chart with deploy/helm/gomodel, adds stateless and SQLite deployment resources, introduces kind-based local Kubernetes development, and adds Docker, Skaffold, CI validation, and OCI release workflows.

Changes

Helm chart foundation

Layer / File(s) Summary
Chart contracts and shared helpers
deploy/helm/gomodel/Chart.yaml, deploy/helm/gomodel/values.yaml, deploy/helm/gomodel/values.schema.json, deploy/helm/gomodel/templates/_helpers.tpl, deploy/helm/gomodel/templates/_pod.tpl, deploy/helm/gomodel/README.md
Defines chart metadata, validated values, naming helpers, secret and persistence logic, pod configuration, and deployment documentation.
Chart workload and supporting resources
deploy/helm/gomodel/templates/*
Adds Deployment and StatefulSet rendering with ConfigMap, Secret, Service, Ingress, NetworkPolicy, PDB, ServiceAccount, HPA, ServiceMonitor, and installation notes.
Local Kubernetes environment
deploy/local/*, deploy/helm/gomodel/ci/*, docs/dev/local-kubernetes.md, docs/DEVELOPMENT.md
Adds kind, Redis, PostgreSQL, MongoDB, and mock LLM manifests with local values and usage documentation.
Build, deployment, and validation automation
Dockerfile.dev, Makefile, skaffold.yaml, .github/workflows/*, .dockerignore, .pre-commit-config.yaml
Adds the development image, Kubernetes Make targets, Skaffold deployment, Helm CI validation, OCI publishing, and updated ignore rules.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Poem

A rabbit checks the chart at night,
Helm values render clean and bright.
Kind clusters hop into the queue,
Mock models answer “How do you do?”
Skaffold builds, then workflows run—
A carrot for every successful one!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the chart rework and local development support introduced by the pull request.
Description check ✅ Passed The description explains the purpose and major changes, including the Helm chart, CI/CD automation, and local Kubernetes workflow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch feature/helm-refactor
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@SantiagoDePolonia

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 15

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/helm-ci.yml:
- Around line 82-86: Add a no-values helm template validation before the
existing values-file loop in the workflow, piping the default render through
kubeconform with the same strict, missing-schema, and summary options. Keep the
current named-values validation loop unchanged.
- Line 29: Pin the actions at lines 29, 34, 55, 64, and 67 to their reviewed
full commit SHAs instead of mutable version tags, while preserving each original
version tag in an adjacent comment for maintenance.
- Around line 73-76: Update the kubeconform installation steps around the curl
download and tar extraction to download the release CHECKSUMS file, verify
kubeconform-linux-amd64.tar.gz against its expected checksum, and only extract
and install after verification succeeds. Keep the existing version and asset
names consistent.

In @.github/workflows/helm-release.yml:
- Around line 24-25: Harden the release workflow by pinning both
actions/checkout and azure/setup-helm to immutable commit SHAs instead of
mutable version tags, and update the Docker login step to receive
DOCKER_USERNAME and DOCKERHUB_TOKEN through its env block rather than
interpolating secrets directly in the run script; preserve the existing
metadata-step environment handling.
- Around line 27-30: Update the version value in the “Set up Helm” workflow step
to the latest supported Helm v3.x patch release, replacing the outdated v3.16.3
pin while preserving the existing azure/setup-helm@v4 action configuration.

In `@deploy/helm/gomodel/Chart.yaml`:
- Around line 7-8: Replace the "latest" value in Chart.yaml’s appVersion with
the concrete released GoModel version this chart was tested against, and update
that pinned version for every subsequent chart release so default image tags and
version labels remain meaningful.

In `@deploy/helm/gomodel/templates/_helpers.tpl`:
- Around line 116-127: Document the probe-path limitation in the comment for the
gomodel.basePath helper, explicitly stating that only env.BASE_PATH and
config.server.base_path are supported sources; also update the README.md
probe-path documentation to state the same restriction and clarify that
BASE_PATH supplied through extraEnv or secrets.data is not honored.

In `@deploy/helm/gomodel/templates/_pod.tpl`:
- Around line 54-99: Update the port configuration around the pod template’s
http container port so it is derived from the configured application port rather
than hardcoded to 8080. Compute the resolved port once using the existing
configuration values and reuse that helper for containerPort, the named http
Service port, and any corresponding Service targetPort, while preserving the
named-port references used by the probes.

In `@deploy/helm/gomodel/templates/pdb.yaml`:
- Around line 10-13: Update the PodDisruptionBudget condition around
podDisruptionBudget.maxUnavailable and minAvailable to detect explicitly
configured zero values, not only truthy values. Reject configurations where both
fields are set together or both are null/nil, while rendering exactly one
configured field, including maxUnavailable: 0.

In `@deploy/helm/gomodel/values.schema.json`:
- Around line 109-117: Update the secrets.data schema within the secrets
properties to define its additional properties as strings, while preserving the
object type and existing secrets validation. This must reject nested objects,
booleans, and other non-string values during schema validation.

In `@deploy/local/kind-cluster.yaml`:
- Around line 4-6: Update the comments in the local kind cluster configuration,
including the comment near extraPortMappings, to describe gateway access through
the NodePort mapping from container port 30080 to host port 8080. Remove the
stale claim that Skaffold port-forwarding is required and that the mappings are
reserved for an optional 80/443 Ingress controller.

In `@docs/dev/local-kubernetes.md`:
- Line 5: Update the external links in docs/dev/local-kubernetes.md, including
the Helm chart reference and the deploy/local/values.yaml reference, to absolute
GitHub URLs targeting the main branch; preserve the existing link text and
destinations.

In `@Makefile`:
- Around line 89-91: Update the comment above the undeploy-k8s target to clarify
that skaffold delete removes only the Helm release, while dependency manifests
remain until make kind-down; do not change the command unless explicitly adding
dependency deletion to this target.
- Around line 65-68: Update the kind create command in the kind-up target to
pass KIND_CLUSTER via the kind cluster name option, ensuring newly created
clusters and contexts match the existing kind-$(KIND_CLUSTER) references.

In `@skaffold.yaml`:
- Around line 3-11: Correct the local gateway access comments in the skaffold
configuration: remove the claim that make dev-k8s provides Skaffold
port-forwarding and state that access uses the kind NodePort mapping 30080 to
8080, unless an explicit portForward configuration is added.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 2a9b35ff-1f14-4d1c-a564-4eced617b880

📥 Commits

Reviewing files that changed from the base of the PR and between 503cdae and 17d225d.

⛔ Files ignored due to path filters (1)
  • helm/Chart.lock is excluded by !**/*.lock
📒 Files selected for processing (46)
  • .dockerignore
  • .github/workflows/helm-ci.yml
  • .github/workflows/helm-release.yml
  • .pre-commit-config.yaml
  • Dockerfile.dev
  • Makefile
  • deploy/helm/gomodel/.helmignore
  • deploy/helm/gomodel/Chart.yaml
  • deploy/helm/gomodel/README.md
  • deploy/helm/gomodel/ci/ingress-tls-values.yaml
  • deploy/helm/gomodel/ci/sqlite-persistent-values.yaml
  • deploy/helm/gomodel/ci/stateless-values.yaml
  • deploy/helm/gomodel/templates/NOTES.txt
  • deploy/helm/gomodel/templates/_helpers.tpl
  • deploy/helm/gomodel/templates/_pod.tpl
  • deploy/helm/gomodel/templates/configmap.yaml
  • deploy/helm/gomodel/templates/deployment.yaml
  • deploy/helm/gomodel/templates/hpa.yaml
  • deploy/helm/gomodel/templates/ingress.yaml
  • deploy/helm/gomodel/templates/networkpolicy.yaml
  • deploy/helm/gomodel/templates/pdb.yaml
  • deploy/helm/gomodel/templates/secret.yaml
  • deploy/helm/gomodel/templates/service.yaml
  • deploy/helm/gomodel/templates/serviceaccount.yaml
  • deploy/helm/gomodel/templates/servicemonitor.yaml
  • deploy/helm/gomodel/templates/statefulset.yaml
  • deploy/helm/gomodel/values.schema.json
  • deploy/helm/gomodel/values.yaml
  • deploy/local/deps.yaml
  • deploy/local/kind-cluster.yaml
  • deploy/local/mockllm.yaml
  • deploy/local/values.yaml
  • docs/DEVELOPMENT.md
  • docs/dev/local-kubernetes.md
  • helm/Chart.yaml
  • helm/README.md
  • helm/templates/NOTES.txt
  • helm/templates/_helpers.tpl
  • helm/templates/configmap.yaml
  • helm/templates/deployment.yaml
  • helm/templates/gateway.yaml
  • helm/templates/secret.yaml
  • helm/templates/servicemonitor.yaml
  • helm/values.schema.json
  • helm/values.yaml
  • skaffold.yaml
💤 Files with no reviewable changes (11)
  • helm/templates/secret.yaml
  • helm/templates/gateway.yaml
  • helm/Chart.yaml
  • helm/templates/deployment.yaml
  • helm/templates/NOTES.txt
  • helm/templates/servicemonitor.yaml
  • helm/templates/configmap.yaml
  • helm/templates/_helpers.tpl
  • helm/README.md
  • helm/values.yaml
  • helm/values.schema.json

name: Lint and template
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
if [ -f .github/workflows/helm-ci.yml ]; then
  nl -ba .github/workflows/helm-ci.yml | sed -n '1,110p'
else
  echo "missing .github/workflows/helm-ci.yml"
fi

echo
echo "== action uses lines =="
rg -n 'uses:\s*[^#\s]+' .github/workflows/helm-ci.yml || true

Repository: ENTERPILOT/GoModel

Length of output: 216


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
if [ -f .github/workflows/helm-ci.yml ]; then
  awk '{printf "%7d  %s\n", NR, $0}' .github/workflows/helm-ci.yml | sed -n '1,110p'
else
  echo "missing .github/workflows/helm-ci.yml"
fi

echo
echo "== action uses lines =="
grep -nE 'uses:\s*[^#\s]+' .github/workflows/helm-ci.yml || true

Repository: ENTERPILOT/GoModel

Length of output: 3983


Pin every GitHub Action to a full commit SHA.

Mutable action tags such as actions/checkout@v7, azure/setup-helm@v4, and helm/chart-testing-action@v2 can be retargeted to execute different code. Pin lines 29, 34, 55, 64, and 67 to reviewed full commit SHAs, and keep the version tag in a comment for maintenance.

🧰 Tools
🪛 zizmor (1.28.0)

[warning] 29-31: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 29-29: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-ci.yml at line 29, Pin the actions at lines 29, 34,
55, 64, and 67 to their reviewed full commit SHAs instead of mutable version
tags, while preserving each original version tag in an adjacent comment for
maintenance.

Source: Linters/SAST tools

Comment on lines +73 to +76
curl -sSL -o /tmp/kubeconform.tar.gz \
https://github.com/yannh/kubeconform/releases/download/v0.6.7/kubeconform-linux-amd64.tar.gz
tar -xzf /tmp/kubeconform.tar.gz -C /tmp
sudo mv /tmp/kubeconform /usr/local/bin/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

gh api repos/yannh/kubeconform/releases/tags/v0.6.7 \
  --jq '.assets[].name'

Repository: ENTERPILOT/GoModel

Length of output: 470


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

URL="https://github.com/yannh/kubeconform/releases/download/v0.6.7/kubeconform-linux-amd64.tar.gz"

printf 'asset URL reachable: '
curl -Ifs "$URL" > /tmp/kubeconform-check-url-reach.txt
curl -Ifs "$URL" | sed -n '1p'

printf '\nchecksum file URL reachable: '
GH="https://github.com/yannh/kubeconform/releases/download/v0.6.7/CHECKSUMS"
curl -Ifs "$GH" > /tmp/kubeconform-check-checksum-url.txt
curl -Ifs "$GH" | sed -n '1p'

printf '\nchecksum file first lines:\n'
curl -sf "$GH" | sed -n '1,20p'

printf '\nlocal workflow lines:\n'
sed -n '60,85p' .github/workflows/helm-ci.yml

Repository: ENTERPILOT/GoModel

Length of output: 1269


Verify the kubeconform checksum before installing.

This script downloads the release asset directly to /tmp, extracts it, and moves it onto PATH without comparing it against the upstream CHECKSUMS checksum file. Add a checksum verification step for kubeconform-linux-amd64.tar.gz before extraction.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-ci.yml around lines 73 - 76, Update the kubeconform
installation steps around the curl download and tar extraction to download the
release CHECKSUMS file, verify kubeconform-linux-amd64.tar.gz against its
expected checksum, and only extract and install after verification succeeds.
Keep the existing version and asset names consistent.

Comment on lines +82 to +86
for f in deploy/helm/gomodel/ci/*-values.yaml deploy/local/values.yaml; do
echo "Validating manifests rendered with $f"
helm template ci deploy/helm/gomodel -f "$f" \
| kubeconform -strict -ignore-missing-schemas -summary
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Validate the default chart render with kubeconform.

The workflow renders default values at line 45, but only named value files enter the kubeconform pipeline here. Add a no-values helm template validation before the loop. Otherwise, an invalid default-only manifest can pass CI.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-ci.yml around lines 82 - 86, Add a no-values helm
template validation before the existing values-file loop in the workflow, piping
the default render through kubeconform with the same strict, missing-schema, and
summary options. Keep the current named-values validation loop unchanged.

Comment on lines +24 to +25
- name: Checkout
uses: actions/checkout@v7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Harden the checkout/setup-helm pinning and secret usage.

Two independent hardening gaps:

  • actions/checkout@v7 (line 25) and azure/setup-helm@v4 (line 28) are pinned to mutable tags, not commit SHAs. A compromised or re-pointed tag would run arbitrary code in this release pipeline.
  • secrets.DOCKER_USERNAME/secrets.DOCKERHUB_TOKEN (lines 49-51) are interpolated directly into run: script text instead of passed through env:, unlike the DOCKER_USERNAME handling in the earlier "Resolve chart metadata" step (lines 38-39). Passing ${{ }} expressions through env: is the recommended pattern to avoid the value being spliced directly into the shell script.
🔒 Proposed fix for the login step
       - name: Login to Docker Hub (OCI)
+        env:
+          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
+          DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
         run: |
-          echo "${{ secrets.DOCKERHUB_TOKEN }}" \
+          echo "${DOCKERHUB_TOKEN}" \
             | helm registry login registry-1.docker.io \
-                --username "${{ secrets.DOCKER_USERNAME }}" --password-stdin
+                --username "${DOCKER_USERNAME}" --password-stdin

Also applies to: 28-28, 47-51

🧰 Tools
🪛 zizmor (1.28.0)

[warning] 24-25: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 25-25: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-release.yml around lines 24 - 25, Harden the release
workflow by pinning both actions/checkout and azure/setup-helm to immutable
commit SHAs instead of mutable version tags, and update the Docker login step to
receive DOCKER_USERNAME and DOCKERHUB_TOKEN through its env block rather than
interpolating secrets directly in the run script; preserve the existing
metadata-step environment handling.

Source: Linters/SAST tools

Comment on lines +27 to +30
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.16.3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What is the latest Helm v3 patch release?

💡 Result:

The latest Helm v3 patch release is v3.21.3, which was released on July 9, 2026 [1][2]. Helm v3 is currently in support mode, receiving only bug and security fixes [3]. The next scheduled patch release for Helm v3 is v3.21.4, planned for August 12, 2026 [1][2].

Citations:


Bump the pinned Helm version.

version: v3.16.3 is several patch releases behind current Helm v3.x patch releases. Bump to the latest supported v3.x patch version to pick up fixes.

🧰 Tools
🪛 zizmor (1.28.0)

[error] 28-28: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/helm-release.yml around lines 27 - 30, Update the version
value in the “Set up Helm” workflow step to the latest supported Helm v3.x patch
release, replacing the outdated v3.16.3 pin while preserving the existing
azure/setup-helm@v4 action configuration.

Comment on lines +4 to +6
# Access to the gateway is provided by Skaffold's port-forward (localhost:8080),
# so no NodePort/Ingress is required for the default workflow. The extra port
# mappings below are kept ready for an optional Ingress controller on 80/443.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd skaffold.yaml --exec cat -n {}

Repository: ENTERPILOT/GoModel

Length of output: 2113


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '--- deploy/local/kind-cluster.yaml ---\n'
cat -n deploy/local/kind-cluster.yaml

printf '\n--- deploy/local/values.yaml relevant service config ---\n'
rg -n -C 4 'service:|type:|nodePort:|port:' deploy/local/values.yaml || true

printf '\n--- docs/dev/local-kubernetes.md relevant gateway text ---\n'
rg -n -C 3 'localhost:8080|NodePort|skaffold' docs/dev/local-kubernetes.md || true

Repository: ENTERPILOT/GoModel

Length of output: 247


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- deploy/local/kind-cluster.yaml ---'
cat -n deploy/local/kind-cluster.yaml

printf '%s\n' ''
printf '%s\n' '--- deploy/local/values.yaml relevant service config ---'
rg -n -C 4 'service:|type:|nodePort:|port:' deploy/local/values.yaml || true

printf '%s\n' ''
printf '%s\n' '--- docs/dev/local-kubernetes.md relevant gateway text ---'
rg -n -C 3 'localhost:8080|NodePort|skaffold' docs/dev/local-kubernetes.md || true

Repository: ENTERPILOT/GoModel

Length of output: 4512


Fix the stale comment describing the local port mapping.

extraPortMappings maps containerPort: 30080 to hostPort: 8080, which matches service.type: NodePort and service.nodePort: 30080 in deploy/local/values.yaml. The gateway is reachable through this NodePort even without skaffold dev; update the comments at lines 4-6 and 12 to describe the NodePort mapping instead of Ingress/80-443.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy/local/kind-cluster.yaml` around lines 4 - 6, Update the comments in
the local kind cluster configuration, including the comment near
extraPortMappings, to describe gateway access through the NodePort mapping from
container port 30080 to host port 8080. Remove the stale claim that Skaffold
port-forwarding is required and that the mappings are reserved for an optional
80/443 Ingress controller.


Develop GoModel against a local [kind](https://kind.sigs.k8s.io/) cluster using
[Skaffold](https://skaffold.dev/) for a build → deploy → watch loop. The app is
deployed through the same production [Helm chart](../../deploy/helm/gomodel) with dev overrides,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use absolute GitHub URLs for links outside the docs/ tree.

Line 5 links to ../../deploy/helm/gomodel and line 103 links to ../../deploy/local/values.yaml. Both paths point outside the docs/ tree. Replace both with absolute GitHub URLs (e.g. https://github.com/ENTERPILOT/GoModel/blob/main/deploy/helm/gomodel).

Based on learnings, in the GoModel repo all Markdown files under the docs/ directory (including ADRs) that link to files outside the docs/ tree must use absolute GitHub URLs (e.g., https://github.com/ENTERPILOT/GoModel/blob/main/internal/...) instead of relative paths like ../../internal/....

Also applies to: 103-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/dev/local-kubernetes.md` at line 5, Update the external links in
docs/dev/local-kubernetes.md, including the Helm chart reference and the
deploy/local/values.yaml reference, to absolute GitHub URLs targeting the main
branch; preserve the existing link text and destinations.

Source: Learnings

Comment thread Makefile
Comment on lines +65 to +68
kind-up:
@kind get clusters | grep -qx "$(KIND_CLUSTER)" \
|| kind create cluster --config deploy/local/kind-cluster.yaml
@kubectl cluster-info --context kind-$(KIND_CLUSTER)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Makefile KIND references:"
if [ -f Makefile ]; then
  nl -ba Makefile | sed -n '1,110p'
else
  fd -a 'Makefile' . | sed -n '1,20p'
fi

echo
echo "Search KIND_CLUSTER and cluster-info/create commands:"
rg -n "KIND_CLUSTER|kind create cluster|cluster-info|kind-gomodel-dev|kind-\\$\\{KIND_CLUSTER\\}|kind-\\$\\(KIND_CLUSTER\\)" .

Repository: ENTERPILOT/GoModel

Length of output: 222


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Makefile candidates:"
find . -name Makefile -o -name makefile -o -name GNUmakefile | sort

echo
echo "Relevant Makefile content:"
if [ -f Makefile ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' Makefile | sed -n '1,120p'
fi

echo
echo "Search KIND_CLUSTER and kind commands:"
rg -n "KIND_CLUSTER|kind create cluster|cluster-info|kind-gomodel-dev|kind-\\$\\(KIND_CLUSTER\\)" -S . || true

echo
echo "Kind documentation/name semantics from local installed docs:"
if command -v kind >/dev/null 2>&1; then
  kind version 2>&1 || true
  kind create cluster --help 2>&1 | grep -A80 "^Usage:" || true
else
  echo "kind binary not installed"
fi

Repository: ENTERPILOT/GoModel

Length of output: 7004


🌐 Web query:

kind create cluster --name default cluster name kubectl config set-context kind-name

💡 Result:

When creating a cluster using kind, the tool automatically manages the Kubernetes configuration file (typically located at ~/.kube/config) and creates a context for you [1][2]. To create a cluster with a specific name, use the --name flag: kind create cluster --name By default, when you create a cluster, kind assigns it a context name prefixed with "kind-". For example, if you create a cluster with --name my-cluster, the resulting context name in your kubeconfig will be kind-my-cluster [3]. If you need to manually set or switch your kubectl context to this cluster, use the following command: kubectl config set-context kind- To verify or switch to the context, you can also use: kubectl config use-context kind- Kind automatically sets the current context to the new cluster upon creation, so you generally do not need to run these commands immediately after creating the cluster [3]. If your context is not found, ensure that you are running kubectl as the same user that created the kind cluster, as the kubeconfig file is written based on the user's home directory [4].

Citations:


Pass KIND_CLUSTER to kind create cluster.

The create command omits --name "$(KIND_CLUSTER)". If no gomodel-dev cluster exists, kind create cluster creates the default kind cluster and context. The following commands then use kind-gomodel-dev, so make kind-up fails on new setups.

Proposed fix
 	`@kind` get clusters | grep -qx "$(KIND_CLUSTER)" \
-		|| kind create cluster --config deploy/local/kind-cluster.yaml
+		|| kind create cluster --name "$(KIND_CLUSTER)" --config deploy/local/kind-cluster.yaml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
kind-up:
@kind get clusters | grep -qx "$(KIND_CLUSTER)" \
|| kind create cluster --config deploy/local/kind-cluster.yaml
@kubectl cluster-info --context kind-$(KIND_CLUSTER)
kind-up:
`@kind` get clusters | grep -qx "$(KIND_CLUSTER)" \
|| kind create cluster --name "$(KIND_CLUSTER)" --config deploy/local/kind-cluster.yaml
`@kubectl` cluster-info --context kind-$(KIND_CLUSTER)
🧰 Tools
🪛 checkmake (0.3.2)

[warning] 65-65: Target body for "kind-up" exceeds allowed length of 5 lines (9).

(maxbodylength)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 65 - 68, Update the kind create command in the kind-up
target to pass KIND_CLUSTER via the kind cluster name option, ensuring newly
created clusters and contexts match the existing kind-$(KIND_CLUSTER)
references.

Comment thread Makefile
Comment on lines +89 to +91
# Tear down the deployed release and dependencies.
undeploy-k8s:
skaffold delete --kube-context kind-$(KIND_CLUSTER)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the teardown scope description.

skaffold delete removes the Helm release only. It does not remove the dependency manifests applied by kind-up. State that dependencies remain until make kind-down, or delete them explicitly in this target.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 89 - 91, Update the comment above the undeploy-k8s
target to clarify that skaffold delete removes only the Helm release, while
dependency manifests remain until make kind-down; do not change the command
unless explicitly adding dependency deletion to this target.

Comment thread skaffold.yaml
Comment on lines +3 to +11
# make kind-up # one-time: create the kind cluster + deploy dependencies
# make dev-k8s # build + deploy + watch + port-forward (skaffold dev)
# make deploy-k8s # one-shot build + deploy (skaffold run)
# make undeploy-k8s # remove the release (skaffold delete)
#
# The in-cluster dependencies (Redis, PostgreSQL, MongoDB) are deployed by
# `make kind-up` (deploy/local/deps.yaml), so they persist across app redeploys.
# The gateway is reachable at http://localhost:8080 (Skaffold port-forward and,
# as a fallback, the kind NodePort mapping 30080 -> 8080).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Correct the local access instructions.

This configuration has no portForward block. make dev-k8s does not create Skaffold port forwarding. State that access uses the kind NodePort mapping, or add an explicit portForward configuration.

Also applies to: 44-46

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@skaffold.yaml` around lines 3 - 11, Correct the local gateway access comments
in the skaffold configuration: remove the claim that make dev-k8s provides
Skaffold port-forwarding and state that access uses the kind NodePort mapping
30080 to 8080, unless an explicit portForward configuration is added.

@greptile-apps

greptile-apps Bot commented Aug 1, 2026

Copy link
Copy Markdown

Confidence Score: 3/5

Not safe to merge: supported deployment configuration can break application availability, and the release workflow trusts mutable third-party code before registry publishing.

The reproduced failures affect independent paths: application routing for listener-port overrides, connectivity to documented external datastores when network isolation is enabled, and integrity of the credentialed chart-release process.

Files Needing Attention: deploy/helm/gomodel/templates/_pod.tpl, deploy/helm/gomodel/templates/networkpolicy.yaml, and .github/workflows/helm-release.yml

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex validated default port behavior by running a port-mismatch check and confirming 8080 as the standard port in the deployment templates.
  • T-Rex evaluated Helm-independent NetworkPolicy rendering, established a baseline with policy disabled, and observed the blocks when policy is enabled.
  • T-Rex inspected the workflow pinning and SHA-based immutability checks to ensure the pinned workflow tokens are immutable and ordered correctly.
  • T-Rex validated that NetworkPolicy is not enabled by default and documented the necessary changes to defaults; Helm CLI was unavailable, constraining the check.
  • T-Rex posted additional P1 findings proofs and generated corresponding artifacts for review.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (3)

  1. General comment

    P1 Helm probes and Service still target 8080 after configuring the application listener

    • Bug
      • Setting either config.server.port or env.PORT changes the resolved application port, but deploy/helm/gomodel/templates/_pod.tpl keeps the named http container port at 8080. The readiness/liveness/startup probes use that named port, and service.yaml targets it. A pod listening on a configured non-8080 port therefore fails HTTP probes and receives no Service traffic.
    • Cause
      • The chart exposes a fixed containerPort: 8080 rather than deriving the named port from the same listener configuration that is passed to the application through config or env.
    • Fix
      • Add a chart-level application/listen port value (or otherwise consistently resolve env.PORT/config.server.port) and use it for the named http containerPort; retain the probes and Service targetPort: http so they follow the corrected named port. Add render tests for both config.server.port and env.PORT non-8080 cases.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 Enabled NetworkPolicy denies documented external datastore egress

    • Bug
      • The egress allow-list at deploy/helm/gomodel/templates/networkpolicy.yaml:24-36 renders TCP/UDP 53 and TCP 443 only. With stateless external datastore settings, TCP PostgreSQL 5432, Redis 6379, and MongoDB 27017 are not selected by any egress rule and are denied by Kubernetes NetworkPolicy egress isolation.
    • Cause
      • The template uses two literal egress port lists and appends networkPolicy.extraEgress, whose default is an empty list. The documented stateless values configure external PostgreSQL and Redis without providing matching extra egress rules.
    • Fix
      • Add TCP 5432, TCP 6379, and TCP 27017 to the default egress rules (or derive rules from configured datastore backends). Preserve extraEgress for nonstandard destinations. Note that this behavior applies only when networkPolicy.enabled=true, because it defaults to false.

    T-Rex Ran code and verified through T-Rex

  3. General comment

    P1 Helm setup action is referenced through a mutable tag before registry credential use

    • Bug
      • azure/setup-helm@v4 at .github/workflows/helm-release.yml:28 is a symbolic tag, not a full 40-character commit SHA. This action executes before the workflow reads Docker Hub credentials, authenticates to Docker Hub, and pushes the OCI chart.
    • Cause
      • The workflow uses the mutable major-version tag v4 for a third-party GitHub Action.
    • Fix
      • Replace azure/setup-helm@v4 with the reviewed full commit SHA for the intended v4 release; retain the human-readable version in an adjacent comment if desired.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "Merge branch 'main' into feature/helm-re..." | Re-trigger Greptile

{{- end }}
ports:
- name: http
containerPort: 8080

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Helm routing ignores the configured listener port

config.server.port and env.PORT both change the application's listener port, but this template always declares the named http container port as 8080. The Service targets http and all HTTP probes use it, so a release configured to listen on any other port receives probes and Service traffic on 8080 instead. Derive the named container port from the effective listener-port configuration and add non-8080 render coverage.

Artifacts

Focused Helm port mismatch check source

  • Shell harness copied the focused Go check into the config package and executed it for default and configured port scenarios; it provides the repeatable verification entry point.

Focused Helm port mismatch Go check source

  • Go source executes the real configuration loader for config-file and environment port inputs and evaluates the implicated Helm pod and Service template invariants; it confirms the mismatch condition.

Default 8080 port verification output

  • Executed default-port run from `/home/user/repo` exited 0 and shows application configuration plus named-port, probe, and Service target all resolve to 8080; the default case is consistent.

Configured non-8080 port verification output

  • Executed configured-port run from `/home/user/repo` exited 0 and shows application ports 19091 and 19092 while the named port, probes, and Service target remain 8080; the mismatch is confirmed.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +24 to +36
egress:
# DNS resolution.
- to: []
ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
# Outbound HTTPS to provider APIs and external datastores.
- to: []
ports:
- port: 443
protocol: TCP

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Enabled NetworkPolicy blocks datastore connections

When networkPolicy.enabled=true, the default egress allowlist permits DNS and HTTPS only. The documented stateless deployment can use PostgreSQL, Redis, and MongoDB, but TCP ports 5432, 6379, and 27017 are not allowed, so those configured backends cannot connect unless every installation supplies matching extraEgress rules. Include the documented datastore ports in the defaults or derive the rules from the selected backend configuration.

Artifacts

Helm-independent NetworkPolicy render and egress evaluator source

  • Authored executable evaluator that merges the chart defaults with stateless values, verifies the relevant template guards, renders the literal egress rules, and checks datastore ports; it provides the reproducible check.

Baseline stateless render with NetworkPolicy disabled

  • Executed `python3 trex-artifacts/networkpolicy-stateless-check.py` in `/home/user/repo`; stateless defaults leave NetworkPolicy disabled and render no NetworkPolicy, establishing the default-enablement semantics.

Enabled NetworkPolicy render blocks PostgreSQL Redis and MongoDB

  • Executed `python3 trex-artifacts/networkpolicy-stateless-check.py --enable-policy` in `/home/user/repo`; the rendered egress rules expose only ports 53 and 443 and the check reports TCP 5432, 6379, and 27017 blocked, confirming the defect.

View artifacts

T-Rex Ran code and verified through T-Rex

uses: actions/checkout@v7

- name: Set up Helm
uses: azure/setup-helm@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Release setup action is not immutable

azure/setup-helm@v4 is a mutable tag and runs before this job reads Docker Hub credentials, authenticates to the registry, and publishes the OCI chart. Pin the action to the reviewed full commit SHA, retaining a version comment if useful, so a moved or compromised tag cannot execute unreviewed code in the release job.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Artifacts

Focused workflow pinning assertion source

  • Python assertion source executed against the workflow and a SHA-pinned comparison fixture; it checks the action ref format and exact credential/push ordering, with the takeaway that the check is reproducible.

Current workflow check showing mutable Helm action tag

  • Captured execution of the focused assertion on the current repository workflow; it reports `v4` at line 28 as a non-SHA tag before Docker credential use and OCI publishing, confirming the issue.

SHA-pinned comparison check

  • Captured execution of the same assertion against a same-scope SHA-pinned workflow copy; it classifies the 40-character ref as immutable while preserving the workflow ordering, showing the required remediation shape.

View artifacts

T-Rex Ran code and verified through T-Rex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants