diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2383f9f..c00da9f 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -61,7 +61,7 @@ jobs: - name: Lint (ruff) run: | pip install ruff - ruff check . + ruff check . --show-files - name: Run tests run: pytest diff --git a/.gitignore b/.gitignore index 55f4c13..7d20ed0 100644 --- a/.gitignore +++ b/.gitignore @@ -27,10 +27,6 @@ frontend/build/ frontend/.next/ frontend/out/ -# Frontend Environment -frontend/.env.production -.env.prod - # Frontend logs frontend/npm-debug.log* frontend/yarn-debug.log* @@ -90,5 +86,4 @@ docker-compose.prod.yml # Environment variables -.env.production !.env.example diff --git a/backend/app/.env.development b/backend/app/.env.development index e1c2fd7..4cc91ef 100644 --- a/backend/app/.env.development +++ b/backend/app/.env.development @@ -1,26 +1,6 @@ -DEV_USER=user1 -DB_PORT=5433 BACKEND_PORT=8001 - -# ============================================ -# DATENBANK -# ============================================ -POSTGRES_USER=user -POSTGRES_PASSWORD=dev_pass_user1 -POSTGRES_DB=appdb_dev_user1 - -DB_READER_USER=reader -DB_READER_PASS=reader-pass -DB_ADMIN_USER=admin -DB_ADMIN_PASS=admin-pass - -# ============================================ -# BACKEND -# ============================================ -DATABASE_URL=postgresql://user:dev_pass_user1@db:5432/appdb_dev_user1 +LOG_LEVEL=INFO IMAGE_DIR=/app/static/images CORS_ORIGINS=http://localhost:3000 -# CORS_ORIGINS=http://localhost:3001, http://localhost:8001, http://132.195.69.123:3001, http://132.195.69.123:8001, http://132.195.69.123:80, http://132.195.178.126 +DATABASE_URL=postgresql://user:dev_pass_user1@db:5432/appdb_dev_user1 SECRET_KEY = "9a6f88adad60f8dc9cae15ea76b9e363a21a051020268f1b2158004ddd5160f4" - -LOG_LEVEL=INFO diff --git a/backend/app/.env.production b/backend/app/.env.production new file mode 100644 index 0000000..22ee266 --- /dev/null +++ b/backend/app/.env.production @@ -0,0 +1,6 @@ +BACKEND_PORT=8001 +LOG_LEVEL=INFO +IMAGE_DIR=/app/static/images +CORS_ORIGINS=http://localhost:3000 +DATABASE_URL=postgresql://user:dev_pass_user1@db:5432/appdb_dev_user1 +SECRET_KEY = "changeme" diff --git a/docker-compose.dev2.yml b/docker-compose.dev2.yml deleted file mode 100644 index 5514595..0000000 --- a/docker-compose.dev2.yml +++ /dev/null @@ -1,69 +0,0 @@ -services: - db: - image: postgres:16 - container_name: usecase-management_db-dev-${DEV_USER} - environment: - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_DB: ${POSTGRES_DB} - ports: - - "127.0.0.1:5434:5432" # NUR localhost! - volumes: - - db_data_dev:/var/lib/postgresql/data - networks: - - app-network - - backend: - build: - context: ./backend - dockerfile: Dockerfile - container_name: usecase-management_backend-${DEV_USER} - environment: - - DATABASE_URL=${DATABASE_URL} - - IMAGE_DIR=${IMAGE_DIR} - - ENV=${ENV} - - ALLOWED_ORIGINS=${ALLOWED_ORIGINS} - - DB_READER_USER=${DB_READER_USER} - - DB_READER_PASS=${DB_READER_PASS} - - DB_ADMIN_USER=${DB_ADMIN_USER} - - DB_ADMIN_PASS=${DB_ADMIN_PASS} - ports: - - "127.0.0.1:8002:8000" # NUR localhost! - depends_on: - - db - volumes: - - ./backend:/app - - static_images_volume_dev:/app/static/images - command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload - networks: - - app-network - - frontend: - build: - context: ./frontend - dockerfile: Dockerfile - container_name: usecase-management_frontend-${DEV_USER} - ports: - - "127.0.0.1:3002:3000" # NUR localhost - depends_on: - - backend - volumes: - - ./frontend:/app - - /app/node_modules - environment: - - CHOKIDAR_USEPOLLING=true - - VITE_HMR_HOST=localhost - - VITE_API_URL=${VITE_API_URL} - command: npm run dev -- --host 0.0.0.0 - networks: - - app-network - -volumes: - db_data_dev: - name: usecase-management_db_data_dev_${DEV_USER} - static_images_volume_dev: - name: usecase-management_static_images_dev_${DEV_USER} - -networks: - app-network: - driver: bridge diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index d019277..a6102e9 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -3,11 +3,9 @@ services: image: postgres:16 container_name: usecase-management_db-prod environment: - POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_USER: user POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} - # ports: - # - "5432:5432" (kein Ports-Mapping = nur intern erreichbar) volumes: - db_data:/var/lib/postgresql/data restart: unless-stopped @@ -15,51 +13,28 @@ services: - app-network backend: - build: - context: ./backend - dockerfile: Dockerfile + image: ghcr.io/project-construct-x/usecase-management-backend:latest container_name: usecase-management_backend-prod environment: - - DATABASE_URL=${DATABASE_URL} - - IMAGE_DIR=${IMAGE_DIR} - - ENV=${ENV} - - ALLOWED_ORIGINS=${ALLOWED_ORIGINS} - - DB_READER_USER=${DB_READER_USER} - - DB_READER_PASS=${DB_READER_PASS} - - DB_ADMIN_USER=${DB_ADMIN_USER} - - DB_ADMIN_PASS=${DB_ADMIN_PASS} - - SECRET_KEY=${SECRET_KEY} + APP_ENV: production ports: - "8000:8000" depends_on: - db restart: unless-stopped volumes: - # Kein Code-Mount in Production! - static_images_volume:/app/static/images command: uvicorn app.main:app --host 0.0.0.0 --port 8000 - networks: - - app-network frontend: - build: - context: ./frontend - dockerfile: Dockerfile.prod + image: ghcr.io/project-construct-x/usecase-management-frontend:latest container_name: usecase-management_frontend-prod ports: - "80:80" depends_on: - backend restart: unless-stopped - volumes: - - ./frontend/.htpasswd:/etc/nginx/.htpasswd:ro - networks: - - app-network volumes: db_data: static_images_volume: - -networks: - app-network: - driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index 4360a19..daec5c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,11 +7,9 @@ services: POSTGRES_PASSWORD: dev_pass_user1 POSTGRES_DB: appdb_dev_user1 ports: - - "5432:5432" # NUR localhost! + - "5432:5432" volumes: - db_data_dev:/var/lib/postgresql/data - networks: - - app-network backend: build: @@ -19,7 +17,7 @@ services: dockerfile: Dockerfile container_name: usecase-management_backend-user1 ports: - - "8080:8080" # NUR localhost! + - "8080:8080" environment: - APP_ENV=development depends_on: @@ -28,8 +26,6 @@ services: - ./backend:/app - static_images_volume_dev:/app/static/images command: uvicorn app.main:app --host 0.0.0.0 --port 8080 --reload - networks: - - app-network frontend: build: @@ -37,23 +33,16 @@ services: dockerfile: Dockerfile container_name: usecase-management_frontend-user1 ports: - - "3000:3000" # NUR localhost + - "3000:3000" depends_on: - backend volumes: - ./frontend:/app - /app/node_modules command: npm run dev -- --host 0.0.0.0 - networks: - - app-network volumes: db_data_dev: name: usecase-management_db_data_dev_user1 static_images_volume_dev: name: usecase-management_static_images_dev_user1 - -networks: - app-network: - name: usecase-management_network_user1 - driver: bridge diff --git a/frontend/.env.production b/frontend/.env.production new file mode 100644 index 0000000..1b1a580 --- /dev/null +++ b/frontend/.env.production @@ -0,0 +1 @@ +VITE_API_URL=https://usecase-management.staging.construct-x.net/api diff --git a/helm/deploy.sh b/helm/deploy.sh index 2fc54e2..38f4451 100755 --- a/helm/deploy.sh +++ b/helm/deploy.sh @@ -2,8 +2,8 @@ set -euo pipefail CLUSTER="borrmann-dev" -NAMESPACE="soundboard" -RELEASE="soundboard" +NAMESPACE="usecase-management-staging" +RELEASE="usecase-management" CHART_DIR="$(dirname "$0")" usage() { @@ -15,7 +15,7 @@ Usage: $(basename "$0") delete Delete the release (keeps PVCs) Requires a kubeconfig context named '${CLUSTER}'. -Run 'secrets.sh write' first to set Discord credentials in the cluster. +Run 'secrets.sh write' first to set credentials in the cluster. EOF exit 1 } @@ -35,6 +35,7 @@ cmd_install() { helm upgrade --install "${RELEASE}" "${CHART_DIR}" \ --namespace "${NAMESPACE}" \ --create-namespace \ + --values "${CHART_DIR}/values-staging.yaml" \ --wait \ --timeout=5m \ "$@" @@ -46,6 +47,7 @@ cmd_upgrade() { check_context helm upgrade "${RELEASE}" "${CHART_DIR}" \ --namespace "${NAMESPACE}" \ + --values "${CHART_DIR}/values-staging.yaml" \ --wait \ --timeout=5m \ "$@" diff --git a/helm/secrets.sh b/helm/secrets.sh deleted file mode 100755 index 696e7d1..0000000 --- a/helm/secrets.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -NAMESPACE="soundboard" -SECRET_NAME="soundboard-secret" - -usage() { - cat < - - write Prompt for Discord secrets and update the cluster Secret - read Decode and show the cluster Secret -EOF - exit 1 -} - -cmd_write() { - echo "Enter Discord secrets:" - echo "" - read -r -p " Token: " TOKEN - read -r -p " Client ID: " CLIENT_ID - read -r -p " Client Secret: " CLIENT_SECRET - - if [[ -z "${TOKEN}" && -z "${CLIENT_ID}" && -z "${CLIENT_SECRET}" ]]; then - echo "ERROR: all fields empty — nothing to update." >&2 - exit 1 - fi - - local patch=() - [[ -n "${TOKEN}" ]] && patch+=("--from-literal=DISCORD_TOKEN=${TOKEN}") - [[ -n "${CLIENT_ID}" ]] && patch+=("--from-literal=DISCORD_CLIENT_ID=${CLIENT_ID}") - [[ -n "${CLIENT_SECRET}" ]] && patch+=("--from-literal=DISCORD_CLIENT_SECRET=${CLIENT_SECRET}") - - kubectl -n "${NAMESPACE}" create secret generic "${SECRET_NAME}" \ - "${patch[@]}" \ - --dry-run=client -o yaml | \ - kubectl apply -f - - - echo "" - echo "Secret '${SECRET_NAME}' updated in ${NAMESPACE}." -} - -cmd_read() { - if ! kubectl -n "${NAMESPACE}" get secret "${SECRET_NAME}" &>/dev/null; then - echo "Secret '${SECRET_NAME}' not found in namespace '${NAMESPACE}'." >&2 - exit 1 - fi - - echo "Secrets in ${NAMESPACE}/${SECRET_NAME}:" - echo "" - kubectl -n "${NAMESPACE}" get secret "${SECRET_NAME}" -o jsonpath='{.data}' \ - | jq -r 'to_entries[] | " \(.key): \(.value | @base64d)"' -} - -case "${1:-}" in - write) cmd_write ;; - read) cmd_read ;; - *) usage ;; -esac diff --git a/helm/templates/backend.yaml b/helm/templates/backend.yaml index 3379f97..ffd21bb 100644 --- a/helm/templates/backend.yaml +++ b/helm/templates/backend.yaml @@ -42,20 +42,12 @@ spec: - containerPort: 8080 env: - name: DATABASE_URL - valueFrom: - secretKeyRef: - name: usecase-management-secret - key: DATABASE_URL + value: {{ printf "postgresql://%s:%s@usecase-management-db:5432/%s" .Values.db.user .Values.db.password .Values.db.db | quote }} - name: SECRET_KEY valueFrom: secretKeyRef: name: usecase-management-secret key: SECRET_KEY - - name: ALLOWED_ORIGINS - valueFrom: - secretKeyRef: - name: usecase-management-secret - key: ALLOWED_ORIGINS volumeMounts: - name: static-images mountPath: "/app/static/images" diff --git a/helm/templates/db.yaml b/helm/templates/db.yaml index fc4227b..394dd39 100644 --- a/helm/templates/db.yaml +++ b/helm/templates/db.yaml @@ -29,7 +29,7 @@ spec: replicas: 1 selector: matchLabels: - app: db + app: usecase-management-db template: metadata: labels: @@ -42,20 +42,11 @@ spec: - containerPort: 5432 env: - name: POSTGRES_USER - valueFrom: - secretKeyRef: - name: usecase-management-secret - key: POSTGRES_USER + value: {{ .Values.db.user | quote }} - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: usecase-management-secret - key: POSTGRES_PASSWORD + value: {{ .Values.db.password | quote }} - name: POSTGRES_DB - valueFrom: - secretKeyRef: - name: usecase-management-secret - key: POSTGRES_DB + value: {{ .Values.db.db | quote }} volumeMounts: - name: db-data mountPath: /var/lib/postgresql/data diff --git a/helm/templates/frontend.yaml b/helm/templates/frontend.yaml index 9e7c52a..b719c01 100644 --- a/helm/templates/frontend.yaml +++ b/helm/templates/frontend.yaml @@ -21,7 +21,7 @@ spec: template: metadata: labels: - app: soundboard-frontend + app: usecase-management-frontend spec: containers: - name: frontend diff --git a/helm/values-staging.yaml b/helm/values-staging.yaml new file mode 100644 index 0000000..5dee6d8 --- /dev/null +++ b/helm/values-staging.yaml @@ -0,0 +1,21 @@ +backend: + image: + repository: ghcr.io/project-construct-x/usecase-management-backend + tag: latest + storage: + size: 30Gi + +frontend: + image: + repository: ghcr.io/project-construct-x/usecase-management-frontend + tag: latest + +ingress: + host: https://usecase-management.staging.construct-x.net + +db: + user: "user" + password: "dev_pass_user1" + db: "appdb_dev_user1" + storage: + size: 30Gi diff --git a/helm/values.yaml b/helm/values.yaml index a769694..0076db2 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -1,22 +1,23 @@ backend: image: - repository: usecase-management/backend + repository: ghcr.io/project-construct-x/usecase-management-backend tag: latest storage: size: 30Gi - className: "" #tbd frontend: image: - repository: usecase-management/frontend + repository: ghcr.io/project-construct-x/usecase-management-frontend tag: latest ingress: - host: usecase-management.example.com # tbd + host: usecase-management.example.com className: nginx - clusterIssuer: letsencrypt-prod # tbd + clusterIssuer: letsencrypt-prod db: + user: "user" + password: "password" + db: "appdb" storage: size: 30Gi - className: "" # tbd