feat: add feature branch deployments with per-branch isolation
Some checks failed
CI / build (push) Successful in 1m8s
CI / cleanup-branch (push) Has been skipped
CI / docker (push) Successful in 42s
CI / deploy (push) Failing after 5s
CI / deploy-feature (push) Has been skipped

Enable deploying feature branches into isolated environments on the same
k3s cluster. Each branch gets its own namespace (cam-<slug>), PostgreSQL
schema, and OpenSearch index prefix for data isolation while sharing the
underlying infrastructure.

- Make OpenSearch index prefix and DB schema configurable via env vars
  (defaults preserve existing behavior)
- Restructure deploy/ into Kustomize base + overlays (main/feature)
- Extend CI to build Docker images for all branches, not just main
- Add deploy-feature job with namespace creation, secret copying,
  Traefik Ingress routing (<slug>-api/ui.cameleer.siegeln.net)
- Add cleanup-branch job to remove namespace, PG schema, OS indices
  on branch deletion
- Install required tools (git, jq, curl) in CI deploy containers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-03-17 11:35:07 +01:00
parent 672544660f
commit 15f20d22ad
10 changed files with 573 additions and 21 deletions

View File

@@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: cameleer-branch-ingress
spec:
rules:
- host: BRANCH_SLUG-api.cameleer.siegeln.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cameleer3-server
port:
number: 8081
- host: BRANCH_SLUG.cameleer.siegeln.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: cameleer3-ui
port:
number: 80

View File

@@ -0,0 +1,30 @@
apiVersion: batch/v1
kind: Job
metadata:
name: init-schema
spec:
template:
spec:
restartPolicy: Never
containers:
- name: init
image: postgres:16
command: ["sh", "-c"]
args:
- |
PGPASSWORD=$POSTGRES_PASSWORD psql \
-h postgres.cameleer.svc.cluster.local \
-U $POSTGRES_USER -d cameleer3 \
-c "CREATE SCHEMA IF NOT EXISTS BRANCH_SCHEMA"
env:
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: postgres-credentials
key: POSTGRES_USER
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: POSTGRES_PASSWORD
backoffLimit: 3

View File

@@ -0,0 +1,44 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: BRANCH_NAMESPACE
resources:
- ../../base
- ingress.yaml
- init-job.yaml
images:
- name: gitea.siegeln.net/cameleer/cameleer3-server
newTag: BRANCH_SHA
- name: gitea.siegeln.net/cameleer/cameleer3-server-ui
newTag: BRANCH_SHA
patches:
# Server Deployment: branch-specific schema, index prefix, UI origin, OIDC disabled
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: cameleer3-server
spec:
template:
spec:
containers:
- name: server
env:
- name: CAMELEER_DB_SCHEMA
value: "BRANCH_SCHEMA"
- name: CAMELEER_OPENSEARCH_INDEX_PREFIX
value: "cam-BRANCH_SLUG-executions-"
- name: CAMELEER_UI_ORIGIN
value: "http://BRANCH_SLUG.cameleer.siegeln.net"
- name: CAMELEER_OIDC_ENABLED
value: "false"
# UI ConfigMap: branch-specific API URL
- target:
kind: ConfigMap
name: cameleer3-ui-config
patch: |
- op: replace
path: /data/config.js
value: |
window.__CAMELEER_CONFIG__ = {
apiBaseUrl: 'http://BRANCH_SLUG-api.cameleer.siegeln.net/api/v1',
};

View File

@@ -0,0 +1,57 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: cameleer
resources:
- ../../base
patches:
# Server Service: NodePort 30081
- target:
kind: Service
name: cameleer3-server
patch: |
- op: replace
path: /spec/type
value: NodePort
- op: add
path: /spec/ports/0/nodePort
value: 30081
# UI Service: NodePort 30090
- target:
kind: Service
name: cameleer3-ui
patch: |
- op: replace
path: /spec/type
value: NodePort
- op: add
path: /spec/ports/0/nodePort
value: 30090
# Server Deployment: same-namespace DNS + production UI origin
- patch: |
apiVersion: apps/v1
kind: Deployment
metadata:
name: cameleer3-server
spec:
template:
spec:
containers:
- name: server
env:
- name: SPRING_DATASOURCE_URL
value: "jdbc:postgresql://postgres:5432/cameleer3?currentSchema=public"
- name: OPENSEARCH_URL
value: "http://opensearch:9200"
- name: CAMELEER_UI_ORIGIN
value: "http://192.168.50.86:30090"
# UI ConfigMap: production API URL
- target:
kind: ConfigMap
name: cameleer3-ui-config
patch: |
- op: replace
path: /data/config.js
value: |
window.__CAMELEER_CONFIG__ = {
apiBaseUrl: 'http://192.168.50.86:30081/api/v1',
};