Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- name: Backend CI/CD
- on:
- push:
- paths:
- - 'backend/**'
- - 'backend/infra/traefik/**'
- - '.github/workflows/ci-cd-pipeline.yml'
- branches: [main]
- pull_request:
- paths:
- - 'backend/**'
- - 'backend/infra/traefik/**'
- - '.github/workflows/ci-cd-pipeline.yml'
- jobs:
- build-and-push:
- name: Build and Push Docker Image
- runs-on: ubuntu-latest
- outputs:
- image_tag: ${{ steps.get_version.outputs.image_tag }}
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Log in to DigitalOcean Container Registry
- uses: docker/login-action@v3
- with:
- registry: registry.digitalocean.com
- username: do
- password: ${{ secrets.DOCR_TOKEN }}
- - name: Install Poetry
- run: pip install poetry
- - name: Get backend version
- id: get_version
- working-directory: ./backend
- run: |
- VERSION=$(poetry version -s)
- echo "VERSION=$VERSION" >> $GITHUB_ENV
- echo "image_tag=$VERSION" >> $GITHUB_OUTPUT
- - name: Print VERSION
- run: echo "VERSION is ${{ env.VERSION }}"
- env:
- VERSION: ${{ env.VERSION }}
- - name: Build and push Docker image
- id: build_push
- uses: docker/build-push-action@v5
- env:
- VERSION: ${{ env.VERSION }}
- with:
- context: ./backend
- file: ./backend/Dockerfile
- push: true
- tags: |
- registry.digitalocean.com/hackalyst-backend/hackalyst-backend:latest
- registry.digitalocean.com/hackalyst-backend/hackalyst-backend:${{ env.VERSION }}
- registry.digitalocean.com/hackalyst-backend/hackalyst-backend:${{ github.sha }}
- deploy-traefik:
- name: Deploy Traefik Configuration
- needs: build-and-push
- runs-on: ubuntu-latest
- if: github.ref == 'refs/heads/main'
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
- - name: Copy Traefik files to remote server
- uses: appleboy/scp-action@master
- with:
- host: ${{ secrets.DROPLET_IP }}
- username: ${{ secrets.DROPLET_USER }}
- key: ${{ secrets.DROPLET_SSH_KEY }}
- source: "backend/infra/traefik/*,backend/infra/traefik/dynamic/*"
- target: "/opt/hackalyst/"
- strip_components: 2
- - name: Deploy Traefik Configuration
- with:
- host: ${{ secrets.DROPLET_IP }}
- username: ${{ secrets.DROPLET_USER }}
- key: ${{ secrets.DROPLET_SSH_KEY }}
- script_stop: true
- script: |
- # Create traefik directory if it doesn't exist
- mkdir -p /opt/hackalyst/traefik
- mkdir -p /opt/hackalyst/traefik/dynamic
- # Navigate to Traefik directory
- cd /opt/hackalyst/traefik
- # Fix acme.json permissions
- touch acme/acme.json
- chmod 600 acme/acme.json
- # Remove the version line from docker-compose.yml
- grep -v "^version:" docker-compose.yml > docker-compose.tmp && mv docker-compose.tmp docker-compose.yml
- # Update network configuration to use external network
- sed -i 's/external: false/external: true/' docker-compose.yml
- # Fix network issue by handling active containers before recreating the network
- # First stop traefik container if it exists
- docker stop traefik || true
- docker rm traefik || true
- # Handle active endpoints on the proxy network
- if docker network inspect proxy 2>/dev/null; then
- # Get list of containers connected to the proxy network
- CONNECTED_CONTAINERS=$(docker network inspect proxy -f '{{range .Containers}}{{.Name}} {{end}}')
- if [ -n "$CONNECTED_CONTAINERS" ]; then
- echo "Disconnecting containers from proxy network: $CONNECTED_CONTAINERS"
- for CONTAINER in $CONNECTED_CONTAINERS; do
- echo "Disconnecting $CONTAINER from proxy network"
- docker network disconnect -f proxy "$CONTAINER" || true
- done
- fi
- # Now it's safe to remove the network
- docker network rm proxy || true
- fi
- # Create the network with proper subnet and labels
- docker network create --subnet=137.184.161.0/24 --gateway=137.184.161.1 --label="com.docker.compose.network=proxy" proxy
- # Pull latest changes and restart Traefik
- # Ensure Traefik dashboard port is available
- if netstat -tuln | grep -q ':8081'; then
- echo "Warning: Port 8081 is already in use. Checking what's using it..."
- fuser -n tcp 8081 || true
- lsof -i:8081 || true
- echo "Attempting to stop any process using port 8081..."
- fuser -k 8081/tcp || true
- fi
- # Pass the Traefik dashboard credentials from GitHub secrets
- export TRAEFIK_DASHBOARD_CRED="${{ secrets.TRAEFIK_DASHBOARD_CRED }}"
- docker compose -f docker-compose.yml pull
- docker compose -f docker-compose.yml up -d
- deploy-production:
- name: Deploy to Production Droplet
- needs: deploy-traefik
- runs-on: ubuntu-latest
- if: github.ref == 'refs/heads/main'
- steps:
- - name: Checkout code
- uses: actions/checkout@v3
- - name: Install jq
- run: sudo apt-get update && sudo apt-get install -y jq
- - name: Install Infisical CLI
- run: |
- curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | sudo -E bash
- sudo apt-get update && sudo apt-get install -y infisical
- - name: Generate Infisical Access Token
- run: |
- chmod +x backend/scripts/generate_infisical_token.sh
- source backend/scripts/generate_infisical_token.sh
- echo "INFISICAL_ACCESS_TOKEN=$INFISICAL_ACCESS_TOKEN" >> $GITHUB_ENV
- env:
- INFISICAL_MACHINE_IDENTITY_ID: ${{ secrets.INFISICAL_MACHINE_IDENTITY_ID }}
- INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET: ${{ secrets.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET }}
- INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_PROJECT_ID }}
- - name: Deploy to Production Droplet
- with:
- envs: INFISICAL_MACHINE_IDENTITY_ID,INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET,INFISICAL_PROJECT_ID
- host: ${{ secrets.DROPLET_IP }}
- username: ${{ secrets.DROPLET_USER }}
- key: ${{ secrets.DROPLET_SSH_KEY }}
- script: |
- # Install Docker if needed
- if ! command -v docker &> /dev/null; then
- curl -fsSL https://get.docker.com -o get-docker.sh
- sudo sh get-docker.sh
- sudo usermod -aG docker $USER
- newgrp docker
- fi
- # Login to DigitalOcean Container Registry
- echo "${{ secrets.DOCR_TOKEN }}" | docker login \
- --username do \
- --password-stdin \
- registry.digitalocean.com
- # Pull the latest image
- docker pull registry.digitalocean.com/hackalyst-backend/hackalyst-backend:latest
- # Stop and remove existing container if it exists
- docker stop hackalyst-backend || true
- docker rm hackalyst-backend || true
- # Ensure proxy network exists with the correct labels and subnet
- # Remove existing network if it exists
- docker network inspect proxy >/dev/null 2>&1 && docker network rm proxy
- # Create network with specific subnet
- docker network create --subnet=137.184.161.0/24 --gateway=137.184.161.1 proxy --label="com.docker.compose.network=proxy"
- # Run the new container with Infisical environment variables and Traefik labels
- docker run -d --name hackalyst-backend --network proxy \
- --ip 137.184.161.2 \
- --network-alias hackalyst-backend \
- -p 127.0.0.1:8000:8000 \
- -e INFISICAL_MACHINE_IDENTITY_ID="${{ secrets.INFISICAL_MACHINE_IDENTITY_ID }}" \
- -e INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET="${{ secrets.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET }}" \
- -e INFISICAL_PROJECT_ID="${{ secrets.INFISICAL_PROJECT_ID }}" \
- -l "traefik.enable=true" \
- -l "traefik.http.routers.backend.rule=Host(\`backend.hackalyst.com\`)" \
- -l "traefik.http.routers.backend.entrypoints=websecure" \
- -l "traefik.http.routers.backend.tls.certresolver=letsencrypt" \
- -l "traefik.http.services.backend.loadbalancer.server.port=3000" \
- --restart unless-stopped \
- registry.digitalocean.com/hackalyst-backend/hackalyst-backend:latest
- # Verify DNS resolution is working correctly
- echo "Verifying DNS resolution from traefik to hackalyst-backend..."
- docker exec traefik ping -c 4 hackalyst-backend
- # Verify IP address assignment
- echo "Verifying IP address assignment..."
- docker inspect hackalyst-backend | grep "IPv4Address"
- env:
- INFISICAL_MACHINE_IDENTITY_ID: ${{ secrets.INFISICAL_MACHINE_IDENTITY_ID }}
- INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET: ${{ secrets.INFISICAL_MACHINE_IDENTITY_CLIENT_SECRET }}
- INFISICAL_ACCESS_TOKEN: ${{ env.INFISICAL_ACCESS_TOKEN }}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement