Skip to content

feat: implement automated secret injection and NestJS Prisma template…#53

Merged
PhuocHoan merged 3 commits into
features/database-persistencefrom
users/hph/feat/automated-secret-injection
Mar 16, 2026
Merged

feat: implement automated secret injection and NestJS Prisma template…#53
PhuocHoan merged 3 commits into
features/database-persistencefrom
users/hph/feat/automated-secret-injection

Conversation

@PhuocHoan
Copy link
Copy Markdown
Collaborator

Summary

  • Add Phase 0.9 to the operator reconcile loop that injects DB_HOST, DB_USER, DB_PASS env vars (via secretKeyRef) into backend Deployments created by ArgoCD
  • Create a NestJS + Prisma Backstage scaffolder template with Prisma 7 driver adapter support, compatible with the operator's secret injection
  • Add manual verification guide for testing on a k3d cluster
  • Add Claude Code skills for implementation workflow and Go/CUE coding guidelines

Operator — Secret Injection (Phase 0.9)

  • InjectDatabaseEnvVars() — patches a Deployment's first container with DB_HOST, DB_USER, DB_PASS as secretKeyRef entries. Idempotent: skips if vars already exist.
  • reconcileDatabaseSecretInjection() — finds components with database traits, fetches the live Deployment, injects env vars, gracefully skips if Deployment doesn't exist yet (ArgoCD hasn't synced)
  • 6 new unit/integration tests covering injection, idempotency, empty containers, missing deployments, and full reconcile flow
  • RBAC role updated for statefulsets and ingresses

NestJS Prisma Template

  • Full Backstage scaffolder template (template.yaml + source + GitOps manifest)
  • Prisma 7 compatible: uses prisma.config.ts with defineConfig() instead of url in schema.prisma
  • PrismaService uses @prisma/adapter-pg with namespace import (import * as pg from 'pg') for CommonJS compatibility
  • Multi-stage Dockerfile with prisma migrate deploy at startup
  • Database trait in GitOps manifest triggers operator provisioning

Version Bumps

  • golangci-lint v2.10.1 → v2.11.3
  • CUE language v0.15.4 → v0.16.0
  • Go module dependencies updated

Manually Verified on k3d

All acceptance criteria passed on a local k3d cluster:

  • kubectl describe pod <backend-pod> shows DB_HOST, DB_USER, DB_PASS mounted via secretKeyRef
  • Postgres StatefulSet + headless Service created and healthy
  • NestJS server connects to DB, runs Prisma migrations, responds to health checks

See docs/manual-verification-guide.md for full reproduction steps.

Test plan

  • go build ./... compiles cleanly
  • go vet ./... passes
  • make test — all existing + 6 new tests pass
  • Follow docs/manual-verification-guide.md to reproduce k3d verification

…#39)

Add Phase 0.9 to the operator reconcile loop that injects DB_HOST, DB_USER,
DB_PASS env vars (via secretKeyRef) into backend Deployments. Create a
NestJS + Prisma Backstage template with Prisma 7 driver adapter support.

Operator changes:
- Add InjectDatabaseEnvVars() and reconcileDatabaseSecretInjection() to
  patch live Deployments with database credential references
- Add 6 unit/integration tests for injection logic (idempotency, empty
  containers, missing deployments)
- Update RBAC role for statefulsets and ingresses
- Bump golangci-lint to v2.11.3, CUE language to v0.16.0

NestJS Prisma template:
- Full Backstage scaffolder template with NestJS 11 + Prisma 7 + pg adapter
- prisma.config.ts for Prisma 7 datasource URL (replaces schema.prisma url)
- PrismaService with namespace import (import * as pg) for CommonJS compat
- Multi-stage Dockerfile with migration support
- Helios GitOps manifest with database trait

Documentation:
- Manual verification guide for k3d cluster testing
- Implementation plan, task tracking, and walkthrough docs
- Claude Code skills for implementation workflow and Go/CUE guidelines

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 15, 2026 03:55
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 15, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: daecbca0-a1ca-4922-875c-b74aa3a3064e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch users/hph/feat/automated-secret-injection
📝 Coding Plan
  • Generate coding plan for human review comments

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

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

@PhuocHoan PhuocHoan linked an issue Mar 15, 2026 that may be closed by this pull request
@PhuocHoan PhuocHoan requested a review from NgocAnhDo26 March 15, 2026 04:00
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements operator-side secret injection of database credentials into ArgoCD-managed backend Deployments (Phase 0.9), and adds a Backstage scaffolder template for a NestJS + Prisma service designed to consume those injected env vars, along with supporting docs and dependency/version bumps.

Changes:

  • Add Phase 0.9 reconcile step to inject DB_HOST, DB_USER, DB_PASS into live Deployments via secretKeyRef.
  • Add NestJS + Prisma Backstage template + GitOps HeliosApp manifest aligned with the injected env vars.
  • Add verification/docs plus dependency/version updates (Go/CUE/tooling).

