name: Build & Deploy Tippspiel on: push: branches: [main] env: REGISTRY: git.home.rm-warpstation.de IMAGE: mwf975_git/tippspiel jobs: build: runs-on: self-hosted steps: - name: Setup tools run: apk add --no-cache curl python3 - name: Checkout run: | rm -rf workspace && mkdir workspace GIT_TERMINAL_PROMPT=0 git clone \ --depth 1 \ --branch main \ http://x-token:${{ secrets.DEPLOY_TOKEN }}@gitea:3000/mwf975_git/tippspiel.git \ workspace - name: Create build context run: | cd workspace tar cf /tmp/tippspiel-ci.tar \ --exclude='.git' \ --exclude='node_modules' \ --exclude='*.docx' \ --exclude='prototyp_*.html' \ . echo "Build context size: $(du -sh /tmp/tippspiel-ci.tar | cut -f1)" - name: Build Docker Image via Portainer run: | IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE }}:latest" echo "Building image: $IMAGE_TAG" curl -s -k -X POST \ "https://192.168.1.60:9444/api/endpoints/2/docker/build?t=${IMAGE_TAG}&dockerfile=./Dockerfile&nocache=1" \ -H "X-API-Key: ${{ secrets.PORTAINER_TOKEN }}" \ -H "Content-Type: application/x-tar" \ --data-binary @/tmp/tippspiel-ci.tar \ --max-time 600 \ | grep -E '(Successfully|error|Error)' || true echo "Build completed." - name: Push to Gitea Registry run: | IMAGE_TAG="${{ env.REGISTRY }}/${{ env.IMAGE }}:latest" # Login to Gitea registry via Portainer Docker API LOGIN_PAYLOAD=$(python3 -c "import json; print(json.dumps({'username': 'mwf975_git', 'password': '${{ secrets.DEPLOY_TOKEN }}', 'serveraddress': 'https://${{ env.REGISTRY }}'}))") curl -s -k -X POST \ "https://192.168.1.60:9444/api/endpoints/2/docker/auth" \ -H "X-API-Key: ${{ secrets.PORTAINER_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$LOGIN_PAYLOAD" || true # Push image to registry echo "Pushing $IMAGE_TAG..." AUTH_HEADER=$(python3 -c "import base64,json; print(base64.urlsafe_b64encode(json.dumps({'username':'mwf975_git','password':'${{ secrets.DEPLOY_TOKEN }}'}).encode()).decode())") curl -s -k -X POST \ "https://192.168.1.60:9444/api/endpoints/2/docker/images/${IMAGE_TAG}/push" \ -H "X-API-Key: ${{ secrets.PORTAINER_TOKEN }}" \ -H "X-Registry-Auth: $AUTH_HEADER" \ --max-time 300 || true echo "Push completed." - name: Redeploy Stack via Portainer run: | echo "Fetching current stack config from Portainer..." # Aktuelle Env-Vars aus Portainer lesen ENV_VARS=$(curl -s -k \ "https://192.168.1.60:9444/api/stacks/115" \ -H "X-API-Key: ${{ secrets.PORTAINER_TOKEN }}" \ | python3 -c "import sys,json; print(json.dumps(json.load(sys.stdin).get('Env', [])))") # Stack mit Image-Pull neu deployen PAYLOAD=$(python3 -c " import json env_vars = $ENV_VARS print(json.dumps({ 'stackFileContent': '''services: tippspiel: image: ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest container_name: wm2026-tippspiel restart: unless-stopped ports: - \"3301:3001\" environment: - NODE_ENV=\${NODE_ENV} - PORT=\${PORT} - DATABASE_URL=\${DATABASE_URL} - SUPABASE_URL=\${SUPABASE_URL} - SUPABASE_SERVICE_ROLE_KEY=\${SUPABASE_SERVICE_ROLE_KEY} - ANTHROPIC_API_KEY=\${ANTHROPIC_API_KEY} - FOOTBALL_API_KEY=\${FOOTBALL_API_KEY} - FOOTBALL_API_BASE_URL=\${FOOTBALL_API_BASE_URL} - ELEVENLABS_API_KEY=\${ELEVENLABS_API_KEY} - CORS_ORIGIN=\${CORS_ORIGIN} - STAFFBASE_PUBLIC_KEY=\${STAFFBASE_PUBLIC_KEY:-} - STAFFBASE_PLUGIN_ID=\${STAFFBASE_PLUGIN_ID:-} healthcheck: test: [\"CMD\", \"wget\", \"-qO-\", \"http://localhost:3001/health\"] interval: 30s timeout: 5s start_period: 10s retries: 3 networks: - main-network networks: main-network: external: true''', 'env': env_vars, 'prune': True, 'pullImage': True })) ") echo "Redeploying stack wm2026-tippspiel..." curl -s -k -X PUT \ "https://192.168.1.60:9444/api/stacks/115?endpointId=2" \ -H "X-API-Key: ${{ secrets.PORTAINER_TOKEN }}" \ -H "Content-Type: application/json" \ -d "$PAYLOAD" \ | python3 -c "import sys,json; d=json.load(sys.stdin); print('Stack redeployed:', d.get('Name'), '| Status:', d.get('Status'))" \ || echo "Stack redeploy triggered." echo "Deployment complete!" - name: Verify deployment run: | sleep 20 STATUS=$(curl -s http://192.168.1.60:3301/health | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('status'))" 2>/dev/null || echo "unreachable") echo "Health check: $STATUS" if [ "$STATUS" = "ok" ]; then echo "✅ Deployment successful! App running at http://192.168.1.60:3301" else echo "⚠️ Health check inconclusive (container may be restarting)" fi - name: Cleanup if: always() run: rm -rf workspace /tmp/tippspiel-ci.tar