step 9: single image CI/CD, drop FE/BE split
Some checks failed
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-frontend (push) Failing after 5s
CI/CD / test-sqlite (push) Successful in 2m37s
CI/CD / test-go-pg (push) Successful in 1m53s
CI/CD / build-and-deploy (push) Has been skipped

CI pipeline: replace separate FE + BE image builds with single unified
Dockerfile. Remove FE_IMAGE, FE_REPLICAS, FE_* resource vars. Simplify
build/push/deploy to single IMAGE. Remove frontend.yaml k8s manifest.
Remove provider integration test env vars (PROVIDER, PROVIDER_KEY,
VENICE_API_KEY). Remove EXTRACTION_CONCURRENCY.

Delete server/Dockerfile (backend-only image, superseded by root
Dockerfile). Delete k8s/frontend.yaml (no separate FE deployment).

Update ROADMAP: steps 5-7 and 9 marked complete. Step 8 (ICD) partial.
Step 10 (smoke test + tag) is all that remains for v0.1.0.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 11:10:47 +00:00
parent ec750f4981
commit 71d448406c
4 changed files with 46 additions and 240 deletions

View File

@@ -2,8 +2,8 @@
# ============================================ # ============================================
# Switchboard Core - CI/CD Pipeline (v0.17.3) # Switchboard Core - CI/CD Pipeline (v0.17.3)
# ============================================ # ============================================
# Cluster deployments use SEPARATE FE + BE images. # Single unified image (Go backend + nginx frontend).
# Unified image is for Docker Hub only (docker-compose use). # v0.1.0: Dropped FE/BE image split per ROADMAP design decision.
# #
# Pipeline: # Pipeline:
# 0. Detect changes (path-based gating for all downstream jobs) # 0. Detect changes (path-based gating for all downstream jobs)
@@ -88,8 +88,7 @@ env:
CERT_ISSUER: ${{ vars.CERT_ISSUER_PROD || 'letsencrypt-prod' }} CERT_ISSUER: ${{ vars.CERT_ISSUER_PROD || 'letsencrypt-prod' }}
POSTGRES_HOST: ${{ vars.POSTGRES_HOST || 'postgres-primary.postgres.svc.cluster.local' }} POSTGRES_HOST: ${{ vars.POSTGRES_HOST || 'postgres-primary.postgres.svc.cluster.local' }}
POSTGRES_PORT: ${{ vars.POSTGRES_PORT || '5432' }} POSTGRES_PORT: ${{ vars.POSTGRES_PORT || '5432' }}
FE_IMAGE: ${{ vars.REGISTRY }}/xcaliber/switchboard-fe IMAGE: ${{ vars.REGISTRY }}/switchboard/core
BE_IMAGE: ${{ vars.REGISTRY }}/xcaliber/switchboard-be
DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_IMAGE || 'gobha/switchboard-core' }} DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_IMAGE || 'gobha/switchboard-core' }}
jobs: jobs:
@@ -297,12 +296,6 @@ jobs:
env: env:
GOPRIVATE: git.gobha.me/* GOPRIVATE: git.gobha.me/*
GONOSUMCHECK: git.gobha.me/* GONOSUMCHECK: git.gobha.me/*
# Generic provider config for live integration tests
PROVIDER: ${{ vars.PROVIDER }}
PROVIDER_KEY: ${{ secrets.PROVIDER_KEY }}
PROVIDER_URL: ${{ vars.PROVIDER_URL }}
# Legacy compat: VENICE_API_KEY still works if PROVIDER_KEY is not set
VENICE_API_KEY: ${{ secrets.VENICE_API_KEY }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -415,16 +408,11 @@ jobs:
echo "DEPLOY_SUFFIX=-dev" >> "$GITHUB_OUTPUT" echo "DEPLOY_SUFFIX=-dev" >> "$GITHUB_OUTPUT"
echo "DB_NAME=switchboard_core_dev" >> "$GITHUB_OUTPUT" echo "DB_NAME=switchboard_core_dev" >> "$GITHUB_OUTPUT"
echo "DB_WIPE=true" >> "$GITHUB_OUTPUT" echo "DB_WIPE=true" >> "$GITHUB_OUTPUT"
echo "FE_REPLICAS=1" >> "$GITHUB_OUTPUT" echo "REPLICAS=1" >> "$GITHUB_OUTPUT"
echo "BE_REPLICAS=1" >> "$GITHUB_OUTPUT" echo "MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_REQUEST=64Mi" >> "$GITHUB_OUTPUT" echo "MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_LIMIT=128Mi" >> "$GITHUB_OUTPUT" echo "CPU_REQUEST=50m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_REQUEST=25m" >> "$GITHUB_OUTPUT" echo "CPU_LIMIT=250m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_LIMIT=100m" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "BE_CPU_REQUEST=50m" >> "$GITHUB_OUTPUT"
echo "BE_CPU_LIMIT=250m" >> "$GITHUB_OUTPUT"
echo "env_label=dev (PR #${{ gitea.event.pull_request.number }})" >> "$GITHUB_OUTPUT" echo "env_label=dev (PR #${{ gitea.event.pull_request.number }})" >> "$GITHUB_OUTPUT"
elif [[ "${{ gitea.ref }}" == refs/tags/v* ]]; then elif [[ "${{ gitea.ref }}" == refs/tags/v* ]]; then
VERSION="${{ gitea.ref_name }}" VERSION="${{ gitea.ref_name }}"
@@ -436,16 +424,11 @@ jobs:
echo "DEPLOY_SUFFIX=" >> "$GITHUB_OUTPUT" echo "DEPLOY_SUFFIX=" >> "$GITHUB_OUTPUT"
echo "DB_NAME=switchboard_core" >> "$GITHUB_OUTPUT" echo "DB_NAME=switchboard_core" >> "$GITHUB_OUTPUT"
echo "DB_WIPE=false" >> "$GITHUB_OUTPUT" echo "DB_WIPE=false" >> "$GITHUB_OUTPUT"
echo "FE_REPLICAS=2" >> "$GITHUB_OUTPUT" echo "REPLICAS=2" >> "$GITHUB_OUTPUT"
echo "BE_REPLICAS=2" >> "$GITHUB_OUTPUT" echo "MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_REQUEST=64Mi" >> "$GITHUB_OUTPUT" echo "MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_LIMIT=128Mi" >> "$GITHUB_OUTPUT" echo "CPU_REQUEST=100m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_REQUEST=50m" >> "$GITHUB_OUTPUT" echo "CPU_LIMIT=500m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_LIMIT=200m" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "BE_CPU_REQUEST=100m" >> "$GITHUB_OUTPUT"
echo "BE_CPU_LIMIT=500m" >> "$GITHUB_OUTPUT"
echo "is_release=true" >> "$GITHUB_OUTPUT" echo "is_release=true" >> "$GITHUB_OUTPUT"
echo "env_label=production (${VERSION})" >> "$GITHUB_OUTPUT" echo "env_label=production (${VERSION})" >> "$GITHUB_OUTPUT"
else else
@@ -456,16 +439,11 @@ jobs:
echo "DEPLOY_SUFFIX=-test" >> "$GITHUB_OUTPUT" echo "DEPLOY_SUFFIX=-test" >> "$GITHUB_OUTPUT"
echo "DB_NAME=switchboard_core_test" >> "$GITHUB_OUTPUT" echo "DB_NAME=switchboard_core_test" >> "$GITHUB_OUTPUT"
echo "DB_WIPE=false" >> "$GITHUB_OUTPUT" echo "DB_WIPE=false" >> "$GITHUB_OUTPUT"
echo "FE_REPLICAS=1" >> "$GITHUB_OUTPUT" echo "REPLICAS=1" >> "$GITHUB_OUTPUT"
echo "BE_REPLICAS=1" >> "$GITHUB_OUTPUT" echo "MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_REQUEST=64Mi" >> "$GITHUB_OUTPUT" echo "MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "FE_MEMORY_LIMIT=128Mi" >> "$GITHUB_OUTPUT" echo "CPU_REQUEST=50m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_REQUEST=25m" >> "$GITHUB_OUTPUT" echo "CPU_LIMIT=250m" >> "$GITHUB_OUTPUT"
echo "FE_CPU_LIMIT=100m" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_REQUEST=256Mi" >> "$GITHUB_OUTPUT"
echo "BE_MEMORY_LIMIT=512Mi" >> "$GITHUB_OUTPUT"
echo "BE_CPU_REQUEST=50m" >> "$GITHUB_OUTPUT"
echo "BE_CPU_LIMIT=250m" >> "$GITHUB_OUTPUT"
echo "env_label=test (main)" >> "$GITHUB_OUTPUT" echo "env_label=test (main)" >> "$GITHUB_OUTPUT"
fi fi
@@ -577,45 +555,33 @@ jobs:
SQL SQL
echo "✓ Dev wipe complete — backend will rebuild schema on startup" echo "✓ Dev wipe complete — backend will rebuild schema on startup"
# ── Build Backend Image ────────────────────── # ── Build Unified Image ──────────────────────
- name: Build backend image - name: Build image
run: | run: |
docker build -f server/Dockerfile \ docker build -f Dockerfile \
-t ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} \ -t ${IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} \
.
# ── Build Frontend Image ─────────────────────
- name: Build frontend image
run: |
docker build -f Dockerfile.frontend \
-t ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} \
. .
# ── Tag release versions ───────────────────── # ── Tag release versions ─────────────────────
- name: Tag release versions - name: Tag release versions
if: steps.setup.outputs.EXTRA_TAG != '' if: steps.setup.outputs.EXTRA_TAG != ''
run: | run: |
docker tag ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${BE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }} docker tag ${IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
docker tag ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${FE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
# ── Push to Internal Registry ──────────────── # ── Push to Internal Registry ────────────────
- name: Push images - name: Push image
run: | run: |
docker push ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} docker push ${IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}
docker push ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}
if [[ -n "${{ steps.setup.outputs.EXTRA_TAG }}" ]]; then if [[ -n "${{ steps.setup.outputs.EXTRA_TAG }}" ]]; then
docker push ${BE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }} docker push ${IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
docker push ${FE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
fi fi
# ── Build + Push Unified to Docker Hub (release only) ── # ── Push to Docker Hub (release only) ────────
- name: Build and push unified image - name: Push to Docker Hub
if: steps.setup.outputs.is_release == 'true' if: steps.setup.outputs.is_release == 'true'
run: | run: |
docker build -f Dockerfile \ docker tag ${IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${DOCKERHUB_IMAGE}:latest
-t ${DOCKERHUB_IMAGE}:latest \ docker tag ${IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${DOCKERHUB_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
-t ${DOCKERHUB_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }} \
.
if [[ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then if [[ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then
echo "${{ secrets.DOCKERHUB_TOKEN }}" | \ echo "${{ secrets.DOCKERHUB_TOKEN }}" | \
docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
@@ -692,21 +658,15 @@ jobs:
DEPLOY_HOST: ${{ steps.setup.outputs.DEPLOY_HOST }} DEPLOY_HOST: ${{ steps.setup.outputs.DEPLOY_HOST }}
BASE_PATH: ${{ steps.setup.outputs.BASE_PATH }} BASE_PATH: ${{ steps.setup.outputs.BASE_PATH }}
DB_NAME: ${{ steps.setup.outputs.DB_NAME }} DB_NAME: ${{ steps.setup.outputs.DB_NAME }}
FE_REPLICAS: ${{ steps.setup.outputs.FE_REPLICAS }} REPLICAS: ${{ steps.setup.outputs.REPLICAS }}
BE_REPLICAS: ${{ steps.setup.outputs.BE_REPLICAS }} MEMORY_REQUEST: ${{ steps.setup.outputs.MEMORY_REQUEST }}
FE_MEMORY_REQUEST: ${{ steps.setup.outputs.FE_MEMORY_REQUEST }} MEMORY_LIMIT: ${{ steps.setup.outputs.MEMORY_LIMIT }}
FE_MEMORY_LIMIT: ${{ steps.setup.outputs.FE_MEMORY_LIMIT }} CPU_REQUEST: ${{ steps.setup.outputs.CPU_REQUEST }}
FE_CPU_REQUEST: ${{ steps.setup.outputs.FE_CPU_REQUEST }} CPU_LIMIT: ${{ steps.setup.outputs.CPU_LIMIT }}
FE_CPU_LIMIT: ${{ steps.setup.outputs.FE_CPU_LIMIT }}
BE_MEMORY_REQUEST: ${{ steps.setup.outputs.BE_MEMORY_REQUEST }}
BE_MEMORY_LIMIT: ${{ steps.setup.outputs.BE_MEMORY_LIMIT }}
BE_CPU_REQUEST: ${{ steps.setup.outputs.BE_CPU_REQUEST }}
BE_CPU_LIMIT: ${{ steps.setup.outputs.BE_CPU_LIMIT }}
# Storage (v0.12.0+) # Storage (v0.12.0+)
STORAGE_CLASS: ${{ vars.STORAGE_CLASS }} STORAGE_CLASS: ${{ vars.STORAGE_CLASS }}
STORAGE_SIZE: ${{ vars.STORAGE_SIZE || '10Gi' }} STORAGE_SIZE: ${{ vars.STORAGE_SIZE || '10Gi' }}
STORAGE_BACKEND: ${{ vars.STORAGE_BACKEND || 'pvc' }} STORAGE_BACKEND: ${{ vars.STORAGE_BACKEND || 'pvc' }}
EXTRACTION_CONCURRENCY: ${{ vars.EXTRACTION_CONCURRENCY || '3' }}
run: | run: |
# Render PVC first (must exist before backend references it) # Render PVC first (must exist before backend references it)
if [[ -n "${STORAGE_CLASS}" ]]; then if [[ -n "${STORAGE_CLASS}" ]]; then
@@ -714,7 +674,6 @@ jobs:
fi fi
envsubst < k8s/backend.yaml > /tmp/backend.yaml envsubst < k8s/backend.yaml > /tmp/backend.yaml
envsubst < k8s/frontend.yaml > /tmp/frontend.yaml
envsubst < k8s/middleware-retry.yaml > /tmp/middleware-retry.yaml envsubst < k8s/middleware-retry.yaml > /tmp/middleware-retry.yaml
envsubst < k8s/ingress.yaml > /tmp/ingress.yaml envsubst < k8s/ingress.yaml > /tmp/ingress.yaml
@@ -729,7 +688,6 @@ jobs:
fi fi
kubectl apply -f /tmp/backend.yaml kubectl apply -f /tmp/backend.yaml
kubectl apply -f /tmp/frontend.yaml
# Traefik retry middleware (v0.28.8) — requires RBAC for traefik.io CRDs. # Traefik retry middleware (v0.28.8) — requires RBAC for traefik.io CRDs.
# First-time setup: kubectl apply -f k8s/rbac-traefik.yaml (cluster admin) # First-time setup: kubectl apply -f k8s/rbac-traefik.yaml (cluster admin)
@@ -760,23 +718,19 @@ jobs:
SUFFIX: ${{ steps.setup.outputs.DEPLOY_SUFFIX }} SUFFIX: ${{ steps.setup.outputs.DEPLOY_SUFFIX }}
ENV: ${{ steps.setup.outputs.ENVIRONMENT }} ENV: ${{ steps.setup.outputs.ENVIRONMENT }}
run: | run: |
kubectl rollout restart deployment/switchboard-be${SUFFIX} -n ${NAMESPACE} kubectl rollout restart deployment/switchboard${SUFFIX} -n ${NAMESPACE}
kubectl rollout restart deployment/switchboard-fe${SUFFIX} -n ${NAMESPACE} kubectl rollout status deployment/switchboard${SUFFIX} -n ${NAMESPACE} --timeout=180s
kubectl rollout status deployment/switchboard-be${SUFFIX} -n ${NAMESPACE} --timeout=180s
kubectl rollout status deployment/switchboard-fe${SUFFIX} -n ${NAMESPACE} --timeout=180s
echo "" echo ""
echo "━━━ Pod Status ━━━" echo "━━━ Pod Status ━━━"
kubectl get pods -n ${NAMESPACE} -l app=switchboard,env=${ENV} kubectl get pods -n ${NAMESPACE} -l app=switchboard,env=${ENV}
BE_READY=$(kubectl get deployment switchboard-be${SUFFIX} -n ${NAMESPACE} -o jsonpath='{.status.readyReplicas}') READY=$(kubectl get deployment switchboard${SUFFIX} -n ${NAMESPACE} -o jsonpath='{.status.readyReplicas}')
FE_READY=$(kubectl get deployment switchboard-fe${SUFFIX} -n ${NAMESPACE} -o jsonpath='{.status.readyReplicas}')
if [[ "${BE_READY:-0}" -gt 0 ]] && [[ "${FE_READY:-0}" -gt 0 ]]; then if [[ "${READY:-0}" -gt 0 ]]; then
echo "✅ Healthy: BE=${BE_READY} FE=${FE_READY} pods ready" echo "✅ Healthy: ${READY} pods ready"
else else
echo "❌ Unhealthy: BE=${BE_READY:-0} FE=${FE_READY:-0}" echo "❌ Unhealthy: ${READY:-0} pods ready"
kubectl logs -n ${NAMESPACE} -l app=switchboard,env=${ENV} --tail=30 kubectl logs -n ${NAMESPACE} -l app=switchboard,env=${ENV} --tail=30
exit 1 exit 1
fi fi

View File

@@ -14,11 +14,11 @@ platform that extensions build on.
| 2. Delete packages | ✅ | 15 Go packages, 29 handler files removed | | 2. Delete packages | ✅ | 15 Go packages, 29 handler files removed |
| 3. Gut stores/models | ✅ | 40 → 20 store interfaces, kernel-only models | | 3. Gut stores/models | ✅ | 40 → 20 store interfaces, kernel-only models |
| 4. Fresh migrations | ✅ | 9 files × 2 dialects, 27 tables | | 4. Fresh migrations | ✅ | 9 files × 2 dialects, 27 tables |
| 5. Fix compilation | 🔧 | ~95% done, ~5 compile errors remaining | | 5. Fix compilation | | `go build ./...` clean, 300+ stale route lines cut |
| 6. Fix tests | | Prune 13K test lines to kernel-only | | 6. Fix tests | | 8 test packages pass, ~12K stale test lines pruned |
| 7. Frontend gut | | Shell + SDK only, vendor libs baked | | 7. Frontend gut | | Shell + SDK only, 50+ files of chat/notes/projects code removed |
| 8. New ICD | | Kernel-only API spec | | 8. New ICD | 🔧 | Stub in place, full kernel-only spec TBD |
| 9. CI/CD + Dockerfile | | Single image, new DB names | | 9. CI/CD + Dockerfile | | Single unified image, FE/BE split removed, DB names updated |
| 10. Smoke test + tag | ⬜ | Deploy, verify, tag v0.1.0 | | 10. Smoke test + tag | ⬜ | Deploy, verify, tag v0.1.0 |
## v0.2.0 — SDK & Triggers ## v0.2.0 — SDK & Triggers

View File

@@ -1,99 +0,0 @@
# k8s/frontend.yaml
# ============================================
# Switchboard Core - Frontend Deployment
# ============================================
# nginx serving the SPA + proxying page routes
# to the backend for Go template rendering.
#
# v0.22.6+: BACKEND_URL enables proxy_pass for
# /, /login, /admin, /editor, /notes, /settings.
# ============================================
apiVersion: apps/v1
kind: Deployment
metadata:
name: switchboard-fe${DEPLOY_SUFFIX}
namespace: ${NAMESPACE}
labels:
app: switchboard
component: frontend
env: ${ENVIRONMENT}
spec:
replicas: ${FE_REPLICAS}
selector:
matchLabels:
app: switchboard
component: frontend
env: ${ENVIRONMENT}
template:
metadata:
labels:
app: switchboard
component: frontend
env: ${ENVIRONMENT}
spec:
containers:
- name: frontend
image: ${FE_IMAGE}:${IMAGE_TAG}
imagePullPolicy: Always
ports:
- containerPort: 80
name: http
env:
- name: BASE_PATH
value: "${BASE_PATH}"
- name: ENVIRONMENT
value: "${ENVIRONMENT}"
- name: BACKEND_URL
value: "http://switchboard-be${DEPLOY_SUFFIX}:8080"
volumeMounts:
- name: branding
mountPath: /branding
readOnly: true
resources:
requests:
memory: "${FE_MEMORY_REQUEST}"
cpu: "${FE_CPU_REQUEST}"
limits:
memory: "${FE_MEMORY_LIMIT}"
cpu: "${FE_CPU_LIMIT}"
readinessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 3
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 5
periodSeconds: 30
timeoutSeconds: 5
failureThreshold: 3
volumes:
- name: branding
configMap:
name: switchboard-branding
optional: true
---
apiVersion: v1
kind: Service
metadata:
name: switchboard-fe${DEPLOY_SUFFIX}
namespace: ${NAMESPACE}
labels:
app: switchboard
component: frontend
env: ${ENVIRONMENT}
spec:
selector:
app: switchboard
component: frontend
env: ${ENVIRONMENT}
ports:
- protocol: TCP
port: 80
targetPort: 80
name: http

View File

@@ -1,49 +0,0 @@
# ==========================================
# Switchboard Core - Backend Dockerfile
# ==========================================
# Standalone Go API server for cluster deployment.
# Build context is the repo root (not ./server).
# ==========================================
# Build stage
FROM golang:1.23-bookworm AS builder
ARG APP_VERSION=dev
WORKDIR /app
# Copy module files and download deps
COPY server/go.mod server/go.sum* ./
RUN go mod download
# Copy source and tidy (resolves any go.sum gaps)
COPY server/ .
RUN go mod tidy
# Copy VERSION from repo root — used by ldflags and copied to runtime image.
# If APP_VERSION build-arg was supplied by CI, it takes precedence via ldflags.
# If not, $(cat VERSION) reads the file directly so the binary always has a real version.
COPY VERSION ./
RUN CGO_ENABLED=0 go build -ldflags="-s -w -X main.Version=$(cat VERSION)" -o /bin/switchboard .
# Runtime stage
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /bin/switchboard /usr/local/bin/switchboard
COPY --from=builder /app/database/migrations /app/database/migrations
# VERSION file at /VERSION — version.go init() reads it as fallback for local/dev runs
COPY --from=builder /app/VERSION /VERSION
# Builtin extensions (seeded into DB on startup)
COPY extensions/builtin/ /app/extensions/builtin/
WORKDIR /app
EXPOSE 8080
ENTRYPOINT ["switchboard"]