name: Build and Deploy LittleShop on: push: branches: - main - development tags: - 'v*' workflow_dispatch: env: DOCKER_BUILDKIT: 1 COMPOSE_DOCKER_CLI_BUILD: 1 jobs: deploy-production: name: Deploy to Production VPS (Manual Only) runs-on: ubuntu-latest if: false # Disabled - Manual deployment only via workflow_dispatch environment: name: production url: https://admin.dark.side steps: - 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: 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 }}" # Navigate to deployment directory cd /opt/littleshop # Clone or pull latest code if [ ! -d .git ]; then echo "Cloning repository..." git clone https://git.silverlabs.uk/Jamie/littleshop.git . fi echo "Pulling latest code from git..." git fetch origin git checkout $VERSION || git checkout main # Build images on VPS echo "Building LittleShop image..." docker build --no-cache -t littleshop:$VERSION . docker tag littleshop:$VERSION littleshop:latest docker tag littleshop:$VERSION localhost:5000/littleshop:$VERSION docker tag littleshop:$VERSION localhost:5000/littleshop:latest echo "Building TeleBot image..." docker build --no-cache -t telebot:$VERSION -f Dockerfile.telebot . docker tag telebot:$VERSION telebot: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 # 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) 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: Set up SSH for CT109 run: | echo "Setting up SSH connection..." echo "Host: ${{ secrets.CT109_HOST }}" echo "Port: ${{ secrets.CT109_SSH_PORT }}" echo "User: ${{ secrets.CT109_USER }}" mkdir -p ~/.ssh chmod 700 ~/.ssh echo "Writing SSH key..." echo "${{ secrets.CT109_SSH_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key echo "SSH key size: $(wc -c < ~/.ssh/deploy_key) bytes" echo "Adding host to known_hosts..." ssh-keyscan -p ${{ secrets.CT109_SSH_PORT }} ${{ secrets.CT109_HOST }} >> ~/.ssh/known_hosts 2>&1 || echo "Warning: ssh-keyscan failed" echo "Testing SSH connection..." ssh -i ~/.ssh/deploy_key -p ${{ secrets.CT109_SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.CT109_USER }}@${{ secrets.CT109_HOST }} "echo 'SSH connection successful'" || echo "SSH test failed" echo "SSH setup complete" - 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 }}" export GITEA_TOKEN="${{ secrets.SECRET }}" # Use home directory for deployment DEPLOY_DIR=~/littleshop echo "Using deployment directory: \$DEPLOY_DIR" # Create deployment directory if it doesn't exist mkdir -p "\$DEPLOY_DIR" cd "\$DEPLOY_DIR" # Clone or pull latest code if [ ! -d .git ]; then echo "Cloning repository with authentication..." rm -rf * # Clean any existing files git clone https://oauth2:\${GITEA_TOKEN}@git.silverlabs.uk/Jamie/littleshop.git . else echo "Repository already cloned, pulling latest..." git fetch origin fi echo "Checking out version: \$VERSION" git checkout \$VERSION || git checkout main # Build images on CT109 echo "Building LittleShop image..." docker build --no-cache -t littleshop:\$VERSION . docker tag littleshop:\$VERSION littleshop:latest echo "Building TeleBot image..." docker build --no-cache -t telebot:\$VERSION -f Dockerfile.telebot . docker tag telebot:\$VERSION telebot:latest # 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