diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 1a4b0de..a96d24a 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -171,6 +171,8 @@ jobs: name: Deploy to Production runs-on: ubuntu-latest needs: [backend-tests, frontend-tests] + env: + SECRET_KEY: test-secret-key-for-ci-environment-32chars-minimum container: volumes: - /var/packages/ContainerManager/target/usr/bin/docker:/usr/bin/docker @@ -237,24 +239,82 @@ jobs: - name: Sync runtime compose file run: cp dashboard/docker-compose.yml /nas-dashboard/docker-compose.yml - - name: Deploy + - name: Deploy and verify run: | set -e export DOCKER_API_VERSION=1.43 - docker compose -f /nas-dashboard/docker-compose.yml up -d --pull never - - name: Wait for container to be healthy - run: | + # Docker 24 compose fails when it can't connect external networks + # during container creation. Try compose first; if the container + # isn't created, strip networks from compose file and retry. + docker compose -f /nas-dashboard/docker-compose.yml up -d --pull never 2>&1 || true + + if ! docker container inspect nas-dashboard >/dev/null 2>&1; then + echo "Compose failed to create container, stripping networks from compose file..." + python3 -c " + import os + lines = open('/nas-dashboard/docker-compose.yml').readlines() + out = [] + skip_net = False + for l in lines: + stripped = l.strip() + if stripped == 'networks:' and not l[0].isspace(): + skip_net = True + continue + if skip_net: + if l[0].isspace(): + continue + skip_net = False + if stripped == 'networks:' and l[:4].strip() == '': + skip_net = True + continue + if skip_net: + if l.startswith(' '): + continue + skip_net = False + out.append(l) + open('/tmp/prod-ci.yml','w').writelines(out) + " + docker compose -f /tmp/prod-ci.yml up -d --pull never + fi + + # Create the internal network if compose didn't create it + docker network create internal 2>/dev/null || true + + # Connect docker-socket-proxy to networks + docker network connect internal docker-socket-proxy 2>/dev/null || true + docker network connect nas-dashboard_internal docker-socket-proxy 2>/dev/null || true + + # Connect dashboard to networks + docker network connect internal nas-dashboard 2>/dev/null || true + docker network connect nas-dashboard_internal nas-dashboard 2>/dev/null || true + docker network connect gitea_gitea nas-dashboard 2>/dev/null || true + + # Verify network connections + echo "=== Network connections ===" + docker inspect nas-dashboard --format '{{json .NetworkSettings.Networks}}' | python3 -c 'import json,sys;nets=json.load(sys.stdin);[print(f" Connected to {n}") for n in nets];assert "nas-dashboard_internal" in nets, "Missing nas-dashboard_internal";print("All network connections established")' + + # Wait for container to be healthy echo "Waiting for container to be healthy..." for i in {1..30}; do STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "starting") if [ "$STATUS" = "healthy" ]; then echo "✅ Container is healthy" - exit 0 + break fi echo "Waiting... ($i/30) Status: $STATUS" sleep 2 done - echo "❌ Container failed to become healthy" - docker logs nas-dashboard --tail 50 - exit 1 + STATUS=$(docker inspect --format='{{.State.Health.Status}}' nas-dashboard 2>/dev/null || echo "unknown") + if [ "$STATUS" != "healthy" ]; then + echo "❌ Container failed to become healthy: $STATUS" + docker logs nas-dashboard --tail 50 + exit 1 + fi + + # Run smoke tests via docker exec + echo "=== Running smoke tests ===" + docker exec nas-dashboard python3 -c "import urllib.request,json; d=json.loads(urllib.request.urlopen('http://localhost:4000/api/health',timeout=5).read()); assert d['status']=='ok', f'unexpected: {d}'" && echo "✅ Health check passed" || { echo "❌ Health check failed"; docker logs nas-dashboard --tail 50; exit 1; } + docker exec nas-dashboard python3 -c "import urllib.request; html=urllib.request.urlopen('http://localhost:4000/',timeout=5).read().decode(); assert 'NAS Dashboard' in html, f'missing NAS Dashboard'" && echo "✅ Frontend loads" || { echo "❌ Frontend failed to load"; exit 1; } + echo "" + echo "=== All deployment checks passed! ==="