↓Skip to main content
MusicVoting
  1. Technical Docs/

CI/CD & Deployment

··429 words·3 mins·
Developer
Table of Contents

Die App ist im HTL-Leonding-Cluster deployed und unter https://it220241.cloud.htl-leonding.ac.at erreichbar.

Workflows (GitHub Actions)
#

WorkflowTriggerAufgabe
.github/workflows/build-push-deploy.ymlPush auf main oder feature/deployment (Pfade musicvoting/**, deployment/k8s/**, der Workflow selbst) + manuellApp bauen, Images pushen, deployen
.github/workflows/hugo.yamlPush auf main (Pfade hugo/**, .github/workflows/**) + manuellDiese Doku-Website nach GitHub Pages bauen (Hugo Extended 0.145.0)

App-Pipeline (build-push-deploy)
#

  1. Build & Push: Backend- und Frontend-Image werden gebaut und nach GHCR gepusht (ghcr.io/2526-4ahitm-itp/music-voting-backend und …-frontend, Tags latest + Commit-SHA).
  2. Deploy: kubectl apply -f k8s/ im Namespace student-it220241.
  3. Postgres neu starten: kubectl rollout restart deployment/postgres und auf rollout status warten – so wird das Schema aus der (evtl. geänderten) ConfigMap neu angelegt, bevor das Backend sich verbindet.
  4. Rollout: kubectl rollout restart für Backend und Frontend, damit die neuen Images gezogen werden, danach rollout status (Timeout 120 s).
Warning

Postgres hat kein PersistentVolume. Jeder Deploy (und jeder Pod-Neustart) setzt die Datenbank zurück – alle Partys gehen dabei verloren.

Kubernetes-Manifests (deployment/k8s/)
#

DateiInhalt
01-postgres.yamlConfigMap postgres-init-config (Kopie von setup.sql) + PostgreSQL-Deployment + Service
02-backend.yamlBackend-Deployment + Service (Port 8080), Env-Variablen
03-frontend.yamlFrontend-Deployment + Service (Port 80)
ingress.yamlIngress (nginx) für it220241.cloud.htl-leonding.ac.at
  • Ingress-Routing: /api (sowie /graphql, /ws) → Backend (8080), alles übrige → Frontend (80). Read-/Send-Timeout 3600 s, damit SSE-Verbindungen offen bleiben.
  • Backend-Env zeigt auf die Produktions-URLs (APP_PUBLIC_HOST, *_REDIRECT_URI, MUSICVOTING_JOIN_BASE_URL) und die DB (QUARKUS_DATASOURCE_* → Service postgres), dazu die Auto-Refill-Werte SPOTIFY_MARKET (AT) und SPOTIFY_TOPCHARTS_PLAYLIST_ID (leer).
  • SPOTIFY_WEB_REDIRECT_URI muss auf /select-playlist zeigen – sonst überspringt der Host nach dem Login die Standard-Playlist-Auswahl.
  • Secrets: SPOTIFY_CLIENT_ID/SECRET kommen aus dem Kubernetes-Secret spotify-credentials, nicht aus application.properties. Images werden über ghcr-pull-secret gezogen.
Note

KUBE_CONFIG und GITHUB_TOKEN liegen als GitHub-Actions-Secrets vor und sind nicht im Repository.

Important

Schema-Änderung = zwei Dateien. Neue Spalten müssen in musicvoting/backend/setup.sql und in der ConfigMap in deployment/k8s/01-postgres.yaml stehen. Fehlt eine Spalte in der ConfigMap, antwortet das Backend in Produktion mit HTTP 500 (so geschehen im Juni 2026).

Eigener Server mit HTTPS (deployment/server/)
#

deployment/server/ enthält einen eigenständigen Produktions-Stack: Caddy (Reverse-Proxy mit automatischem Let’s-Encrypt-Zertifikat), Frontend, Backend und PostgreSQL (mit Volume).

  1. cd deployment/server && cp .env.example .env und die Werte eintragen – DOMAIN, ACME_EMAIL, SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET sind Pflicht. Alle URLs (QR-Join, OAuth-Callback, /select-playlist) werden aus DOMAIN abgeleitet.
  2. DNS-Eintrag auf den Server, Ports 80 und 443 offen.
  3. Im Spotify-Dashboard https://DOMAIN/api/spotify/callback und https://DOMAIN/select-playlist eintragen.
  4. docker compose up -d --build.

Caddy leitet /api/* ungepuffert (flush_interval -1, wichtig für SSE) ans Backend, alles andere an die Angular-SPA. Alle Details: deployment/server/PLACEHOLDERS.md.

Lokal mit denselben Images
#

Unter deployment/compose/ liegt ein Docker-Compose-Stack, der die GHCR-Images plus PostgreSQL startet – siehe Variante A in

How To Run
··673 words·4 mins
Developer
.