Reviewed changes

Copilot reviewed 33 out of 35 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
walkthrough.md Walkthrough document for the feature implementation (includes code references).
task.md Implementation checklist for secret injection + template work.
implementation_plan.md Design/plan document describing the approach and test plan.
docs/manual-verification-guide.md Step-by-step manual verification guide for k3d testing.
cue/cue.mod/module.cue Bumps CUE language version to v0.16.0.
apps/portal/examples/nestjs-prisma-template/template.yaml Adds Backstage scaffolder template for NestJS + Prisma + GitOps flow.
apps/portal/examples/nestjs-prisma-template/content/source/tsconfig.json Adds TS compiler config for generated NestJS service.
apps/portal/examples/nestjs-prisma-template/content/source/tsconfig.build.json Adds build TS config exclusions.
apps/portal/examples/nestjs-prisma-template/content/source/src/prisma/prisma.service.ts Adds PrismaService using Prisma adapter-pg + pg Pool (env-driven).
apps/portal/examples/nestjs-prisma-template/content/source/src/prisma/prisma.module.ts Adds global Prisma module exporting PrismaService.
apps/portal/examples/nestjs-prisma-template/content/source/src/main.ts Adds NestJS bootstrap entrypoint for template.
apps/portal/examples/nestjs-prisma-template/content/source/src/app.service.ts Adds basic app service + health response in template.
apps/portal/examples/nestjs-prisma-template/content/source/src/app.module.ts Adds NestJS root module wiring Prisma + controllers/providers.
apps/portal/examples/nestjs-prisma-template/content/source/src/app.controller.ts Adds hello + health endpoints for template.
apps/portal/examples/nestjs-prisma-template/content/source/prisma/schema.prisma Adds Prisma schema (Prisma 7-style datasource config approach).
apps/portal/examples/nestjs-prisma-template/content/source/prisma/migrations/migration_lock.toml Adds Prisma migrate lock file.
apps/portal/examples/nestjs-prisma-template/content/source/prisma.config.ts Adds Prisma config that builds datasource URL from injected env vars.
apps/portal/examples/nestjs-prisma-template/content/source/package.json Adds NestJS/Prisma/pg dependencies and scripts for template.
apps/portal/examples/nestjs-prisma-template/content/source/nest-cli.json Adds Nest CLI config for template.
apps/portal/examples/nestjs-prisma-template/content/source/catalog-info.yaml Adds Backstage catalog metadata for generated service.
apps/portal/examples/nestjs-prisma-template/content/source/Dockerfile Adds multi-stage Dockerfile that runs prisma migrate deploy at startup.
apps/portal/examples/nestjs-prisma-template/content/source/.env.example Adds example env vars for local/dev use.
apps/portal/examples/nestjs-prisma-template/content/gitops/helios-app.yaml Adds HeliosApp manifest w/ database trait to trigger provisioning + injection.
apps/operator/internal/controller/heliosapp_controller.go Adds Phase 0.9 call into the reconcile loop.
apps/operator/internal/controller/database_resources_test.go Adds tests for env-var injection and reconcile flow; minor typing updates (any).
apps/operator/internal/controller/database_resources.go Adds InjectDatabaseEnvVars + reconcileDatabaseSecretInjection.
apps/operator/go.mod Bumps Go/CUE/controller-runtime deps and Go directive.
apps/operator/go.sum Updates module sums to match dependency bumps.
apps/operator/config/rbac/role.yaml Updates RBAC to include statefulsets/ingresses.
apps/operator/config/manager/kustomization.yaml Changes manager image mapping to helios-operator:local.
apps/operator/Makefile Bumps golangci-lint version.
.claude/skills/use-modern-go/SKILL.md Adds Claude skill guidance for modern Go usage in this repo.
.claude/skills/use-modern-cue/SKILL.md Adds Claude skill guidance for modern CUE usage in this repo.
.claude/skills/implement-task/SKILL.md Adds Claude workflow guidance for implementing tasks in this repo.
Comments suppressed due to low confidence (1)

apps/operator/config/rbac/role.yaml:70

  • role.yaml is generated by controller-gen (make manifests). If statefulsets/ingresses permissions are required, they should be added via +kubebuilder:rbac markers in the controller source; otherwise the next controller-gen run will likely overwrite this manual edit and drop the extra resources.
- apiGroups:
  - apps
  resources:
  - deployments
  - statefulsets
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +469 to +491
// Build a set of existing env var names for fast lookup.
existingEnvs := make(map[string]bool, len(container.Env))
for _, ev := range container.Env {
existingEnvs[ev.Name] = true
}

