Revert "feat(docker): add Dockerfiles, compose, Docker manager, tests… #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CD | |
| on: | |
| push: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| packages: write | |
| env: | |
| REGISTRY: ghcr.io | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| backend_image: ${{ steps.tags.outputs.backend }} | |
| frontend_image: ${{ steps.tags.outputs.frontend }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Derive lowercase image repo | |
| run: | | |
| echo "IMAGE_REPO=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set image tags | |
| id: tags | |
| run: | | |
| SHA_TAG=sha-${GITHUB_SHA::7} | |
| echo "backend=${{ env.REGISTRY }}/${IMAGE_REPO}-backend:${SHA_TAG}" >> $GITHUB_OUTPUT | |
| echo "backend_latest=${{ env.REGISTRY }}/${IMAGE_REPO}-backend:latest" >> $GITHUB_OUTPUT | |
| echo "frontend=${{ env.REGISTRY }}/${IMAGE_REPO}-frontend:${SHA_TAG}" >> $GITHUB_OUTPUT | |
| echo "frontend_latest=${{ env.REGISTRY }}/${IMAGE_REPO}-frontend:latest" >> $GITHUB_OUTPUT | |
| - name: Build and push backend | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: backend/Dockerfile | |
| push: true | |
| provenance: false | |
| compression: gzip | |
| tags: | | |
| ${{ steps.tags.outputs.backend }} | |
| ${{ steps.tags.outputs.backend_latest }} | |
| - name: Build and push frontend | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: frontend | |
| file: frontend/Dockerfile | |
| push: true | |
| provenance: false | |
| compression: gzip | |
| tags: | | |
| ${{ steps.tags.outputs.frontend }} | |
| ${{ steps.tags.outputs.frontend_latest }} | |
| - name: Show image tags | |
| run: | | |
| echo "Backend: ${{ steps.tags.outputs.backend }}" | |
| echo "Frontend: ${{ steps.tags.outputs.frontend }}" | |
| deploy-compose: | |
| runs-on: ubuntu-latest | |
| needs: build-and-push | |
| environment: production | |
| concurrency: | |
| group: prod-deploy | |
| cancel-in-progress: false | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Verify required secrets are present | |
| env: | |
| SSH_HOST: ${{ secrets.SSH_HOST }} | |
| SSH_USER: ${{ secrets.SSH_USER }} | |
| SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }} | |
| run: | | |
| if [ -z "$SSH_HOST" ] || [ -z "$SSH_USER" ]; then | |
| echo "Missing SSH_HOST or SSH_USER"; exit 1; fi | |
| if [ -z "$SSH_PRIVATE_KEY" ]; then | |
| echo "SSH_PRIVATE_KEY is required (password auth not supported)"; exit 1; fi | |
| - name: Upload docker-compose file | |
| uses: appleboy/scp-action@v0.1.7 | |
| with: | |
| host: ${{ secrets.SSH_HOST }} | |
| username: ${{ secrets.SSH_USER }} | |
| key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| passphrase: ${{ secrets.SSH_PASSPHRASE }} | |
| source: "docker-compose.prod.yml" | |
| target: "/tmp" | |
| strip_components: 0 | |
| - name: Deploy via SSH | |
| uses: appleboy/ssh-action@v1.0.3 | |
| with: | |
| host: ${{ secrets.SSH_HOST }} | |
| username: ${{ secrets.SSH_USER }} | |
| key: ${{ secrets.SSH_PRIVATE_KEY }} | |
| passphrase: ${{ secrets.SSH_PASSPHRASE }} | |
| script: | | |
| set -euo pipefail | |
| APP_DIR=/opt/edgeflow | |
| sudo mkdir -p ${APP_DIR} | |
| cd ${APP_DIR} | |
| # Move compose file into place | |
| if [ -d docker-compose.yml ]; then sudo rm -rf docker-compose.yml; fi | |
| if [ -f /tmp/docker-compose.prod.yml ]; then mv /tmp/docker-compose.prod.yml docker-compose.yml; fi | |
| # Write .env with image tags | |
| cat > .env << 'EOF' | |
| BACKEND_IMAGE=${{ needs.build-and-push.outputs.backend_image }} | |
| FRONTEND_IMAGE=${{ needs.build-and-push.outputs.frontend_image }} | |
| EOF | |
| # Login to GHCR if credentials provided | |
| if [ -n "${{ secrets.GHCR_USERNAME }}" ] && [ -n "${{ secrets.GHCR_TOKEN }}" ]; then | |
| echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin | |
| fi | |
| # Ensure docker compose is available | |
| docker compose version | |
| export COMPOSE_PROJECT_NAME=edgeflow | |
| # Stop any existing stack and containers to free ports (plugin only) | |
| (docker compose -p ${COMPOSE_PROJECT_NAME} -f docker-compose.yml down -v || true) | |
| (docker rm -f edgeflow-backend edgeflow-frontend || true) | |
| (docker network rm ${COMPOSE_PROJECT_NAME}_edgeflow-net || true) | |
| sleep 2 | |
| # Pull and run cleanly | |
| docker compose -p ${COMPOSE_PROJECT_NAME} --env-file .env -f docker-compose.yml pull | |
| docker compose -p ${COMPOSE_PROJECT_NAME} --env-file .env -f docker-compose.yml up -d --remove-orphans --force-recreate | |
| docker image prune -f || true | |
| # Basic health checks (backend on host port 18000) | |
| curl -fsS http://localhost:18000/api/health || (echo 'Backend health failed' && exit 1) | |
| curl -fsS http://localhost:13000/ || (echo 'Frontend health failed' && exit 1) |