From b1613501a44dc441c6526a4e6a9766a67d768eb8 Mon Sep 17 00:00:00 2001 From: dvirlabs Date: Wed, 17 Dec 2025 06:30:48 +0200 Subject: [PATCH] Create first test app --- .woodpecker.yaml | 121 ++++++++++++++++++++++++++++++++++++ HELM_CHART_UPDATE.md | 90 +++++++++++++++++++++++++++ helm/dating-app/values.yaml | 8 +-- 3 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 .woodpecker.yaml create mode 100644 HELM_CHART_UPDATE.md diff --git a/.woodpecker.yaml b/.woodpecker.yaml new file mode 100644 index 0000000..3d68271 --- /dev/null +++ b/.woodpecker.yaml @@ -0,0 +1,121 @@ +steps: + build-frontend: + name: Build & Push Frontend + image: woodpeckerci/plugin-kaniko + when: + branch: [ master, develop ] + event: [ push, pull_request, tag ] + path: + include: [ frontend/** ] + settings: + registry: harbor.dvirlabs.com + repo: my-apps/${CI_REPO_NAME}-frontend + dockerfile: frontend/Dockerfile + context: frontend + tags: + - latest + - ${CI_COMMIT_TAG:-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:7}} + username: + from_secret: DOCKER_USERNAME + password: + from_secret: DOCKER_PASSWORD + + build-backend: + name: Build & Push Backend + image: woodpeckerci/plugin-kaniko + when: + branch: [ master, develop ] + event: [ push, pull_request, tag ] + path: + include: [ backend/** ] + settings: + registry: harbor-core.dev-tools.svc.cluster.local + repo: my-apps/${CI_REPO_NAME}-backend + dockerfile: backend/Dockerfile + context: backend + tags: + - latest + - ${CI_COMMIT_TAG:-${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:7}} + username: + from_secret: DOCKER_USERNAME + password: + from_secret: DOCKER_PASSWORD + + update-values-frontend: + name: Update frontend tag in values.yaml + image: alpine:3.19 + when: + branch: [ master, develop ] + event: [ push ] + path: + include: [ frontend/** ] + environment: + GIT_USERNAME: + from_secret: GIT_USERNAME + GIT_TOKEN: + from_secret: GIT_TOKEN + commands: + - apk add --no-cache git yq + - git config --global user.name "woodpecker-bot" + - git config --global user.email "ci@dvirlabs.com" + - git clone "https://$${GIT_USERNAME}:$${GIT_TOKEN}@git.dvirlabs.com/dvirlabs/my-apps.git" + - cd my-apps + - | + TAG="${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:7}" + echo "💡 Setting frontend tag to: $TAG" + yq -i ".frontend.image.tag = \"$TAG\"" manifests/${CI_REPO_NAME}/values.yaml + git add manifests/${CI_REPO_NAME}/values.yaml + git commit -m "frontend: update tag to $TAG" || echo "No changes" + git push origin HEAD + + update-values-backend: + name: Update backend tag in values.yaml + image: alpine:3.19 + when: + branch: [ master, develop ] + event: [ push ] + path: + include: [ backend/** ] + environment: + GIT_USERNAME: + from_secret: GIT_USERNAME + GIT_TOKEN: + from_secret: GIT_TOKEN + commands: + - apk add --no-cache git yq + - git config --global user.name "woodpecker-bot" + - git config --global user.email "ci@dvirlabs.com" + - | + if [ ! -d "my-apps" ]; then + git clone "https://$${GIT_USERNAME}:$${GIT_TOKEN}@git.dvirlabs.com/dvirlabs/my-apps.git" + fi + - cd my-apps + - | + TAG="${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA:0:7}" + echo "💡 Setting backend tag to: $TAG" + yq -i ".backend.image.tag = \"$TAG\"" manifests/${CI_REPO_NAME}/values.yaml + git add manifests/${CI_REPO_NAME}/values.yaml + git commit -m "backend: update tag to $TAG" || echo "No changes" + git push origin HEAD + + + trigger-gitops-via-push: + when: + branch: [ master, develop ] + event: [ push ] + name: Trigger apps-gitops via Git push + image: alpine/git + environment: + GIT_USERNAME: + from_secret: GIT_USERNAME + GIT_TOKEN: + from_secret: GIT_TOKEN + commands: | + git config --global user.name "woodpecker-bot" + git config --global user.email "ci@dvirlabs.com" + git clone "https://$${GIT_USERNAME}:$${GIT_TOKEN}@git.dvirlabs.com/dvirlabs/apps-gitops.git" + cd apps-gitops + echo "# trigger at $(date) by $${CI_REPO_NAME}" >> .trigger + git add .trigger + git commit -m "ci: trigger apps-gitops build" || echo "no changes" + git push origin HEAD \ No newline at end of file diff --git a/HELM_CHART_UPDATE.md b/HELM_CHART_UPDATE.md new file mode 100644 index 0000000..18d0470 --- /dev/null +++ b/HELM_CHART_UPDATE.md @@ -0,0 +1,90 @@ +# Helm Chart Update Summary + +## Overview +The Helm chart has been updated to deploy a complete dating app with PostgreSQL, backend API, and frontend on Kubernetes. + +## Architecture + +### Components Deployed: +1. **PostgreSQL StatefulSet** - Database for the application + - 1 replica (configurable) + - 10Gi persistent volume + - Headless service for StatefulSet operations + +2. **Backend Deployment** - FastAPI application + - 2 replicas (configurable) + - Exposed via ClusterIP service on port 8000 + - Health checks enabled (readiness & liveness probes) + +3. **Frontend Deployment** - React application + - 2 replicas (configurable) + - Exposed via ClusterIP service on port 80 + - Health checks enabled (readiness & liveness probes) + +### Ingresses (2): +1. **Backend Ingress** + - Host: `api-dateme.dvirlabs.com` + - Routes to: backend service port 8000 + +2. **Frontend Ingress** + - Host: `dateme.dvirlabs.com` + - Routes to: frontend service port 80 + +## Domain Configuration + +| Component | Domain | Type | +|-----------|--------|------| +| Frontend | dateme.dvirlabs.com | Ingress | +| Backend API | api-dateme.dvirlabs.com | Ingress | +| Database | postgres.dating-app.svc.cluster.local | Internal Service | + +## Frontend to Backend Communication + +The frontend is configured to call the backend via the ingress domain: +- **VITE_API_URL**: `https://api-dateme.dvirlabs.com` + +This environment variable is injected via ConfigMap into the frontend deployment. + +## CORS Configuration + +The backend is configured to accept requests from: +- `http://localhost:5173` (dev) +- `http://localhost:3000` (dev) +- `http://localhost` (dev) +- `https://dateme.dvirlabs.com` (production frontend) + +## Database Connection + +Backend connects to PostgreSQL via: +``` +postgresql://dating_app_user:Aa123456@postgres.dating-app.svc.cluster.local:5432/dating_app +``` + +## Deployment Commands + +```bash +# Install the chart +helm install dating-app ./helm/dating-app + +# Upgrade the chart +helm upgrade dating-app ./helm/dating-app + +# With custom values +helm install dating-app ./helm/dating-app -f values-production.yaml +``` + +## Prerequisites + +1. **Kubernetes Cluster** with NGINX Ingress Controller +2. **DNS Configuration** - Point domains to your Kubernetes ingress controller: + - `dateme.dvirlabs.com` → Ingress IP + - `api-dateme.dvirlabs.com` → Ingress IP +3. **SSL/TLS Certificates** (optional, configure via annotations) + +## Notes + +- All components are deployed in the `dating-app` namespace +- Storage class defaults to cluster default if not specified +- Update `JWT_SECRET` in production values +- Adjust replica counts and resource limits based on your cluster capacity +- PostgreSQL credentials are in the ConfigMap (use external secrets in production) diff --git a/helm/dating-app/values.yaml b/helm/dating-app/values.yaml index 2ec2896..f0d703a 100644 --- a/helm/dating-app/values.yaml +++ b/helm/dating-app/values.yaml @@ -48,14 +48,14 @@ backend: ingress: enabled: true className: nginx - host: api.example.com + host: api-dateme.dvirlabs.com path: / pathType: Prefix environment: JWT_SECRET: your-secret-key-change-in-production JWT_EXPIRES_MINUTES: "1440" MEDIA_DIR: /app/media - CORS_ORIGINS: "http://localhost:5173,http://localhost:3000,http://localhost" + CORS_ORIGINS: "http://localhost:5173,http://localhost:3000,http://localhost,https://dateme.dvirlabs.com" persistence: enabled: true size: 5Gi @@ -94,11 +94,11 @@ frontend: ingress: enabled: true className: nginx - host: app.example.com + host: dateme.dvirlabs.com path: / pathType: Prefix environment: - VITE_API_URL: "http://api.example.com" + VITE_API_URL: "https://api-dateme.dvirlabs.com" probes: readiness: enabled: true