changed := false
for _, envName := range databaseEnvVarNames {
if existingEnvs[envName] {
continue
}
container.Env = append(container.Env, corev1.EnvVar{
Name: envName,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: secretName,
},
Key: envName,
},
},
})
changed = true
Comment on lines +5 to +8
images:
- name: controller
newName: helios-operator
newTag: local
Comment thread task.md Outdated
Comment on lines +5 to +7
- [x] Research codebase and understand existing patterns
- [x] Implement [reconcileDatabaseSecretInjection](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go#497-552) in Go operator
- [x] Add new phase (0.9) to inject DB_HOST, DB_USER, DB_PASS into backend Deployment env block
Comment thread implementation_plan.md Outdated
Comment on lines +11 to +23
**Approach**: Add a new reconciliation phase (**Phase 0.9**) in [heliosapp_controller.go](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/heliosapp_controller.go) that **patches the live Deployment** (deployed by ArgoCD) to inject `DB_HOST`, `DB_USER`, and `DB_PASS` as `envFrom` / env vars referencing the K8s Secret. This runs AFTER database secrets and instances are created.

> [!IMPORTANT]
> The CUE engine generates the base Deployment manifest (pushed via GitOps). The Go operator patches the **live Deployment** in-cluster to add secret env vars. This keeps secrets out of the GitOps repo entirely.

#### [MODIFY] [database_resources.go](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go)

Add a new function `InjectDatabaseEnvVars` that:
- Takes a Deployment and a database secret name
- Adds `DB_HOST`, `DB_USER`, `DB_PASS` env vars to the first container using `valueFrom.secretKeyRef`
- Also adds `DATABASE_URL` as a convenience env var for Prisma ORM (constructed from the other vars via an init container or as a direct string referencing the secret values)
- Is idempotent: skips if env vars already exist

Comment on lines +130 to +140
// ------------------------------------------------------------------
// PHASE 0.9: Inject Database Credentials into Backend Deployment
// Patches the live Deployment (deployed by ArgoCD) to add DB_HOST,
// DB_USER, DB_PASS env vars referencing the operator-managed Secret.
// Runs AFTER secrets and instances so the Secret already exists.
// ------------------------------------------------------------------
if err := r.reconcileDatabaseSecretInjection(ctx, &heliosApp); err != nil {
log.Error(err, "Failed to inject database secrets into Deployment")
r.updateStatus(ctx, &heliosApp, appv1alpha1.PhaseFailed, fmt.Sprintf("Database secret injection failed: %v", err))
return ctrl.Result{}, err
}
Comment on lines +538 to +542
}

if err := r.Update(ctx, deploy); err != nil {
return fmt.Errorf("failed to update Deployment %s with database env vars: %w", deployName, err)
}
Comment on lines +7 to +11
const port = process.env.PORT || ${{ values.port }
};
await app.listen(port);

console.log(`🚀 Application is running on port ${port}`);
Comment thread walkthrough.md Outdated
Comment on lines +7 to +10
#### [database_resources.go](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go)

- **[InjectDatabaseEnvVars](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go#458-496)** — Patches a Deployment's first container with `DB_HOST`, `DB_USER`, `DB_PASS` env vars via `secretKeyRef`. Idempotent: skips if vars already exist.
- **[reconcileDatabaseSecretInjection](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go#497-552)** — Finds components with database traits, fetches the live Deployment, calls [InjectDatabaseEnvVars](file:///home/phuochoan/Workspace/HCMUS/4th_Year/Capstone_Projects/helios-platform/apps/operator/internal/controller/database_resources.go#458-496), and updates it. Gracefully skips if Deployment doesn't exist yet (ArgoCD hasn't synced).
name: ${{ values.name }}
description: ${{ values.description }}
annotations:
github.com/project-slug: ${{ values.destination.owner + "/" + values.destination.repo }}
PhuocHoan and others added 2 commits March 15, 2026 17:31
PR review fixes:
- Validate existing env var sources in InjectDatabaseEnvVars, not just names
- Revert accidental local-dev image tag in kustomization.yaml
- Requeue when Deployment is missing for database secret injection
- Add ArgoCD ignoreDifferences to prevent self-heal reverting injected env vars
- Fix broken NestJS template main.ts syntax
- Fix catalog-info.yaml referencing undefined template variables
- Remove committed planning docs (task.md, implementation_plan.md, walkthrough.md)

Go 1.26.1 modernization:
- Update Dockerfile and devcontainer from golang:1.24 to golang:1.26
- Use t.Context() instead of context.Background() in tests
- Use for-range over integers instead of C-style loops
- Use strings.SplitSeq instead of strings.Split in for-range
- Update Go version references in documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@PhuocHoan PhuocHoan merged commit ab0a6a7 into features/database-persistence Mar 16, 2026
1 check passed
@PhuocHoan PhuocHoan deleted the users/hph/feat/automated-secret-injection branch March 16, 2026 02:37
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.

[Impl] Automated Secret Injection

2 participants