name: Build and Deploy LittleShop on: push: branches: - main - development tags: - 'v*' workflow_dispatch: env: DOCKER_BUILDKIT: 1 COMPOSE_DOCKER_CLI_BUILD: 1 jobs: build-littleshop: name: Build LittleShop Docker Image runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build LittleShop image run: | echo "Building LittleShop Docker image" docker build --no-cache -t littleshop:${{ github.sha }} . docker tag littleshop:${{ github.sha }} littleshop:latest if [[ "${{ github.ref_type }}" == "tag" ]]; then echo "Tagging as version ${{ github.ref_name }}" docker tag littleshop:${{ github.sha }} littleshop:${{ github.ref_name }} fi - name: Save LittleShop image run: | mkdir -p /tmp/docker-images docker save littleshop:${{ github.sha }} | gzip > /tmp/docker-images/littleshop.tar.gz - name: Upload LittleShop artifact uses: actions/upload-artifact@v4 with: name: littleshop-image path: /tmp/docker-images/littleshop.tar.gz retention-days: 1 build-telebot: name: Build TeleBot Docker Image runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Build TeleBot image run: | echo "Building TeleBot Docker image" docker build --no-cache -t telebot:${{ github.sha }} -f Dockerfile.telebot . docker tag telebot:${{ github.sha }} telebot:latest if [[ "${{ github.ref_type }}" == "tag" ]]; then echo "Tagging as version ${{ github.ref_name }}" docker tag telebot:${{ github.sha }} telebot:${{ github.ref_name }} fi - name: Save TeleBot image run: | mkdir -p /tmp/docker-images docker save telebot:${{ github.sha }} | gzip > /tmp/docker-images/telebot.tar.gz - name: Upload TeleBot artifact uses: actions/upload-artifact@v4 with: name: telebot-image path: /tmp/docker-images/telebot.tar.gz retention-days: 1 deploy-production: name: Deploy to Production VPS (Manual Only) needs: [build-littleshop, build-telebot] runs-on: ubuntu-latest if: false # Disabled - Manual deployment only via workflow_dispatch environment: name: production url: https://admin.dark.side steps: - name: Checkout code uses: actions/checkout@v4 - name: Download LittleShop image uses: actions/download-artifact@v4 with: name: littleshop-image path: /tmp/docker-images - name: Download TeleBot image uses: actions/download-artifact@v4 with: name: telebot-image path: /tmp/docker-images - name: Load Docker images run: | docker load < /tmp/docker-images/littleshop.tar.gz docker load < /tmp/docker-images/telebot.tar.gz - name: Set up SSH run: | mkdir -p ~/.ssh chmod 700 ~/.ssh echo "${{ secrets.VPS_SSH_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -p ${{ secrets.VPS_PORT }} ${{ secrets.VPS_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: Transfer Docker images to VPS run: | echo "Copying LittleShop image to VPS..." docker save littleshop:${{ github.sha }} | \ ssh -i ~/.ssh/deploy_key -p ${{ secrets.VPS_PORT }} ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} \ "docker load" echo "Copying TeleBot image to VPS..." docker save telebot:${{ github.sha }} | \ ssh -i ~/.ssh/deploy_key -p ${{ secrets.VPS_PORT }} ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} \ "docker load" - name: Deploy to VPS run: | ssh -i ~/.ssh/deploy_key -p ${{ secrets.VPS_PORT }} ${{ secrets.VPS_USER }}@${{ secrets.VPS_HOST }} bash -s << 'ENDSSH' set -e export VERSION="${{ github.sha }}" # Tag the images docker tag littleshop:$VERSION localhost:5000/littleshop:$VERSION docker tag littleshop:$VERSION localhost:5000/littleshop:latest docker tag telebot:$VERSION localhost:5000/telebot:$VERSION docker tag telebot:$VERSION localhost:5000/telebot:latest # Push to local registry echo "Pushing images to local Docker registry..." docker push localhost:5000/littleshop:$VERSION || true docker push localhost:5000/littleshop:latest || true docker push localhost:5000/telebot:$VERSION || true docker push localhost:5000/telebot:latest || true # Navigate to deployment directory cd /opt/littleshop # Force stop all littleshop containers echo "Stopping all littleshop containers..." docker stop $(docker ps -q --filter "name=littleshop") 2>/dev/null || true docker rm $(docker ps -aq --filter "name=littleshop") 2>/dev/null || true # Stop TeleBot container echo "Stopping TeleBot container..." docker stop telebot-service 2>/dev/null || true docker rm telebot-service 2>/dev/null || true # Stop services with compose echo "Stopping compose services..." docker-compose down --remove-orphans || true # Prune unused Docker networks echo "Cleaning up Docker networks..." docker network prune -f || true # Apply database migrations if they exist echo "Checking for database migrations..." if [ -d "LittleShop/Migrations" ] && [ -n "$(ls -A LittleShop/Migrations/*.sql 2>/dev/null)" ]; then echo "Found migration files, applying to database..." for migration in LittleShop/Migrations/*.sql; do migration_name=$(basename "$migration") echo "Applying migration: $migration_name" docker run --rm -v littleshop_littleshop_data:/data -v $(pwd)/LittleShop/Migrations:/migrations alpine:latest sh -c " apk add --no-cache sqlite > /dev/null 2>&1 echo 'Creating backup before migration...' cp /data/littleshop-production.db /data/littleshop-production.db.backup-\$(date +%Y%m%d-%H%M%S) 2>/dev/null || true echo 'Applying migration: $migration_name' sqlite3 /data/littleshop-production.db < /migrations/$migration_name echo 'Migration applied successfully' " done else echo "No migration files found, skipping..." fi # Start services with new images echo "Starting services with new images..." docker-compose up -d # Start TeleBot with new image echo "Starting TeleBot with new image..." docker run -d \ --name telebot-service \ --restart unless-stopped \ --network silverpay_silverpay-network \ -e ASPNETCORE_URLS=http://+:5010 \ -e LittleShop__ApiUrl=http://littleshop:5000 \ -e LittleShop__UseTor=false \ -e Privacy__EnableTor=true \ -e Privacy__TorSocksHost=tor-gateway \ -e Privacy__TorSocksPort=9050 \ localhost:5000/telebot:latest # Connect TeleBot to LittleShop network docker network connect littleshop_littleshop-network telebot-service # Wait for startup echo "Waiting for services to start..." sleep 30 # Health check echo "Running health checks..." for i in 1 2 3 4 5 6; do if curl -f -s http://localhost:5100/api/catalog/products > /dev/null 2>&1; then echo "✅ Deployment successful - health check passed" exit 0 fi echo "Health check attempt $i/6 failed, waiting..." sleep 10 done echo "❌ Health check failed after deployment" docker logs littleshop --tail 50 docker logs telebot-service --tail 30 exit 1 ENDSSH - name: Cleanup if: always() run: | rm -f ~/.ssh/deploy_key deploy-preproduction: name: Deploy to Pre-Production (CT109) needs: [build-littleshop, build-telebot] runs-on: ubuntu-latest if: github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main' environment: name: pre-production url: http://ct109.local steps: - name: Checkout code uses: actions/checkout@v4 - name: Download LittleShop image uses: actions/download-artifact@v4 with: name: littleshop-image path: /tmp/docker-images - name: Download TeleBot image uses: actions/download-artifact@v4 with: name: telebot-image path: /tmp/docker-images - name: Load Docker images run: | docker load < /tmp/docker-images/littleshop.tar.gz docker load < /tmp/docker-images/telebot.tar.gz - name: Set up SSH for CT109 run: | mkdir -p ~/.ssh chmod 700 ~/.ssh echo "${{ secrets.CT109_SSH_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -p ${{ secrets.CT109_SSH_PORT }} ${{ secrets.CT109_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: Transfer Docker images to CT109 run: | echo "Copying LittleShop image to CT109..." docker save littleshop:${{ github.sha }} | \ ssh -i ~/.ssh/deploy_key -p ${{ secrets.CT109_SSH_PORT }} ${{ secrets.CT109_USER }}@${{ secrets.CT109_HOST }} \ "docker load" echo "Copying TeleBot image to CT109..." docker save telebot:${{ github.sha }} | \ ssh -i ~/.ssh/deploy_key -p ${{ secrets.CT109_SSH_PORT }} ${{ secrets.CT109_USER }}@${{ secrets.CT109_HOST }} \ "docker load" - name: Deploy to CT109 run: | ssh -i ~/.ssh/deploy_key -p ${{ secrets.CT109_SSH_PORT }} ${{ secrets.CT109_USER }}@${{ secrets.CT109_HOST }} bash -s << 'ENDSSH' set -e export VERSION="${{ github.sha }}" # Tag the images docker tag littleshop:$VERSION littleshop:latest docker tag telebot:$VERSION telebot:latest # Navigate to deployment directory cd /opt/littleshop || mkdir -p /opt/littleshop && cd /opt/littleshop # Stop existing containers echo "Stopping existing containers..." docker stop littleshop telebot-service 2>/dev/null || true docker rm littleshop telebot-service 2>/dev/null || true # Prune unused Docker networks echo "Cleaning up Docker networks..." docker network prune -f || true # Create networks if they don't exist docker network create littleshop-network 2>/dev/null || true docker network create silverpay-network 2>/dev/null || true # Start LittleShop container echo "Starting LittleShop container..." docker run -d \ --name littleshop \ --restart unless-stopped \ --network littleshop-network \ -p 5100:5000 \ -v littleshop-data:/app/data \ -e ASPNETCORE_URLS=http://+:5000 \ -e ASPNETCORE_ENVIRONMENT=Development \ littleshop:latest # Start TeleBot container echo "Starting TeleBot container..." docker run -d \ --name telebot-service \ --restart unless-stopped \ --network silverpay-network \ -e ASPNETCORE_URLS=http://+:5010 \ -e LittleShop__ApiUrl=http://littleshop:5000 \ -e LittleShop__UseTor=false \ telebot:latest # Connect TeleBot to LittleShop network docker network connect littleshop-network telebot-service # Wait for startup echo "Waiting for services to start..." sleep 15 # Health check echo "Running health checks..." for i in 1 2 3 4 5; do if curl -f -s http://localhost:5100/api/catalog/products > /dev/null 2>&1; then echo "✅ Pre-production deployment successful - health check passed" docker ps --filter "name=littleshop" --filter "name=telebot" exit 0 fi echo "Health check attempt $i/5 failed, waiting..." sleep 10 done echo "❌ Health check failed after deployment" echo "LittleShop logs:" docker logs littleshop --tail 50 echo "" echo "TeleBot logs:" docker logs telebot-service --tail 30 exit 1 ENDSSH - name: Cleanup if: always() run: | rm -f ~/.ssh/deploy_key